为什么 iOS 会尝试在 NSIndexPath 上调用 rangeOfCharacterFromSet:?
Why would iOS try to call rangeOfCharacterFromSet: on an NSIndexPath?
我收到以下错误,导致 SIGABRT
:
2015-09-10 17:54:23.859 MyApp[1310:2027719] ERROR CRASH #(null) -[NSIndexPath rangeOfCharacterFromSet:]: unrecognized selector sent to instance 0xc000000000000016
2015-09-10 17:54:23.879 MyApp[1310:2027719] ERROR Stack Trace: (
0 CoreFoundation 0x0000000183840248 <redacted> + 160
1 libobjc.A.dylib 0x00000001952640e4 objc_exception_throw + 60
2 CoreFoundation 0x00000001838472f4 <redacted> + 0
3 CoreFoundation 0x00000001838440a8 <redacted> + 928
4 CoreFoundation 0x000000018374696c _CF_forwarding_prep_0 + 92
5 UIKit 0x0000000188632a44 <redacted> + 104
6 UIKit 0x00000001887a0ff0 <redacted> + 76
7 UIKit 0x00000001887a10b0 <redacted> + 56
8 UIKit 0x00000001887a1194 <redacted> + 36
9 QuartzCore 0x0000000187bf0820 <redacted> + 320
10 QuartzCore 0x0000000187bf06c4 <redacted> + 32
11 QuartzCore 0x0000000187befe58 <redacted> + 276
12 QuartzCore 0x0000000187befbd8 <redacted> + 528
13 QuartzCore 0x0000000187be9300 <redacted> + 80
14 CoreFoundation 0x00000001837f7ff0 <redacted> + 32
15 CoreFoundation 0x00000001837f4f7c <redacted> + 360
16 CoreFoundation 0x00000001837f535c <redacted> + 836
17 CoreFoundation 0x0000000183720f74 CFRunLoopRunSpecific + 396
18 GraphicsServices 0x000000018d0436fc GSEventRunModal + 168
19 UIKit 0x0000000188322d94 UIApplicationMain + 1488
20 MyApp 0x00000001000437b0 main + 68
21 libdyld.dylib 0x000000019590ea08 <redacted> + 4
看起来像 iOS 正在尝试将消息发送到 NSString
选择器,但消息已发送到 NSIndexPath
。奇怪!
后来我发现了问题;我将 UILabel
中文本的值设置为指向 CoreData 对象的 NSNumber
列 (0xc000000000000016
) 中对象的指针,而不是 NSString
。在将它传递给我的 enumToString:
方法之前,我的修复已添加 .intValue
到 NSNumber
。
typedef NS_ENUM(NSInteger, MyEnum)
{
MyEnum1 = 1,
MyEnum2,
MyEnum3
};
- (NSString*)enumToString:(MyEnum)enumValue
{
switch (enumValue) {
case MyEnum1:
return @"One";
case MyEnum2:
return @"Two";
case MyEnum3:
return @"Three";
}
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
// cdObject is a managed object in CoreData. Its enumValue column is an NSNumber.
cell.textLabel.text = [self enumToString:cdObject.enumValue];
return cell;
}
这就留下了问题:为什么这会导致 iOS 尝试向不存在的选择器 -[NSIndexPath rangeOfCharacterFromSet:]
发送消息?
崩溃发生在刚完成 -[UITableViewDataSource tableView:cellForRowAtIndexPath:]
好的,所以原因很可能不是某些线程出错。核心数据在某些时候将 NSManagedObjects 变成错误。这可能是相关的。此外,NSNumbers 是一种特殊的对象:指针是一个带标签的指针,这个带标签的指针可能包含实际的数值。这可能也有关系。无论如何,一条消息被发送到一个指针,而该指针不再指向识别该消息的对象。在此处阅读有关标记指针的信息:https://www.mikeash.com/pyblog/friday-qa-2012-07-27-lets-build-tagged-pointers.html
我收到以下错误,导致 SIGABRT
:
2015-09-10 17:54:23.859 MyApp[1310:2027719] ERROR CRASH #(null) -[NSIndexPath rangeOfCharacterFromSet:]: unrecognized selector sent to instance 0xc000000000000016
2015-09-10 17:54:23.879 MyApp[1310:2027719] ERROR Stack Trace: (
0 CoreFoundation 0x0000000183840248 <redacted> + 160
1 libobjc.A.dylib 0x00000001952640e4 objc_exception_throw + 60
2 CoreFoundation 0x00000001838472f4 <redacted> + 0
3 CoreFoundation 0x00000001838440a8 <redacted> + 928
4 CoreFoundation 0x000000018374696c _CF_forwarding_prep_0 + 92
5 UIKit 0x0000000188632a44 <redacted> + 104
6 UIKit 0x00000001887a0ff0 <redacted> + 76
7 UIKit 0x00000001887a10b0 <redacted> + 56
8 UIKit 0x00000001887a1194 <redacted> + 36
9 QuartzCore 0x0000000187bf0820 <redacted> + 320
10 QuartzCore 0x0000000187bf06c4 <redacted> + 32
11 QuartzCore 0x0000000187befe58 <redacted> + 276
12 QuartzCore 0x0000000187befbd8 <redacted> + 528
13 QuartzCore 0x0000000187be9300 <redacted> + 80
14 CoreFoundation 0x00000001837f7ff0 <redacted> + 32
15 CoreFoundation 0x00000001837f4f7c <redacted> + 360
16 CoreFoundation 0x00000001837f535c <redacted> + 836
17 CoreFoundation 0x0000000183720f74 CFRunLoopRunSpecific + 396
18 GraphicsServices 0x000000018d0436fc GSEventRunModal + 168
19 UIKit 0x0000000188322d94 UIApplicationMain + 1488
20 MyApp 0x00000001000437b0 main + 68
21 libdyld.dylib 0x000000019590ea08 <redacted> + 4
看起来像 iOS 正在尝试将消息发送到 NSString
选择器,但消息已发送到 NSIndexPath
。奇怪!
后来我发现了问题;我将 UILabel
中文本的值设置为指向 CoreData 对象的 NSNumber
列 (0xc000000000000016
) 中对象的指针,而不是 NSString
。在将它传递给我的 enumToString:
方法之前,我的修复已添加 .intValue
到 NSNumber
。
typedef NS_ENUM(NSInteger, MyEnum)
{
MyEnum1 = 1,
MyEnum2,
MyEnum3
};
- (NSString*)enumToString:(MyEnum)enumValue
{
switch (enumValue) {
case MyEnum1:
return @"One";
case MyEnum2:
return @"Two";
case MyEnum3:
return @"Three";
}
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
// cdObject is a managed object in CoreData. Its enumValue column is an NSNumber.
cell.textLabel.text = [self enumToString:cdObject.enumValue];
return cell;
}
这就留下了问题:为什么这会导致 iOS 尝试向不存在的选择器 -[NSIndexPath rangeOfCharacterFromSet:]
发送消息?
崩溃发生在刚完成 -[UITableViewDataSource tableView:cellForRowAtIndexPath:]
好的,所以原因很可能不是某些线程出错。核心数据在某些时候将 NSManagedObjects 变成错误。这可能是相关的。此外,NSNumbers 是一种特殊的对象:指针是一个带标签的指针,这个带标签的指针可能包含实际的数值。这可能也有关系。无论如何,一条消息被发送到一个指针,而该指针不再指向识别该消息的对象。在此处阅读有关标记指针的信息:https://www.mikeash.com/pyblog/friday-qa-2012-07-27-lets-build-tagged-pointers.html