【问题】
参考Your Second iOS App去折腾:
参考教程开发iOS的第二个app:Storyboards – BirdWatching
的过程中,运行模拟器,结果出错:
【解决过程】
1.后来参考:
iOS second app “unrecognized selector sent to instance”
相关代码改为:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController; BirdsMasterViewController *firstViewController = (BirdsMasterViewController *)[[navigationController viewControllers] objectAtIndex:0]; */ BirdsMasterViewController *firstViewController = (BirdsMasterViewController *)self.window.rootViewController; BirdSightingDataController *aDataController = [[BirdSightingDataController alloc] init]; firstViewController.dataController = aDataController; // Override point for customization after application launch. return YES; }
结果还是同样错误。
2.折腾了一段时间,后来基本算是看懂错误的基本原理了:
(又运行了一次,同样错误,但是指针不同而已:
2012-08-22 10:00:06.433 BirdWatching[544:f803] -[UINavigationController setDataController:]: unrecognized selector sent to instance 0x68a90f0
(lldb)
其中0x68a90f0,表示对应的对象firstViewController,可以通过调试过程中,鼠标移动到该对象上,看出:
而此错误,指的是,把对应的selector,即方法setDataController,即属性dataController的setter,发送给了firstViewController,但是firstViewController却无法识别,所以才报错的。
3.因为上面那个参考的帖子中所说的“it’s because self.window.rootViewController
is not a UINavigationController
it might be simple UIViewcontroller
”根本不是我这里 的原因。
我这里,原先代码本身是获得了正确的“UINavigationController
”,所以再次把代码改回去。
然后错误又是原先的UITableViewController了:
但是很明显,代码中,已经通过:
BirdsMasterViewController *firstViewController = (BirdsMasterViewController *)[[navigationController viewControllers] objectAtIndex:0];
去将获得的UITableViewController强制转换为BirdsMasterViewController了,为何此处调试过程中,还是原先的UITableViewController类型???
所以,目前看来,有两种可能的原因:
A。firstViewController的类型有问题,导致真实的变量中,不是BirdsMasterViewController 类型
比如,虽然经过强制转换,但是实际上不是BirdsMasterViewController,而还是UITableViewController,所以此处报错也是针对UITableViewController报错的。
B。属性dataController的定义有问题,导致无法访问
去看了对应的定义:
@interface BirdsMasterViewController : UITableViewController @property (strong, nonatomic) BirdSightingDataController *dataController; @end
看起来不像有错的,而且本身是示例代码,所以错误可能性不是很大。
所以,继续去沿着错误是A的思路继续找原因。
4.参考:
Trying to solve a [DetailViewController setDataController:]: unrecognized selector sent to instance
去回到原先教程:
Implement the Master View Controller
去给BirdsMasterViewController.m中添加了synthesize:
@implementation BirdsMasterViewController @synthesize dataController = _dataController;
结果问题依旧。
也是和期望的一样,毕竟,现在不需要手动去添加synthesize,而编译器会帮我们静态或动态添加的。
5.后来突然想到,是不是那个scene的所属的class所导致的,然后就去看了看,当前出错时,对于MasterView所属的class是UITableViewController:
然后去改为期望的BirdsMasterViewController:
然后再重新运行,错误就消失了,可以正常出行iOS模拟器了:
再回头看错误的原因,就容易明白了:
原先不小心,由于删除detailview等内容,重建detailview,反正结果导致对于Bird Sighting的MasterView,所设置的Class变成了默认的,代码里面所设置的UITableViewController,使得运行时,
通过代码:
[[navigationController viewControllers] objectAtIndex:0];
所获得的object,实际上是UITableViewController,虽然通过;
(BirdsMasterViewController *)
强制转换为BirdsMasterViewController,然后赋值给了firstViewController,但是实际上仍是UITableViewController,所以后面的代码:
firstViewController.dataController = aDataController;
即相当于:
[firstViewController setDataController:aDataController];
去调用firstViewController的setDataController方法,但是由于此时firstViewController是UITableViewController类型,其没有对应的setDataController方法,所以出错。
而去把Bird Sighting的MasterView改为期望的BirdsMasterViewController后,此时
[[navigationController viewControllers] objectAtIndex:0];
本身所获得的object就是BirdsMasterViewController类型了,所以后面去调用setDataController,也就是可以正常运行的了。
【总结】
对于 MainClass callMethod: unrecognized selector sent to instance objectPointer类型的错误:
1. 首先要找到错误代码的位置
这点可以通过Xcode中的调试窗口中直接看到。
如果没有看到代码错误的所在位置,而是在主函数中出现了Thread 1: signal SIGABRT的话,那么可参考:
【未解决】Xcode中编译iOS程序,运行出错:Thread 1: signal SIGABRT
去打上断点,重新运行,程序即可停在具体出错代码的位置了。
2.找到错误所相关的对象/实例
上面的objectPointer就是出错的对象。
其中,可以根据指针的值,找到相应的对象变量。
可以通过鼠标移动到对应变量上,看到对应变量的指针值来确认是该变量。
比如此处就是0x68a90f0,对应着firstViewController。
3.找到所属主类MainClass 和被调用的方法callMethod
找到该对象所属于的类型,和被调用的方法。
比如此处就是firstViewController是UITableViewController类型,被调用的方法是setDataController。
其中setDataController是dataController的setter。
4.具体分析错误的可能,并继续最终错误具体原因
接下来就是分析错误的可能性,并继续找到错误根本原因了。
因为对于MainClass callMethod: unrecognized selector sent to instance objectPointer类型的错误,本身含义就是,
变量objectPointer,其类型是MainClass ,然后调用其方法callMethod,但是其却不识别。
所以,错误的
(1)就是本身MainClass就没有此callMethod的方法
比如此处,UITableViewController的确没有setDataController方法。
而setDataController其实是属性dataController的setter。
由此又可以继续分析错误可能性:
A:UITableViewController没有实现属性dataController的setter方法
B:UITableViewController本身就没有这个dataController的属性
需要说明的是:此setter函数,之前是需要手动通过synthesize加上的,只是最新版本的编译器可以自动帮你加了。
即,最新版本的编译器,可以使得你写代码时,不用再写synthesize了。
所以,此处不是synthesize的原因,不是dataController的setter方法,而是UITableViewController本身就没有这个dataController的属性的原因。
(2)MainClass有此callMethod方法,但是定义不对
比如,是函数设置为了private等原因,但是继承者无法访问等一些类似的原因。
此处暂没遇到,但是是可能的一些原因。
总之,根据具体的class,去找为何调用该method失败,按照这个思路去找原因,最后总是可以分析出错误所在的。
转载请注明:在路上 » 【已解决】UITableViewController setDataController:unrecognized selector sent to instance