未识别的选择器发送到实例 [NSCFString subarrayWithRange:]

7
我有以下代码,它产生了这个错误。我不明白为什么会向一个字符串发送subarrayWithRange消息?当它明显是一个数组时?
我有以下代码,它产生了这个错误。我不明白为什么会向一个字符串发送subarrayWithRange消息?当它明显是一个数组时?
static const int kItemsPerView = 20;
NSRange rangeForView = NSMakeRange( page * kItemsPerView, kItemsPerView );

NSMutableArray *temp = [[APP_DELEGATE keysArray] mutableCopyWithZone:NULL]; 
NSArray *itemsForView = [temp subarrayWithRange:rangeForView];

for (int loopCounter = 0;loopCounter < r*c;loopCounter++){
    NSLog(@"%i: %@ ", loopCounter, [itemsForView objectAtIndex:loopCounter]);
}

错误:

-[NSCFString subarrayWithRange:]: unrecognized selector sent to instance 0x6b071a0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: [NSCFString subarrayWithRange:]:

谢谢

2个回答

29

这种错误通常与内存管理相关。本质上,您正在向一个地址发送消息,而该地址现在已被其他对象占用,因为先前的占用者意外消失了。由于该地址空间可以被任何东西占用,因此您恰好要求一个NSCFString响应某些内容。

如果您在创建临时数组后暂停调试器,那么您看到分配给temp的是什么?我猜每当-keysArray返回时,某些事情并不完全正确。您可能需要仔细检查该函数处理内存的方式。从名称上看,我想您的应用程序委托具有名为“keysArray”的数组作为实例变量。也许在它被创建或分配时没有得到适当的保留?


创建后,temp 是一个包含80个字符串的数组,但调试提示只显示了10个条目,不确定是 Xcode 的问题还是其他原因。你说得对,keysArray 是我应用委托中的一个实例变量,是一个属性,并且使用了 arrayWithContentsOfFile 方便方法进行综合和分配。我不需要手动保留它吗? - joec
是的,它不是由你创建的,而是由方便的方法创建的。因此,如果你希望它在创建后仍然存在,需要通过保留(或创建自己的副本)来声明所有权。再次查看内存管理规则。 - Joshua Nozzi
如果您使用属性访问器而不是赋值,那么您就不需要保留(retain);或者,您可以调用[[NSArray alloc] initWithContentsOfFile:@"somepath"]来代替。 - jlehr
“True,但我认为了解Objective-C 2带来的便利背后发生的事情非常重要(例如@property,@synthesize等)。事实上,为了在非垃圾收集环境中有效地使用@property声明,您需要对Cocoa内存管理有足够了解。” - Joshua Nozzi
将 "assign" 更改为 "strong" 修复了问题。 - Jerry

5

我有一个问题。我做了一些愚蠢的事情。我将UITextView分配给了一个字符串,而不是它的文本属性。例如:

myObj.txtbxThing = [NSString stringWithFormat:@"%@", stuffString];

而不是:

myObj.txtbxThing.text = [NSString stringWithFormat:@"%@", stuffString];

我也犯了类似的愚蠢错误。我将一个NSString赋值给了一个NSURL*,而且不知何故错过了编译器的警告。 - Liron Yahdav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接