发送到实例的无法识别的选择器以一种奇怪的方式抛出
unrecognized selector sent to instance thrown in a strange way
我有一个 tableView,它应该用来自服务器的数据加载它的单元格。
当我的数据从服务器加载时,我在 completionhandler 块中调用 [self.tableView reloadData]。
因此 cellForRowAtIndexPath 方法再次被调用。
我对 cellForRowAtIndexPath 的实现是这样的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Configure the cell...
NewsCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
if(!cell){
cell = [[NewsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"NewsCell"];
}
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
cell.newsTitle.text = currentNews.title;
// cell.newsTitle.text = @"salam";
return cell;
}
注意:self.newsList是一个数组,其中填充了来自服务器
的数据
从服务器解析响应 json 的代码是这样的:
[GNetworkHelper getJsonDataFromURL:urlString
withCompletionHandler:^(NSDictionary * jsonResponse) {
// Parse retrieved json and pass it to completion handler;;
NSMutableArray* news = [[NSMutableArray alloc] init];
if (jsonResponse) {
for (NSDictionary* new in jsonResponse) {
News *currentNew = [[News alloc] initWithDictionary:new];
[news addObject:currentNew];
}
}else{
News* testNew = [[News alloc] init];
[testNew setTitle:@"salam"];
[news addObject:testNew];
}
completionHandler(news);
}];
我的问题: 当我调试这段代码时,我使用 dequeueReusableCellWithIdentifier:forIndexPath 函数创建的单元格变量在调试器的变量部分为空,但是当我使用 lldb 命令 po 打印出来时,我得到了这个
(lldb) po cell
<NewsCell: 0x7fc5fadb2ee0; baseClass = UITableViewCell; frame = (0 0; 375 143); autoresize = W; layer = <CALayer: 0x7fc5fad9fcd0>>
currentNews 变量也是如此。为此,我从 po 命令
得到了这个
(lldb) po currentNews
<News: 0x7fc5fd0480d0>
我什至可以像这样获取属性:
(lldb) po currentNews.title
<__NSCFArray 0x7fc5fd047300>(
"some title"
)
单步执行此方法的语句时没有异常。但是当方法 returns 抛出 Unrecognized Selector 异常
为什么会这样??
奇怪的是,如果我改变这一行:
cell.newsTitle.text = currentNews.title;
对此:
cell.newsTitle.text = @"Some test text";
一切顺利,特别是 cell 和 currentNews 变量不再为空,tableView 毫无问题地呈现单元格
完整的堆栈跟踪是:
[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300
2015-09-16 11:30:40.630 Gallery[12013:952548] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300'
--- First throw call stack:
(
0 CoreFoundation 0x0000000105af3f35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010578cbb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000105afb04d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x0000000105a5327c ___forwarding___ + 988
4 CoreFoundation 0x0000000105a52e18 _CF_forwarding_prep_0 + 120
5 UIKit 0x00000001060a5f45 -[UILabel _textRectForBounds:limitedToNumberOfLines:includingShadow:] + 65
6 UIKit 0x00000001060a5da0 -[UILabel textRectForBounds:limitedToNumberOfLines:] + 76
7 UIKit 0x00000001060a9852 -[UILabel _intrinsicSizeWithinSize:] + 170
8 UIKit 0x00000001060a9932 -[UILabel intrinsicContentSize] + 76
9 UIKit 0x000000010655fea4 -[UIView(UIConstraintBasedLayout) _generateContentSizeConstraints] + 33
10 UIKit 0x000000010655fc64 -[UIView(UIConstraintBasedLayout) _updateContentSizeConstraints] + 422
11 UIKit 0x00000001065670d6 -[UIView(AdditionalLayoutSupport) updateConstraints] + 163
12 UIKit 0x00000001060a979d -[UILabel updateConstraints] + 272
13 UIKit 0x00000001065666fa -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 248
14 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
15 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
16 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
17 Foundation 0x0000000105332d6e -[NSISEngine withBehaviors:performModifications:] + 155
18 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
19 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
20 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
21 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
22 UIKit 0x0000000106566dbe __60-[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded]_block_invoke + 96
23 UIKit 0x0000000106566a86 -[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded] + 231
24 UIKit 0x000000010635c8b8 -[UITableViewCellContentView updateConstraintsIfNeeded] + 95
25 UIKit 0x000000010656719e -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeeded] + 159
26 UIKit 0x0000000105f4db2d -[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 114
27 UIKit 0x0000000105f59973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
28 QuartzCore 0x000000010504ade8 -[CALayer layoutSublayers] + 150
29 QuartzCore 0x000000010503fa0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
30 QuartzCore 0x000000010503f87e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
31 QuartzCore 0x0000000104fad63e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
32 QuartzCore 0x0000000104fae74a _ZN2CA11Transaction6commitEv + 390
33 QuartzCore 0x0000000104faedb5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
34 CoreFoundation 0x0000000105a28dc7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
35 CoreFoundation 0x0000000105a28d20 __CFRunLoopDoObservers + 368
36 CoreFoundation 0x0000000105a1eb53 __CFRunLoopRun + 1123
37 CoreFoundation 0x0000000105a1e486 CFRunLoopRunSpecific + 470
38 GraphicsServices 0x00000001085d29f0 GSEventRunModal + 161
39 UIKit 0x0000000105ee0420 UIApplicationMain + 1282
40 Gallery 0x000000010346ded3 main + 115
41 libdyld.dylib 0x0000000107325145 start + 1
42 ??? 0x0000000000000001 0x0 + 1
)
有人能告诉我这是什么原因吗?
它只是表明在某些时候当您尝试访问 currentNews
对象中的 title
值时,它会是 null
。这就是为什么您的应用会抛出异常。设置一个条件来检查 null
值。
使用以下方法检查任何 value/object 是否存在。
用法
在您的 cellForRowAtIndexPath
方法中编写以下代码。
if([self isEmpty:currentNews.title])
{
cell.newsTitle.text = @"default value";
}
else
{
cell.newsTitle.text = currentNews.title[0];
}
// Method to check empty value/object
- (BOOL)isEmpty:(id)object
{
return object == nil
|| [object isKindOfClass:[NSNull class]]
|| ([object respondsToSelector:@selector(length)]
&& [(NSData *)object length] == 0)
|| ([object respondsToSelector:@selector(count)]
&& [(NSArray *)object count] == 0);
}
服务器 JSON 是一个字符串数组 ["some title"]
,而您希望它只是一个字符串 "some title"
.
尝试添加一个断言,以便您对服务器数据的解析是正确的。
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
NSAssert([currentNews.title isKindOfClass:[NSString class]],
@"Title is not a string but a %@.",
NSStringFromClass([currentNews.title class]));
cell.newsTitle.text = currentNews.title;
我有一个 tableView,它应该用来自服务器的数据加载它的单元格。
当我的数据从服务器加载时,我在 completionhandler 块中调用 [self.tableView reloadData]。
因此 cellForRowAtIndexPath 方法再次被调用。
我对 cellForRowAtIndexPath 的实现是这样的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Configure the cell...
NewsCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
if(!cell){
cell = [[NewsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"NewsCell"];
}
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
cell.newsTitle.text = currentNews.title;
// cell.newsTitle.text = @"salam";
return cell;
}
注意:self.newsList是一个数组,其中填充了来自服务器
的数据
从服务器解析响应 json 的代码是这样的:
[GNetworkHelper getJsonDataFromURL:urlString
withCompletionHandler:^(NSDictionary * jsonResponse) {
// Parse retrieved json and pass it to completion handler;;
NSMutableArray* news = [[NSMutableArray alloc] init];
if (jsonResponse) {
for (NSDictionary* new in jsonResponse) {
News *currentNew = [[News alloc] initWithDictionary:new];
[news addObject:currentNew];
}
}else{
News* testNew = [[News alloc] init];
[testNew setTitle:@"salam"];
[news addObject:testNew];
}
completionHandler(news);
}];
我的问题: 当我调试这段代码时,我使用 dequeueReusableCellWithIdentifier:forIndexPath 函数创建的单元格变量在调试器的变量部分为空,但是当我使用 lldb 命令 po 打印出来时,我得到了这个
(lldb) po cell
<NewsCell: 0x7fc5fadb2ee0; baseClass = UITableViewCell; frame = (0 0; 375 143); autoresize = W; layer = <CALayer: 0x7fc5fad9fcd0>>
currentNews 变量也是如此。为此,我从 po 命令
得到了这个(lldb) po currentNews
<News: 0x7fc5fd0480d0>
我什至可以像这样获取属性:
(lldb) po currentNews.title
<__NSCFArray 0x7fc5fd047300>(
"some title"
)
单步执行此方法的语句时没有异常。但是当方法 returns 抛出 Unrecognized Selector 异常 为什么会这样??
奇怪的是,如果我改变这一行:
cell.newsTitle.text = currentNews.title;
对此:
cell.newsTitle.text = @"Some test text";
一切顺利,特别是 cell 和 currentNews 变量不再为空,tableView 毫无问题地呈现单元格
完整的堆栈跟踪是:
[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300
2015-09-16 11:30:40.630 Gallery[12013:952548] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray length]: unrecognized selector sent to instance 0x7fc5fd047300'
--- First throw call stack:
(
0 CoreFoundation 0x0000000105af3f35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010578cbb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000105afb04d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x0000000105a5327c ___forwarding___ + 988
4 CoreFoundation 0x0000000105a52e18 _CF_forwarding_prep_0 + 120
5 UIKit 0x00000001060a5f45 -[UILabel _textRectForBounds:limitedToNumberOfLines:includingShadow:] + 65
6 UIKit 0x00000001060a5da0 -[UILabel textRectForBounds:limitedToNumberOfLines:] + 76
7 UIKit 0x00000001060a9852 -[UILabel _intrinsicSizeWithinSize:] + 170
8 UIKit 0x00000001060a9932 -[UILabel intrinsicContentSize] + 76
9 UIKit 0x000000010655fea4 -[UIView(UIConstraintBasedLayout) _generateContentSizeConstraints] + 33
10 UIKit 0x000000010655fc64 -[UIView(UIConstraintBasedLayout) _updateContentSizeConstraints] + 422
11 UIKit 0x00000001065670d6 -[UIView(AdditionalLayoutSupport) updateConstraints] + 163
12 UIKit 0x00000001060a979d -[UILabel updateConstraints] + 272
13 UIKit 0x00000001065666fa -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 248
14 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
15 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
16 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
17 Foundation 0x0000000105332d6e -[NSISEngine withBehaviors:performModifications:] + 155
18 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
19 CoreFoundation 0x00000001059fc194 CFArrayApplyFunction + 68
20 UIKit 0x000000010656669b -[UIView(AdditionalLayoutSupport) _internalUpdateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 153
21 UIKit 0x00000001065668f2 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededAccumulatingViewsNeedingSecondPassAndViewsNeedingBaselineUpdate:] + 124
22 UIKit 0x0000000106566dbe __60-[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded]_block_invoke + 96
23 UIKit 0x0000000106566a86 -[UIView(AdditionalLayoutSupport) updateConstraintsIfNeeded] + 231
24 UIKit 0x000000010635c8b8 -[UITableViewCellContentView updateConstraintsIfNeeded] + 95
25 UIKit 0x000000010656719e -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeeded] + 159
26 UIKit 0x0000000105f4db2d -[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 114
27 UIKit 0x0000000105f59973 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 521
28 QuartzCore 0x000000010504ade8 -[CALayer layoutSublayers] + 150
29 QuartzCore 0x000000010503fa0e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
30 QuartzCore 0x000000010503f87e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
31 QuartzCore 0x0000000104fad63e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
32 QuartzCore 0x0000000104fae74a _ZN2CA11Transaction6commitEv + 390
33 QuartzCore 0x0000000104faedb5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
34 CoreFoundation 0x0000000105a28dc7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
35 CoreFoundation 0x0000000105a28d20 __CFRunLoopDoObservers + 368
36 CoreFoundation 0x0000000105a1eb53 __CFRunLoopRun + 1123
37 CoreFoundation 0x0000000105a1e486 CFRunLoopRunSpecific + 470
38 GraphicsServices 0x00000001085d29f0 GSEventRunModal + 161
39 UIKit 0x0000000105ee0420 UIApplicationMain + 1282
40 Gallery 0x000000010346ded3 main + 115
41 libdyld.dylib 0x0000000107325145 start + 1
42 ??? 0x0000000000000001 0x0 + 1
)
有人能告诉我这是什么原因吗?
它只是表明在某些时候当您尝试访问 currentNews
对象中的 title
值时,它会是 null
。这就是为什么您的应用会抛出异常。设置一个条件来检查 null
值。
使用以下方法检查任何 value/object 是否存在。
用法
在您的 cellForRowAtIndexPath
方法中编写以下代码。
if([self isEmpty:currentNews.title])
{
cell.newsTitle.text = @"default value";
}
else
{
cell.newsTitle.text = currentNews.title[0];
}
// Method to check empty value/object
- (BOOL)isEmpty:(id)object
{
return object == nil
|| [object isKindOfClass:[NSNull class]]
|| ([object respondsToSelector:@selector(length)]
&& [(NSData *)object length] == 0)
|| ([object respondsToSelector:@selector(count)]
&& [(NSArray *)object count] == 0);
}
服务器 JSON 是一个字符串数组 ["some title"]
,而您希望它只是一个字符串 "some title"
.
尝试添加一个断言,以便您对服务器数据的解析是正确的。
News* currentNews = (News*)[self.newsList objectAtIndex:indexPath.row];
NSAssert([currentNews.title isKindOfClass:[NSString class]],
@"Title is not a string but a %@.",
NSStringFromClass([currentNews.title class]));
cell.newsTitle.text = currentNews.title;