最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】UITableViewController setDataController:unrecognized selector sent to instance

iOS crifan 6167浏览 0评论

【问题】

参考Your Second iOS App去折腾:

参考教程开发iOS的第二个app:Storyboards – BirdWatching

的过程中,运行模拟器,结果出错:

unrecoginzed selector sent to instance

 

【解决过程】

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,可以通过调试过程中,鼠标移动到该对象上,看出:

firstViewController pointer

而此错误,指的是,把对应的selector,即方法setDataController,即属性dataController的setter,发送给了firstViewController,但是firstViewController却无法识别,所以才报错的。

3.因为上面那个参考的帖子中所说的“it’s because self.window.rootViewController is not a UINavigationController it might be simple UIViewcontroller”根本不是我这里 的原因。

我这里,原先代码本身是获得了正确的“UINavigationController ”,所以再次把代码改回去。

然后错误又是原先的UITableViewController了:

UITableViewController error

但是很明显,代码中,已经通过:

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:

原先的是UITableViewController

然后去改为期望的BirdsMasterViewController:

改为BirdsMasterViewController即可

然后再重新运行,错误就消失了,可以正常出行iOS模拟器了:

can show 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

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. 哈哈,跟我前两天遇到同一个错误场景,自己初学,琢磨的半天才发现是这个原因,网上对此错误都说是对象释放太早导致的,所以走了弯路。
    seanpan12年前 (2012-09-08)回复
86 queries in 0.152 seconds, using 22.23MB memory