#ios #uisplitviewcontroller #xib #uigesturerecognizer #nib
#iOS #uisplitviewcontroller #xib #uigesturerecognizer #nib
Вопрос:
Мне было интересно использовать подкласс UIGestureRecognizer (UILongPressGestureRecognizer) в подклассе ViewController, который у меня был. Мой ViewController имеет UIToolbar, и программно я могу создать экземпляр UILongPressGestureRecognizer, прикрепленный к UIToolbar, и заставить все работать. Мой ViewController использует протокол UIGestureRecognizerDelegate. В ViewController у меня есть:
//My ViewController.h
@interface MyViewController: UIViewController<UIGestureRecognizerDelegate>
/* ... */
@property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
@property (nonatomic, retain) IBOutlet UILongPressGestureRecognizer *longPressGesureRecognizer;
/* ... */
- (IBAction)handleGesture;
@end
Затем работает следующий код:
- (void)viewDidLoad
{
[super viewDidLoad];
//configure UILongPressGestureRecognizer
if(self.longPressGesureRecognizer == nil){
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture)];
longPress.minimumPressDuration = 1.5;
longPress.numberOfTouchesRequired = 1;
longPress.delegate = self;
self.longPressGesureRecognizer = longPress;
[self.toolbar addGestureRecognizer:self.longPressGesureRecognizer];
[longPress release];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return YES;
}
- (IBAction)handleGesture{
NSLog(@"Got a gesture!");
}
Я не думал, что мне действительно нужен UILongPressGestureRecognizer в моем контроллере просмотра. Когда я попытался создать его полностью в файле MyViewController.xib, я сделал следующее, используя XCode 4.2
- Перетащил UILongPressRecognizer на мой UIToolbar в xib (прикрепленный к панели инструментов в MyViewController).
- Установите свойство делегата UILongPressRecognizer для владельца файла
- Установите свойство selector в сообщение handleGesture MyViewController.
Когда я запускаю приложение в симуляторе, я вылетаю, что приводит к следующей ошибке gdb в консоли:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILongPressGestureRecognizer initWithCoder:]: unrecognized selector sent to instance
Очевидно, что UILongPressGestureRecognizer initWithCoder: не выполняется, но мне интересно, какой правильный способ настройки UIGestureRecognizer находится в файле xib. В XCode есть жесты, и я подключил его к представлению. Я не понимаю, что я делаю не так. Все ссылки, которые я видел в UIGestureRecognizer, включая ссылку на класс UIGestureRecognizer от Apple, всегда используют UIGestureRecognizer из кода. Я не видел примера, использующего только файл xib для его настройки.
Меня не слишком беспокоит эта проблема, потому что я могу справиться с ней с помощью кода в ViewController, но я не понимаю, почему XCode позволяет добавлять распознаватели жестов в nib, если UILongPressGestureRecognizer и / или UIGestureRecognizer не соответствуют протоколу NSCoding и будет вызван initWithCoder. Моя интуиция подсказывает, что проблема с моей стороны, а не с Apple, но я бы хотел понять, что происходит не так.
Спасибо!
Обновить
Кажется, я вижу такое поведение только при тестировании, когда использую UISplitViewController. Если я создаю проект на основе ViewController, UIGestureRecognizer работает должным образом. Если я добавляю распознаватель жестов в DetailView приложения UISplitViewController, я получаю сбой, подобный этому:
2011-11-03 10:17:55.873 GestureSplitViewTest[1143:b603] -[UILongPressGestureRecognizer initWithCoder:]: unrecognized selector sent to instance 0x59696b0
2011-11-03 10:17:55.877 GestureSplitViewTest[1143:b603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILongPressGestureRecognizer initWithCoder:]: unrecognized selector sent to instance 0x59696b0'
*** Call stack at first throw:
(
0 CoreFoundation 0x011b15a9 __exceptionPreprocess 185
1 libobjc.A.dylib 0x01305313 objc_exception_throw 44
2 CoreFoundation 0x011b30bb -[NSObject(NSObject) doesNotRecognizeSelector:] 187
3 CoreFoundation 0x01122966 ___forwarding___ 966
4 CoreFoundation 0x01122522 _CF_forwarding_prep_0 50
5 UIKit 0x002fe9fd UINibDecoderDecodeObjectForValue 2592
6 UIKit 0x002fe2f5 UINibDecoderDecodeObjectForValue 792
7 UIKit 0x002ff6ac -[UINibDecoder decodeObjectForKey:] 398
8 UIKit 0x00214979 -[UIRuntimeConnection initWithCoder:] 212
9 UIKit 0x003d34a8 -[UIRuntimeOutletCollectionConnection initWithCoder:] 64
10 UIKit 0x002fe9fd UINibDecoderDecodeObjectForValue 2592
11 UIKit 0x002fe2f5 UINibDecoderDecodeObjectForValue 792
12 UIKit 0x002ff6ac -[UINibDecoder decodeObjectForKey:] 398
13 UIKit 0x00213c36 -[UINib instantiateWithOwner:options:] 804
14 UIKit 0x00215ab7 -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] 168
15 UIKit 0x000cb628 -[UIViewController _loadViewFromNibNamed:bundle:] 70
16 UIKit 0x000c9134 -[UIViewController loadView] 120
17 UIKit 0x000c900e -[UIViewController view] 56
18 UIKit 0x000c7482 -[UIViewController contentScrollView] 42
19 UIKit 0x000d7f25 -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] 48
20 UIKit 0x000d6555 -[UINavigationController _layoutViewController:] 43
21 UIKit 0x000d7870 -[UINavigationController _startTransition:fromViewController:toViewController:] 524
22 UIKit 0x000d232a -[UINavigationController _startDeferredTransitionIfNeeded] 266
23 UIKit 0x001ed2e9 -[UILayoutContainerView layoutSubviews] 226
24 QuartzCore 0x01888a5a -[CALayer layoutSublayers] 181
25 QuartzCore 0x0188addc CALayerLayoutIfNeeded 220
26 QuartzCore 0x018300b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE 310
27 QuartzCore 0x01831294 _ZN2CA11Transaction6commitEv 292
28 UIKit 0x0001b9c9 -[UIApplication _reportAppLaunchFinished] 39
29 UIKit 0x0001be83 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] 690
30 UIKit 0x00026617 -[UIApplication handleEvent:withNewEvent:] 1533
31 UIKit 0x0001eabf -[UIApplication sendEvent:] 71
32 UIKit 0x00023f2e _UIApplicationHandleEvent 7576
33 GraphicsServices 0x00eb2992 PurpleEventCallback 1550
34 CoreFoundation 0x01192944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ 52
35 CoreFoundation 0x010f2cf7 __CFRunLoopDoSource1 215
36 CoreFoundation 0x010eff83 __CFRunLoopRun 979
37 CoreFoundation 0x010ef840 CFRunLoopRunSpecific 208
38 CoreFoundation 0x010ef761 CFRunLoopRunInMode 97
39 UIKit 0x0001b7d2 -[UIApplication _run] 623
40 UIKit 0x00027c93 UIApplicationMain 1160
41 GestureSplitViewTest 0x0000234a main 170
42 GestureSplitViewTest 0x00002295 start 53
)
terminate called throwing an exceptionsharedlibrary apply-load-rules all
Current language: auto; currently objective-c
(gdb)
Комментарии:
1. Спасибо за этот вопрос, у меня была такая же проблема. Кто-нибудь сообщал о проблеме с радаром?
Ответ №1:
Вы убедились, что не используете iOS 4.3 SDK вместо iOS 5 SDK?
Я потратил добрых 30 минут, чтобы выяснить, что я использовал неправильный SDK.
Комментарии:
1. Я провел быстрый тест и подтвердил, что вы были правы. Приложение загружается с помощью UISplitViewController с использованием SDK 5.0, но не SDK 4.3, и работает нормально, независимо от того, используется ли обычный подкласс UIViewController.
Ответ №2:
Для этого требуется только разместить UILongPressRecognizer, а затем настроить IBAction, например
In H: -(IBAction)LongPress;
In M: -(IBAction)LongPress {
NSLog(@"Good!");
}
Последний раз подключите его к UILongPressRecognizer. Готово!
Протестировано и работает.
Надеюсь, это поможет!
Комментарии:
1. Я попробовал это снова с пустым проектом, и это сработало, как вы сказали. Я добавил UILongPressGestureRecognizer, перетащив UIToolbar только в nib, и подключил к нему функцию IBAction в моем ViewController, и она работала, как ожидалось. Я немного углублюсь в свой другой проект, чтобы попытаться понять, в чем дело, но я думаю, что это работает так, как ожидалось. Надеюсь, в ближайшее время.
2. Модифицировал вопрос с учетом новых знаний о том, что это происходит в приложении на основе UISplitViewController.
Ответ №3:
Не рекомендуется менять версию SDK, как кто-то ответил, из-за более позднего распространения. Он не сможет быть установлен на устройствах без 5.0 SDK.
Вместо этого не добавляйте его в xib, вместо этого напишите код. Вот пример кода жеста салфетки
Запишите эту часть кода где-нибудь при инициализации представления, например, Init
UISwipeGestureRecognizer *_swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
[_swipeGestureRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[_swipeGestureRecognizer setNumberOfTouchesRequired:1];
[self addGestureRecognizer:_swipeGestureRecognizer];
А также напишите это для обработки действия жеста
- (void)swipe:(id)sender { ... }