ios7開始 蘋果增加了頁面 右滑返回的效果;具體的是以UINavigationController為容器的ViewController間右滑切換頁面。代碼里的設(shè)置是:self.navigationController.interactivePopGestureRecognizer.enabled = YES;(default is YES)
可以看到蘋果給navigationController添加了一個手勢(具體為UIScreenEdgePanGestureRecognizer(邊緣手勢,同樣是ios7以后才有的)),就是利用這個手勢實現(xiàn)的 ios7的側(cè)滑返回。問題1:然而事情并非我們想的那么簡單。
1.當(dāng)我們用系統(tǒng)的UINavigationController,并且也是利用系統(tǒng)的navigateBar的時候,是完全沒有問題的2.但是當(dāng)我們沒有用系統(tǒng)的navigateBar或者自定義了返回按鈕的時候,這個時候 右滑返回是失效的。解決(問題1)辦法:對于這種失效的情況,考慮到interactivePopGestureRecognizer也有delegate屬性,替換默認(rèn)的self.navigationController.interactivePopGestureRecognizer.delegate來配置右滑返回的表現(xiàn)也是可行的。我們可以在主NavigationController中設(shè)置一下:self.navigationController.interactivePopGestureRecognizer.delegate =(id)self問題2:但是出現(xiàn)很多問題,比如說在rootViewController的時候這個手勢也可以響應(yīng),導(dǎo)致整個程序頁面不響應(yīng);push了多層后,快速的觸發(fā)兩次手勢,也會錯亂解決(問題2)辦法:
@interface NavRootViewController : UINavigationController
@property(nonatomic,weak) UIViewController* currentShowVC;
@end
@implementation NavRootViewController-(id)initWithRootViewController:(UIViewController *)rootViewController{
NavRootViewController* nvc = [super initWithRootViewController:rootViewController];
self.interactivePopGestureRecognizer.delegate = self;
nvc.delegate = self;return mvc;
}?
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
}
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if (navigationController.viewControllers.count == 1)self.currentShowVC = Nil;elseself.currentShowVC = viewController;
}?
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if (gestureRecognizer == self.interactivePopGestureRecognizer) {return (self.currentShowVC == self.topViewController); //the most important}return YES;
}?
@end
借鑒了別人的方法:具體是通過 獲取當(dāng)前pushView棧里的當(dāng)前顯示的VC,根據(jù)這個VC來決定 是否開啟手勢(如果currentShowVC 是當(dāng)前顯示的,則開啟手勢;如果 currentShowVC為nil,則代表在主頁面,關(guān)閉手勢)注:當(dāng)時試了一種方法 就是滑動的時候來回設(shè)置 interactivePopGestureRecognizer的delegate;發(fā)現(xiàn) 會有crash,原因就是 因為 我把 當(dāng)前顯示的VC設(shè)置為了這個手勢的delegate,但當(dāng)這個VC消失的時候,這個delegate便被釋放了,導(dǎo)致crash至此,覺得ios7上的右滑返回大功告成了,心里正happy,媽蛋,發(fā)現(xiàn)了一個可恥的bug:UIScrollView 上 右滑返回的手勢失靈了,靠!?。。。?!
問題三:UIScrollView上手勢失靈:經(jīng)研究,發(fā)現(xiàn)是UIScrollView上已經(jīng)添加了 panGestureRecognizer(滑動)手勢ios7側(cè)滑返回解決(問題三)辦法:參考:http://www.cnblogs.com/lexingyu/p/3702742.html【
解決方案】蘋果以UIGestureRecognizerDelegate的形式,支持多個UIGestureRecognizer共存。其中的一個方法是:1 // called when the recognition of one of gestureRecognizer or otherGestureRecognizer would be blocked by the other 2 // return YES to allow both to recognize simultaneously. the default implementation returns NO (by default no two gestures can be recognized simultaneously) 3 // 4 // note: returning YES is guaranteed to allow simultaneous recognition. returning NO is not guaranteed to prevent simultaneous recognition, as the other gesture's delegate may return YES 5 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; 一句話總結(jié)就是此方法返回YES時,手勢事件會一直往下傳遞,不論當(dāng)前層次是否對該事件進(jìn)行響應(yīng)。?
@implementation UIScrollView (AllowPanGestureEventPass)- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{? ??
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]? ? ? ? && [otherGestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]])? ? {
? ? ? ? return YES;? ?
?}? ? else? ? {?
?? ? ? return? NO;? ?
?}
}
事實上,對UIGestureRecognizer來說,它們對事件的接收順序和對事件的響應(yīng)是可以分開設(shè)置的,即存在接收鏈和響應(yīng)鏈。接收鏈如上文所述,和UIView綁定,由UIView的層次決定接收順序。而響應(yīng)鏈在apple君的定義下,邏輯出奇的簡單,只有一個方法可以設(shè)置多個gestureRecognizer的響應(yīng)關(guān)系:// create a relationship with another gesture recognizer that will prevent this gesture's actions from being called until otherGestureRecognizer transitions to UIGestureRecognizerStateFailed // if otherGestureRecognizer transitions to UIGestureRecognizerStateRecognized or UIGestureRecognizerStateBegan then this recognizer will instead transition to UIGestureRecognizerStateFailed // example usage: a single tap may require a double tap to fail - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;每個UIGesturerecognizer都是一個有限狀態(tài)機(jī),上述方法會在兩個gestureRecognizer間建立一個依托于state的依賴關(guān)系,當(dāng)被依賴的gestureRecognizer.state = failed時,另一個gestureRecognizer才能對手勢進(jìn)行響應(yīng)。所以,只需要[_scrollView.panGestureRecognizer requireGestureRecognizerToFail:screenEdgePanGestureRecognizer];
?- (UIScreenEdgePanGestureRecognizer *)screenEdgePanGestureRecognizer{? ? UIScreenEdgePanGestureRecognizer *screenEdgePanGestureRecognizer = nil;? ? if (self.view.gestureRecognizers.count > 0)? ? {?
?? ? ? for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers)? ? ? ? {?
?? ? ? ? ? if ([recognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]])? ? ? ? ? ? {?
?? ? ? ? ? ? ? screenEdgePanGestureRecognizer = (UIScreenEdgePanGestureRecognizer *)recognizer;? ? ? ? ? ? ? ??
break;? ? ? ? ? ? }? ? ? ? }? ? }? ??
return screenEdgePanGestureRecognizer;
}
參考:牛逼 解決了iOS7下滑動返回與ScrollView共存http://www.cnblogs.com/lexingyu/p/3702742.html更牛逼? 解決了interactivePopGestureRecognizer.delegate 的 釋放導(dǎo)致crash的問題http://www.2cto.com/kf/201401/272886.html