Подкласс UIButton: вызов [super touchesEnded:] после завершения пользовательских анимаций

У меня есть подкласс UIButton, который делает некоторые пользовательские рисунки и анимации. Это все работает отлично и денди.

Тем не менее, большинство моих кнопок отклоняют текущий вид с помощью своего суперпредставления, вызывающего [self dismissViewControllerAnimated], как только подтверждается моделью, что все, что предполагалось при нажатии кнопки, действительно было выполнено, и я хочу, чтобы была задержка, чтобы позволить анимацию завершить до отклонения зрения.

Я могу достаточно легко анимировать подкласс UIButton на touchesEnded, а затем вызвать [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, но ничего не делает.

Я также попытался присвоить touch и аргументы события из touchesEnded как свойствам, так и глобальным переменным, а затем выполнить [super touchesEnded] в другом методе, вызываемом NSTimer. Похоже, то же самое происходит и при выполнении кода, но мой вызов [super touchesEnded] ничего не делает.

Я копался в Интернете часами. Добавлены заглушки других методов касания из UIResponder, которые просто содержат [супер касания...]. Попытался настроить мои глобальные переменные для метода, вызываемого NSTimer, по-другому (я вполне могу что-то упустить в отношении глобальных переменных...). Эта кнопка создается раскадровкой, но я установил класс в свой пользовательский класс, поэтому я не думаю, что метод buttonWithType UIButton +(UIButton *) влияет на это.

Что мне не хватает? Есть ли какая-то мелочь, о которой я забыл, или просто нет способа отложить вызов [super touchesEnded] из подкласса UIButton?

1 ответ

Я не смог решить это, только найти способ обойти это.

Мой последний шаг при решении этой проблемы состоял в том, чтобы выяснить, выполнялось ли [super touchesEnded...] внутри блока завершения в потоке, который отличался от потока, в котором он выполнялся, когда он находился вне блока завершения... и нет, оба они, по-видимому, являются основным потоком (документация Apple по CATransaction действительно утверждает, что ее Завершение всегда выполняется в основном потоке).

Так что на тот случай, если кто-то ударится об это, вот мое не слишком элегантное решение:

1.) В моем подклассе UIButton я создал слабое свойство, которое называется содержащим VC.

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.) Затем в любом виртуальном средстве, с которым в данный момент взаимодействует пользователь, убедившись, что кнопка сделала то, что должна была сделать (в моем случае она проверяет модель, чтобы убедиться, что соответствующее изменение было сделано), каждая кнопка имеет вызвать [someCustomButton animateForPushDismissCurrView], который затем анимирует нажатие кнопки и затем запускает UIStoryboardSegue, который фактически отклоняет представление.

Очевидно, это будет работать для углубления, а не просто для раскручивания, но вам понадобится дополнительная логика в методе (void)animateForPush пользовательской кнопки или в отдельном методе полностью.

Опять же, если я что-то упустил здесь, я бы хотел знать, что это такое. Это кажется абсурдным количеством прыжков, через которые нужно прыгнуть, чтобы выполнить то, что кажется простой задачей.

Наконец, и самое главное, если он просто не будет работать с методом [super touchesEnded...] в блоке завершения CATransaction, я хотел бы знать, ПОЧЕМУ. Я подозреваю, что это как-то связано с потоками или странностью, которая является супер-ключевым словом Objective-C.

Другие вопросы по тегам