一位仁,通過(guò)分類(lèi)向上傳遞信息
這里通過(guò)給UIResponder添加分類(lèi)方法:
- (void)routerInfo:(id)info;
- (void)routerInfo:(id)info sender:(UIResponder *)sender; //帶有發(fā)送者的方法
省去了向上傳遞數(shù)據(jù)的代理方法和block調(diào)用进胯。作者通過(guò)一個(gè)在cell上傳遞數(shù)據(jù)到控制器中的例子展示了nextResonder來(lái)處理事件信息處理的簡(jiǎn)便性逗鸣。這里有個(gè)注意點(diǎn)需要提一下:如果tableView是自定義的并且實(shí)現(xiàn)了- (void)routerInfo:(id)info方法蛋济,接收了數(shù)據(jù)旨袒。那么控制器中就不能響應(yīng)- (void)routerInfo:(id)info方法的事件了察绷。如果控制器還需要處理干签,在tableView中繼續(xù)調(diào)用該方法。
cell中的實(shí)現(xiàn):
@implementation OKTestTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (IBAction)btnClick:(id)sender {
[self.nextResponder routerInfo:self.label.text];
}
@end
tableView中的實(shí)現(xiàn):
@implementation OKTestTableView
//如果tableView中不實(shí)現(xiàn)拆撼,cell的事件就會(huì)向上拋給Controller處理容劳。
- (void)routerInfo:(id)info {
NSLog(@"tableView中的routerInfo");
id tableViewData = nil;
//如果需要向上拋喘沿,那么就繼續(xù)調(diào)用
[self.nextResponder routerInfo:tableViewData];
}
@end
如果tableView中沒(méi)有實(shí)現(xiàn)- (void)routerInfo:(id)info 方法,而控制器中實(shí)現(xiàn)了竭贩,那么控制器會(huì)直接獲取到cell中傳遞的信息蚜印。
控制器中:
- (void)routerInfo:(id)info {
//如果tableView中沒(méi)有實(shí)現(xiàn),控制器就直接獲取cell傳遞的info信息
NSLog(@"控制器的routerInfo:%@",info);
}
二留量,長(zhǎng)按顯示UIMenuController時(shí)窄赋,防止鍵盤(pán)退出
實(shí)現(xiàn)長(zhǎng)按彈出UIMenu的功能,需要在長(zhǎng)按方法中設(shè)置控件(UILabel,UITextField)成為第一響應(yīng)者,并且在canBecome:
- (void)longClick:(UILongPressGestureRecognizer *)longGesture {
if (longGesture.state == UIGestureRecognizerStateBegan) {
// 菜單已經(jīng)打開(kāi)不需重復(fù)操作
UIMenuController *menu=[UIMenuController sharedMenuController];
if (menu.isMenuVisible)return;
//如果要不收起鍵盤(pán)還需要復(fù)寫(xiě)nextResponder方法
// if ([textField isFirstResponder]) {
// textField.inputNextResponder = self;//關(guān)鍵代碼
// }else{
// [self becomeFirstResponder];
// }
//注意要設(shè)置為第一響應(yīng)者
[self becomeFirstResponder];
UIMenuItem *copy = [[UIMenuItem alloc] initWithTitle:@"復(fù)制"action:@selector(copyItem:)];
UIMenuItem *paste = [[UIMenuItem alloc] initWithTitle:@"粘貼" action:@selector(pasteItem:)];
[menu setMenuItems:@[copy,paste]];
[menu setTargetRect:self.bounds inView:self];
[menu setMenuVisible:YES animated:YES];
//如果復(fù)寫(xiě)nextResponder方法楼熄,還要在menu隱藏時(shí)忆绰,移除inputNextResponder
// [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(menuWillHidden) name:UIMenuControllerWillHideMenuNotification object:nil];
}
}
如果是可以輸入的控件需要在鍵盤(pán)彈起時(shí)還能復(fù)制等長(zhǎng)按操作,那么就要增加一個(gè)變量來(lái)保持自己的第一響應(yīng)者身份:
MATextView.h
@interface MATextView : UITextView
@property (nonatomic, weak) UIResponder *inputNextResponder;
@end
MATextView.m
@implementation MATextView
- (UIResponder *)nextResponder {
if (_inputNextResponder != nil)
return _inputNextResponder;
else
return [super nextResponder];
}
//在設(shè)置外部的responder后可岂,就不能執(zhí)行方法
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (self.inputNextResponder != nil) {
return NO;
}
else {
return [super canPerformAction:action withSender:sender];
}
}
@end
需要拷貝的自定義控件里错敢,必須設(shè)置為YES才能添加UIMenu
- (BOOL)canBecomeFirstResponder {
return YES;
}
如果沒(méi)有實(shí)現(xiàn)本方法就只有自定義的item,如果實(shí)現(xiàn)了青柄,就是實(shí)現(xiàn)中的item
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
NSLog(@"%@", NSStringFromSelector(action));
if (action == @selector(cut:)
|| action == @selector(copy:)
|| action == @selector(paste:) || action == @selector(copyItem:)|| action == @selector(pasteItem:)) {
return YES; // YES -> 代表我們只監(jiān)聽(tīng) cut: / copy: / paste:方法
}
return NO; // 除了上面的操作伐债,都不支持
}
如下是照搬代碼供參考,如果添加了inputNextResponder還要將其置空:
- (void)copyBtnWillHidden{
UIView *superView = self.superview.superview.superview;
KFChatToolView *toolView = [superView viewWithTag:kKF5ChatToolViewTag];
if ([toolView isKindOfClass:[KFChatToolView class]]) {
toolView.textView.inputNextResponder = nil;
}
self.chatMessageBackgroundView.highlighted = NO;
[[NSNotificationCenter defaultCenter]removeObserver:self];
}