นอกเหนือจากคำตอบของ Brad Larson : สำหรับเลเยอร์ที่กำหนดเอง (ที่คุณสร้างขึ้น) คุณสามารถใช้การมอบหมายแทนการปรับเปลี่ยนเลเยอร์ของactions
พจนานุกรม วิธีการนี้เป็นแบบไดนามิกมากขึ้นและอาจมีประสิทธิภาพมากขึ้น และอนุญาตให้ปิดใช้งานภาพเคลื่อนไหวโดยนัยทั้งหมดโดยไม่ต้องแสดงรายการคีย์ที่สามารถเคลื่อนไหวได้ทั้งหมด
น่าเสียดายที่มันเป็นไปไม่ได้ที่จะใช้UIView
s เป็นตัวแทนเลเยอร์ที่กำหนดเองเพราะแต่ละคนUIView
เป็นตัวแทนของเลเยอร์ของตัวเองอยู่แล้ว แต่คุณสามารถใช้คลาสตัวช่วยอย่างนี้:
@interface MyLayerDelegate : NSObject
@property (nonatomic, assign) BOOL disableImplicitAnimations;
@end
@implementation MyLayerDelegate
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
if (self.disableImplicitAnimations)
return (id)[NSNull null]; // disable all implicit animations
else return nil; // allow implicit animations
// you can also test specific key names; for example, to disable bounds animation:
// if ([event isEqualToString:@"bounds"]) return (id)[NSNull null];
}
@end
การใช้งาน (ภายในมุมมอง):
MyLayerDelegate *delegate = [[MyLayerDelegate alloc] init];
// assign to a strong property, because CALayer's "delegate" property is weak
self.myLayerDelegate = delegate;
self.myLayer = [CALayer layer];
self.myLayer.delegate = delegate;
// ...
self.myLayerDelegate.disableImplicitAnimations = YES;
self.myLayer.position = (CGPoint){.x = 10, .y = 42}; // will not animate
// ...
self.myLayerDelegate.disableImplicitAnimations = NO;
self.myLayer.position = (CGPoint){.x = 0, .y = 0}; // will animate
บางครั้งมันก็สะดวกที่จะมีตัวควบคุมของมุมมองในฐานะตัวแทนสำหรับ sublayers ที่กำหนดเองของมุมมอง; ในกรณีนี้ไม่จำเป็นต้องมีคลาสผู้ช่วยคุณสามารถใช้actionForLayer:forKey:
วิธีการภายในคอนโทรลเลอร์
หมายเหตุสำคัญ: อย่าพยายามแก้ไขผู้รับมอบสิทธิ์ของUIView
เลเยอร์ต้นแบบ (เช่นเพื่อเปิดใช้งานภาพเคลื่อนไหวโดยนัย) - สิ่งเลวร้ายจะเกิดขึ้น :)
หมายเหตุ: หากคุณต้องการเคลื่อนไหวเลเยอร์การวาดใหม่ (ไม่ปิดใช้งานภาพเคลื่อนไหวสำหรับ) จะไม่มีประโยชน์ในการวาง[CALayer setNeedsDisplayInRect:]
สายในCATransaction
เพราะการวาดภาพจริงอาจเกิดขึ้นได้ในบางครั้งในภายหลัง แนวทางที่ดีคือการใช้คุณสมบัติที่กำหนดเองดังที่อธิบายไว้ในคำตอบนี้
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });