`
WorldMatrix
  • 浏览: 5207 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Fuck self.delegate = self

 
阅读更多

故事背景如下,我有一个UITextField的子类MyTextField,创建了MyTextField的实例tf。我希望tf对应的键盘显示done按钮。代码如下:

 1 @interface MyTextField : UITextField
 2 @end
 3 
 4 MyTextField* tf = [[MyTextField alloc] initWithFrame:someframe];
 5 tf.returnKeyType = UIReturnKeyDone;

然后我希望,当done被按下的时候,键盘关闭,通常的做法是给TextField一个delegate,监听textFieldShouldReturn,当done被按下时,会回调delegate的textFieldShouldReturn方法,代码如下:

 8 @interface TextFieldDelegate : NSObject<UITextFieldDelegate>
 9 @end
10 
11 @implementation TextFieldDelegate
12 - (BOOL)textFieldShouldReturn:(UITextField *)textField
13 {
14     [textField resignFirstResponder];
15     return YES;
16 }
17 @end
18 
19 tf.delegate = [[TextFieldDelegate alloc] init];

这是比较常规的做法,但是要新建一个类,新建一个对象,用完了还要释放这个对象,成本很大。这时我产生了个偷懒的想法,我自己的事情我就自己做吧,我做我自己的代理,self.delegate = self。代码如下,

23 @interface MyTextField : UITextField<UITextFieldDelegate>
24 @end
25 
26 @implementation MyTextField
27 - (BOOL)textFieldShouldReturn:(UITextField *)textField
28 {
29     [textField resignFirstResponder];
30     return YES;
31 }
32 @end
33 
34 MyTextField* tf = [[MyTextField alloc] initWithFrame:someframe];
35 tf.returnKeyType = UIReturnKeyDone;
36 tf.delegate = tf;
37 

干净利落,然后恶梦就开始了。运行这段代码,点击输入框,先是程序就再不响应了,XCode也没什么有用的提示,试一两次,XCode也不再响应了。


这个问题不是我自己解决的,我求助了google。在MyTextField的实现中加入以下函数,

39 - (BOOL)respondsToSelector:(SEL)aSelector
40 {
41     return [super respondsToSelector:aSelector];
42 }

在这个函数中打个断点,再次执行,程序运行到断点后继续执行,会不断的运行到这个断点,然后不断继续,会发现,最终程序在这里无限递归了,参数始终是keyboardInputChangedSelection​,直到栈溢出,程序崩溃。


现在我们知道原因了,为什么呢?猜想一下,这个函数的内部大概会是这样实现

45 - (BOOL)respondsToSelector:(SEL)aSelector
46 {
47     switch(aSelector)
48     {
49         ...
50         case keyboardInputChangedSelection:
51             return [self.delegate respondsToSelector:aSelector];
52         ...
53     }
54 }

这个问题已经不在我们能看到的代码层面了,所以即便能解决,也只能非常暴力的重写respondsToSelector,这个和我们要偷懒的初衷不符。


总结一下,self.delegate = self这种写法,在遇到

56 -(void)method
57 {
58     [self.delegate method];
59 }

这种用法的时候,会发生无限递归导致崩溃,一定要避免。


分享到:
评论

相关推荐

    SearchBar和tableView 组合并且不遮住状态栏

    self.searchcontroller.searchBar.delegate = self; self.searchcontroller.searchBar.keyboardType = UIKeyboardTypeDefault; CGRect r= self.table.tableHeaderView.bounds; r.origin.y=-10; self.table....

    ios-JAScrollChartView.zip

    self.chartView.delegate = self; self.chartView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.chartView]; NSMutableArray* data = [NSMutableArray new]; for (int i = 0; i...

    时间选择器

    _textField.delegate = self; _cuiPickerView = [[CuiPickerView alloc]init]; _cuiPickerView.frame = CGRectMake(0, self.view.frame.size.height, self.view.frame.size.width, 200); //这一步很重要 _...

    广告轮播控件

    广告轮播控件,调用简单。 调用方法: NSArray *images = @[@"zoro.jpg",@"three.jpg",@"onepiece.jpg"]; WMLoopView *loopView = [... loopView.delegate = self; self.tableView.tableHeaderView = loopView;

    ios-图片轮播.zip

    cycleView.delegate = self; cycleView.currentPageIndicatorTintColor = [UIColor redColor]; cycleView.pageIndicatorTintColor = [UIColor blueColor]; cycleView.diameter = 20; cycleView.cycleView =...

    Swift仿Twitter的导航条和页面

    scrollView.delegate = self scrollView.bounces = false self.view.addSubview(scrollView) self.scrollView.contentSize = CGSize(width: self.view.bounds.size.width * 3, height: hBounds/2) //...

    ios-模仿微博照片选择器,支持多选、选原图和视频的图片选择器,同时有3Dtouch预览功能,长按拖动改变顺序.通过相机拍照录制视频 - 支持ios8.0 以上.zip

    vc.delegate = self; vc.manager = self.manager; [self presentViewController:[[UINavigationController alloc] initWithRootViewController:vc] animated:YES completion:nil]; // 通过 ...

    tableview 上拉刷新 下拉刷新功能实现

    _header.delegate = self; _header.scrollView = self.tableView; //添加上拉加载更多 _footer = [[MJRefreshFooterView alloc] init]; _footer.delegate = self; _footer.scrollView = self.tableView;

    ios-YLPickerView.zip

    _mpicker.delegate = self; [self.view addSubview:_mpicker]; //每一列文字颜色 _mpicker.colorArry = @[color,color,color,color,color]; //每一列的背景颜色 _mpicker.bkcolorArry = @[color1,color1,...

    ios-TableView delegate dataSource封装.zip

    self.tabDataSource = [self.aTableView JDTab_DataSourceWithTabType:NumberOfRowsInSectionCount withVC:self isSection:true reuseIdentifier:@"aTableViewCell"]; [self.tabDataSource updateReloadData:@[@...

    iOS 各种动画

    _splashView.delegate = self; //Optional -&gt; if you want to receive updates on animation beginning/end _splashView.animationDuration = 2; //Optional -&gt; set animation duration. Default: 1s [self.view ...

    ios-ZLDropdownMenu.zip

    menu.delegate = self; menu.dataSource = self; [menu mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(topView.mas_bottom); make.left.right.equalTo(self.view); make.height.mas_...

    InputPasswordLikeAlipay-源码

    添加密码输入完成代理3.new a ZSDPaymentView instance:新建一个ZSDPaymentView实例ZSDPaymentView *payment = [[ZSDPaymentView alloc]init];...payment.goodsName = @"商品名称";...payment.delegate =

    CorePlot学习Demo

    plotSpace.delegate = self; plotSpace.allowsUserInteraction = YES;//允许拖动 //设置移动时的停止动画 这些参数保持默认即可 变化不大 plotSpace.momentumAnimationCurve = CPTAnimationCurveCubicIn; ...

    EasyUIImagePickerController

    .delegate = self 4. 选取图片来自相册 注意使用[weak self] 防止强引用 self.imagePickerController?.selectImageFromAlbumSuccess({[weak self] (imagePickerController) in if let strongSelf = self { ...

    VideoCamera2

    picker.delegate = self; picker.allowsEditing = YES;//设置可编辑 picker.sourceType = sourceType; [self presentModalViewController:picker animated:YES];//进入照相界面 [picker release];

    ios-城市选择器.zip

    cityListVC.delegate = self; //热门城市列表 cityListVC.arrayHotCity = [NSMutableArray arrayWithObjects:@"北京",@"上海",@"广州",@"厦门",@"深圳",@"天津",@"长沙",@"郑州", nil]; //历史选择城市列表 ...

    ios-CLAlertView自定制的弹出菜单.zip

    bottomView.delegate = self; bottomView.hlightButton = 1; bottomView.titleArray = @[@"收入",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",@"支出",...

    ios-时间选择器.zip

    view.delegate = self; //view.titleString = @"测试"; [view showView]; 可以自行设置显示的时间类型 在下列枚举中更改响应的枚举值 typedef NS_ENUM(NSInteger, UIDateType) { UIDateTypeAll = 0, //默认...

    iOS 新闻系统源代码

    iOS 新闻系统源代码 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ ... [self.delegate didSelectRow:self andCityZip:item.zip]; } }

Global site tag (gtag.js) - Google Analytics