2014-09-03 44 views
2

我有一个小UIView在一个盒子里弹跳。我正在添加一个瞬时模式。推。事实上,我添加了很多推 - 5赫兹或更多。我应该removeBehavior一个UIPushBehavior - 我加入很多推

奥秘:

(1)我必须removeBehavior ???? if if .. when?!? “之后”一个“瞬间”? (2)是否UIPushBehaviorModeInstantaneous是一个特殊情况,并且您不必(或不能)删除这些??????????????????????????UIPushBehaviorModeInstantaneous是一种特殊情况,您不必(也不能)

(3)当你addBehavior:那..保留?! UIPushBehavior?要么?? WTF?

(4)我似乎无法在任何地方找到这些方面!

-(void)pushMeRight:(CGFloat)mag 
    { 
    if (self.bounceAnimator == nil) return; 
    NSLog(@"...........push me right %.2f", mag); 

    UIPushBehavior *pushRight = [[UIPushBehavior alloc] 
      initWithItems:@[self] 
      mode:UIPushBehaviorModeInstantaneous]; 

    pushRight.magnitude = mag; 
    pushRight.angle = radians(0); // (NB, 0 is right, 90 is down) 
    [self.bounceAnimator addBehavior:pushRight]; 
    } 

{注:我只是每次我需要一个ALLOC的UIPushBehavior 。请注意,如果您尝试使用“只有一个”作为属性,那么不起作用。事实上,罗布解释了为什么下面。}


解决方案

后极其广泛的测试,我们发现,罗布的“第二”的解决方案,使用.action,基本上是完美的。

同样庞大的测试后,我们会非常强烈建议下面的代码,是的,真的,“解决方案”,只有这样,才能编写重复推..谢天谢地罗布:/

-(void)pushAllUp:(CGFloat)mag 
    { 
    if (self.bounceAnimator == nil) return; 
    for (UIView *pushme in self.subviews) 
     { 
     UIPushBehavior *pp = 
     [[UIPushBehavior alloc]initWithItems:@[ pushme ] 
      mode:UIPushBehaviorModeInstantaneous]; 

     pp.magnitude = mag; 
     pp.angle = radians(270); // (NB, 0 is right, 90 is down) 

     UIPushBehavior __weak *weakPP = pp; 
     pp.action = ^{ if (!weakPP.active) 
      [self.bounceAnimator removeBehavior:weakPP];}; 

     [self.bounceAnimator addBehavior:pp]; 
     } 
    } 

回答

6

在回答你的问题:

  1. 是的,你还说UIPushBehavior正确。

  2. 您在技术上不必呼叫removeBehavior即时推送,因为一旦发生瞬时推送,行为将关闭其状态active

    话虽如此,我会倾向于消除这种行为,因为您在其他方面占用了内存,动画师仍然对这些非瞬时推送行为保持强烈的参照。 (这很容易通过记录动画师的behaviors属性进行验证,该属性是它追踪的所有行为的数组。)最终可能会有一个与性能相关的问题,以便它遍历所有这些非active行为,尽管我怀疑内存问题可能更重要。

    但与其他行为(例如UISnapBehavior)保持active不同,您不必担心延迟的瞬时推送行为会持续影响其添加的项目。

  3. 他们没有“过期”,本身,但是,是的,他们很快去的NO一个active状态。

  4. 是的,当您向动画师添加行为时,动画师会保留对其的强烈引用,直到您移除该行为。

就我个人而言,我倾向于在添加它后删除行为。因为它的瞬间,其去除的时机是不是非常关键的,你可以做的简单的东西:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
    [self.animator removeBehavior:push]; 
}); 

或者,你可以建立一个action是删除它。

UIPushBehavior *push = [[UIPushBehavior alloc] initWithItems:self.items mode:UIPushBehaviorModeInstantaneous]; 
push.pushDirection = ... 

UIPushBehavior __weak *weakPush = push; // avoid strong reference cycle 
push.action = ^{ 
    if (!weakPush.active) { 
     [self.animator removeBehavior:weakPush]; 
    } 
}; 

[self.animator addBehavior:push]; 
+0

感谢您的支持!我必须做一些测试,看看你什么时候可以消除这种行为:这种行为是否发生在那行代码上,然后呢?或者仅在例程结束时(或者更像是一个框架驱动的游戏引擎)。我会发现... – Fattie 2014-09-08 14:48:08

+0

动画师不会执行行为,直到您将主线程退回到运行循环(即您的例程退出)。所以,确保你永远不会阻塞主线程。 (这是一条通用规则,因此请确保您避免在任何时候阻止主线程,否则您将对动画制作者执行动画的能力产生不利影响。)但是,您必须等待动画制作人员拿起行为就是为什么你不只是立即删除行为,而是异步地删除它(即在一些延迟或更好的时候,当'action'块被调用时)。 – Rob 2014-09-08 15:22:11

+0

好的,你已经回答了这个问题 - 太棒了! – Fattie 2014-09-08 15:27:25