今天同事在群里发了一个问题,问有没有人碰到类似如下的问题:
-[UILabel stringByTrimmingCharactersInSet:]: unrecognized selector sent to instance 0x7ff08c865970
一位同事第一反应是不是对象被释放了,出现了野指针?
然而加上异常断点、开启Zombie诊断后,并没有带来有用的信息。
我转身问是不是必现的?回答是的。
于是我建议直接给UILabel加个stringByTrimmingCharactersInSet:方法,然后打个断点,就可以从调用栈看出是哪里在调用——结果,整个主线程都是系统框架在调用。
但是从主线程调用栈还是可以看到跟UITableView的代理回调方法有关——具体是跟sectionHeader的获取有关。
我们通过直接注释掉相关方法得到了验证:
- (nullable UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section
的确是跟这里有关,注释掉后问题消失。
那问题基本就落在headerView的布局上了,这是一个继承自UITableViewHeaderFooterView的子类,点击.h头文件一看,我瞄到了有个UILabel *类型变量叫做text。这样的命名会让我心里一纠结,所以很快就感知到了,因为我会命名为textLabel。
于是我说,这样的命名很容易出现问题,容易发生“将这样命名的变量当做NSString *类型进行传递”的现象。
通过修改属性名称,并且在进行一处处替换的过程中我认真地看着有没有将其错误使用,然而并没有——但是问题还是得到解决了。
于是我们推测,在基类中有NSString *类型的变量名为text,但是在子类中重写了它,导致类型变化,进而引发了问题。
这又让我想起:
There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton