2012-08-10 11 views
6

Ich habe einige Leistungsprobleme mit etwas Code, den ich für die Größenänderung eines CALayer mit Touch geschrieben habe. Es funktioniert gut, aber die Animation ist weit von Snappy genug und hinkt hinter dem Touch-Standort.CALayer Resize ist langsam

CGPoint startPoint; 
CALayer *select; 

- (CGRect)rectPoint:(CGPoint)p1 toPoint:(CGPoint)p2 { 
    CGFloat x, y, w, h; 
    if (p1.x < p2.x) { 
     x = p1.x; 
     w = p2.x - p1.x; 
    } else { 
     x = p2.x; 
     w = p1.x - p2.x; 
    } 
    if (p1.y < p2.y) { 
     y = p1.y; 
     h = p2.y - p1.y; 
    } else { 
     y = p2.y; 
     h = p1.y - p2.y; 
    } 
    return CGRectMake(x, y, w, h); 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *t1 = [[[event allTouches]allObjects]objectAtIndex:0]; 
    CGPoint loc = [t1 locationInView:self]; 
    startPoint = loc; 
    lastPoint = CGPointMake(loc.x + 5, loc.y + 5); 

    select = [CALayer layer]; 
    select.backgroundColor = [[UIColor blackColor]CGColor]; 
    select.frame = CGRectMake(startPoint.x, startPoint.y, 5, 5); 
    [self.layer addSublayer:select]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *t1 = [[[event allTouches]allObjects]objectAtIndex:0]; 
    CGPoint loc = [t1 locationInView:self]; 
    select.bounds = [self rectPoint:startPoint toPoint:loc]; 
} 

Gibt es einen besseren Weg, dies zu erreichen?

Antwort

24

Die Verzögerung liegt daran, dass Sie die Eigenschaft bounds der Ebene ändern, die eine animierbare Eigenschaft darstellt.

Mit CALayers (die CA steht für Core Animation ...) wird jede Änderung an einer animierbaren Eigenschaft standardmäßig animiert. Dies wird als implizite Animation bezeichnet. Die Standardanimation dauert 0,25 Sekunden. Wenn Sie sie häufig aktualisieren, z. B. während der Bearbeitung von Berührungen, summiert sich dies und verursacht eine sichtbare Verzögerung.

in Swift
[CATransaction begin]; 
[CATransaction setDisableActions:YES]; 
layer.bounds = whatever; 
[CATransaction commit]; 
+2

hätte mir mindestens einen Tag gedauert, um das selbstständig herauszufinden, danke stack + jrturton. –

1

akzeptierte Antwort 3/4:

Um dies zu verhindern, müssen Sie eine Animation Transaktion erklären, deaktivieren Sie die implizite Animationen, dann die Eigenschaften ändern

CATransaction.begin() 
CATransaction.setDisableActions(true) 
layer.bounds = whatever 
CATransaction.commit() 

erwähnenswert, dass Dies gilt auch für .frame Eigenschaften, z. B. wenn Sie die Größe einer AVPlayerLayer ändern:

override func layoutSubviews() { 
    CATransaction.begin() 
    CATransaction.setDisableActions(true) 
    playerLayer.frame = self.bounds 
    CATransaction.commit() 
}