1

我有一个 UIButton 子类,它执行一些自定义绘图和动画。这一切都很好,花花公子。

但是,我的大多数按钮通过调用 [selfdismissViewControllerAnimated] 的超级视图来关闭当前视图,一旦模型确认按钮按下应该完成的任何事情都已实际完成,我希望有一个延迟以允许动画在关闭视图之前完成。

我能够轻松地在 touchesEnded 上为 UIButton 子类设置动画,然后调用 [super touchesEnded],它工作正常,只是它不会让我的动画在关闭视图之前完成。像这样:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"transform.foo"];
    //set up myAnimation's properties

    [self.layer addAnimation:shakeAnimation forKey:nil];
    [super touchesEnded:touches withEvent:event]; //works! but no delay
}

我第一次尝试创建延迟是使用 CATransaction,如下所示:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{   
    CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"transform.foo"];
    //set up myAnimation's properties

    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        [super touchesEnded:touches withEvent:event]; //doesn't seem to do anything :-/
    }];
    [self.layer addAnimation:shakeAnimation forKey:nil];
    [CATransaction commit];
}

据我所知,它正在执行 CATransaction 的 completionBlock,但它什么也没做。

我还尝试将 touchesEnded 中的触摸和事件参数分配给属性和全局变量,然后在另一个由 NSTimer 调用的方法中执行 [super touchesEnded]。代码执行的地方似乎也发生了同样的事情,但是我对 [super touchesEnded] 的调用没有做任何事情。

我已经在网上挖了几个小时。添加了来自 UIResponder 的其他触摸方法的存根,其中仅包含 [super touches...]。尝试为 NSTimer 以不同方式调用的方法设置我的全局变量(我很可能遗漏了一些关于全局变量的东西......)。这个按钮是由故事板创建的,但我已经将类设置为我的自定义类,所以我不认为 UIButton 的 +(UIButton *)buttonWithType 方法会影响这一点。

我错过了什么?是否有一些小事情我忘记了,或者没有办法延迟从 UIButton 子类对 [super touchesEnded] 的调用?

4

1 回答 1

1

我无法解决这个问题,只能找到解决方法。

我解决这个问题的最后一次尝试是弄清楚完成块内的 [super touchesEnded...] 是否正在一个与它在完成块之外执行的线程不同的线程中执行......并且不,它们似乎都是主线程(Apple 关于 CATransaction 的文档确实声明其 completionBlock 始终在主线程中运行)。

因此,如果其他人对此表示反对,这是我不太优雅的解决方案:

1.) 在我的 UIButton 子类中,我创建了一个名为 containsVC 的弱属性。

2.)在每个使用自定义按钮类的(呃)VC中,我必须这样做:

@implemenation VCThatUsesCustomButtonsOneOfWayTooMany

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.firstCustomButton.containingVC = self;
    self.secondCustomButton.containingVC = self;
    self.thirdCustomButton.containingVC = self;
    ....
    self.lastCustomButton.containingVC = self;
    //you're probably better off using an IBOutletColletion and NSArray's makeObjectPerformSelector:withObject...
}

@end

3.)然后在我的自定义 UIButton 类中,我有这样的东西:

-(void)animateForPushDismissCurrView
{
    CAAnimation *buttonAnimation = ...make animation

    [CATransaction begin];
    [CATransaction setCompletionBlock:^{

        [self.containingVC performSegueWithIdentifier:@"segueID" sender:self.containingVC];

    }];
    [self.layer addAnimation:buttonAnimation forKey:nil];
    [CATransaction commit];
}

4.)然后在用户当前正在与之交互的任何 VC 中,在确保按钮完成了它应该做的任何事情之后(在我的情况下,它会检查模型以确认已进行相关更改),每个按钮都有调用 [someCustomButton animateForPushDismissCurrView] 然后动画按钮按下,然后触发实际关闭视图的 UIStoryboardSegue。

显然,这将有助于更深入,而不仅仅是展开,但您需要在自定义按钮的 -(void)animateForPush 方法或完全单独的方法中添加额外的逻辑。

同样,如果我在这里遗漏了什么,我很想知道它是什么。为了完成看似简单的任务,这似乎是一个荒谬的圈数。

最后,最重要的是,如果它不能与 CATransaction 的完成块中的 [super touchesEnded...] 方法一起使用,我想知道为什么。我怀疑它与线程或 Objective-C 的 super 关键字的怪异有关。

于 2015-09-02T01:18:50.320 回答