Debug中常见错误之对象被提前释放&函数调用中selector传递机制一窥

来源:互联网 发布:plc人机界面设计软件 编辑:程序博客网 时间:2024/05/29 13:10

一、大纲

1、SIGABRT错误以及出现“unrecognized selector sent to instance XXX”

2、程序中过早释放对象;

3、追到了几个牛逼的函数;

4、启示


二、下面依次说说

1、出现“unrecognized selector sent to instance XXX” 这条错误消息意味着你的app正在试着执行一个不存在的方法。这种情况的发生,主要是都是一个方法被错误的对象调用了(也就是这个对象没有这个方法,但是你调用了他,就错了)。这种错误的解决方法也比较简单,通过使用Exception Breakpoint(异常断点),你可以告诉xcode在一个特定的时候暂停这个程序,这样你就知道是在哪行代码上出现了这个错误,从而继续追踪到出错的对象和出错的selector;

2、这次出现这个SIGABRT错误的原因是我在引用一个第三方库TSTableView的时候没有注意到它在运行中一直需要保留其数据模型TSTableViewModel,而在我的程序中参照案例我只是在TSTableView的初始函数ViewDidLoad中实例化了它,但是并没有保留它,而在之后的操作中,由于还要用到这个Model,所以最后找不到它了,传递给它的selector就回头传递给TSTableView本身,只可惜TSTableView本身并不响应这个selector,最后就报出了"unrecognized selector sent to instance XXX"这样的错误;

3、在追踪的过程中,发现了TSTableView的两个非常厉害的函数:

    

#pragma mark - Provide TSTableViewDataSource functionality- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{    NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];    if(!signature)        signature = [(id)self.dataSource methodSignatureForSelector:aSelector];        return signature;}- (void)forwardInvocation:(NSInvocation *)anInvocation{    if ([self.dataSource respondsToSelector:[anInvocation selector]])        [anInvocation invokeWithTarget:self.dataSource];    else        [super forwardInvocation:anInvocation];}
     这是源代码,具体原理我也没去深究,简单讲一下我的理解,现在的情况是TSTableView本身没有实现一个叫做TSTableViewDataSource的协议protocol,但是它的一个属性dataSource实现了这个协议,因此,当一个TSTableViewDataSource协议中定义的selector传递到TSTableView的时候(这里比如说numberOfColumns),TSTableView会先调用- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector这个方法,判断它自己对这个selector有没有signature,如果没有就返回它的小弟,也就是dataSource属性对于此selector的signature,然后调用下面一个方法

- (void)forwardInvocation:(NSInvocation *)anInvocation,说白了这个方法做的事情也很简单,那就是先判断传递过来的selector自己搞不搞得定,搞得定的话就自己搞定,搞不定的话就让自己的小弟(也就是dataSource属性)出马来搞定。

4、启示

      刚开始遇到这个bug的时候自己都有点不知所措,因为我看了一下TSTableView的的确确是不能够响应numberOfColumns这个selector的啊,一时间我都怀疑是不是我下载的第三方库文件有问题,现在终于明白了,selector传递到一个对象的时候,即使表面上看,这个对象是不能响应的,但是这个对象可以通过selector传递的机制,将这个selector传递给其他对象来处理,我想这也是Objective-C语言的动态性的一种真真切切的体现吧。

    

0 0
原创粉丝点击