Подкласс 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.