Cell長按添加UIMenuController以及cell canBecomeFirstResponder exception的問題

網上有很多這個UIMenuController的教程,以及很多可以替代這個顯示的第三方,例如:DXPopover等

由於項目UI更改需要,改爲系統的UIMenuController顯示。

項目中cell有很多個,但是有一個基類的自定義cell,controller是個聊天室類型的,cell長按後需要出現菜單,點擊menu,實現方法放在controller裏。

下面就講下要做的事:

1.準備:cell裏會有delegate,裏面有單擊、長按的方法,具體實現通過代理在controller裏實現。

2.在controller裏,來到cell長按跳轉過的方法裏:

設置UIMenuController(關於這個的知識可以去百度,這裏只說如何使用)

-(void)longPressMenuViewWithCell:(BaseTableViewCell *)cell atPoint:(CGPoint)position
{
    UIView *keyView = [UIApplication sharedApplication].keyWindow.rootViewController.view;
    
    //爲使其顯示menuController 需要成爲第一響應
    [cell becomeFirstResponder];
    
    UIMenuController *menu = [UIMenuController sharedMenuController];
    
    menu.menuItems = @[
                       [[UIMenuItem alloc] initWithTitle:@"LIAOTIAN" action:@selector(onTapMenuChatButton)], //@""裏面可以國際化
                       [[UIMenuItem alloc] initWithTitle:@"SHANCHU" action:@selector(onTapMenuDeleteButton)]
                       ];
    
    CGFloat menuWidth = menu.menuItems.count * BUTTONDEFAULTWIDTH;
    CGFloat menuHeight = BUTTONDEFAULTHEIGHT;
    CGFloat menuX = (position.x - menuWidth/2); //(position.x > menuWidth/2) ? (position.x - menuWidth/2) : (position.x) ;
    CGFloat menuY = position.y;
    
    CGRect menuCtrlFrame = CGRectMake(menuX, menuY, menuWidth, menuHeight);
    // 菜單最終顯示的位置
    [menu setTargetRect:menuCtrlFrame inView:keyView];
    
    // 顯示菜單
    [menu setMenuVisible:YES animated:YES];
}

3.上面代碼裏  [cell becomeFirstResponder]; 這句話要實現需要進行cell的一些實現,在cell裏:

//重寫該方法,是爲了彈出menuController
-(BOOL)canBecomeFirstResponder
{
    return YES;
}

這裏,有一個crash,在下面會講。


4.很多網上的教程都說要重寫 -(BOOL)canPerformAction:(SEL)action withSender:(id)sender 這個方法,但是這個方法其實解釋是:

Requests the receiving responder to enable or disable the specified command in the user interface.

說明這個方法是在用戶界面中請求啓用或禁用接收響應者指定的命令。直白點說就是當前的第一響應者可以在這個方法裏設置哪些響應方法不執行或者執行。可以獲取系統裏響應的方法

但是由於項目中,我並不需要獲取系統的響應方法,例如:cut、copy、paste等,我這裏用的全部都是自定義的,所以並不需要執行此方法。

如果需要用到這個方法的話,可以根據第一響應者來決定寫在哪裏,如果cell是firstResponder,就寫在cell裏,當然returnYES之前還有別的代碼,請謹慎使用,因爲該方法會在menuview出現或消失的時候都會進行調用,很多次。

5.到這裏,差不多就可以了,當然還需要在controller裏實現點擊這個menuItem的action。

6.如果想要清空的menuItem的話可以

[[UIMenuController sharedMenuController] setMenuItems:@[]];


7.cell canBecomeFirstResponder exception的問題

這個問題是我遇到的比較坑的問題,在程序運行的時候,每次運行到  [cell becomeFirstResponder]; 都會crash。

查了很多地方,終於找到了,地址是:iOS:Error when try becomeFirstResponder call for UIMenuController

Your view controller probably has a property named inputView that is merely a subview, not Your view controller probably has a 

property named inputView that is merely a subview, not an inputView as UIResponder interface expects it to be.

在UIResponder裏有一個inputView,是指當一個對象變成第一響應者的時候顯示的view,但是我項目中也有一個UIView,之前給它命名爲inputView,導致cell變成第一響應的時候,用的是我自定義的這個inputView,導致其crash。

更改方法很簡單:只要將inputView重命名就好。

8.run一下,應該沒什麼問題了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章