Iphone 为什么从plist或JSON解码的数组不响应:class或:count,而通过编程创建的数组却响应:class或:count?

Iphone 为什么从plist或JSON解码的数组不响应:class或:count,而通过编程创建的数组却响应:class或:count?,iphone,Iphone,我遇到了一个非常棘手的问题。我有一个UITableViewController,它在其init方法中从JSON或plist文件(我已经尝试了两者)解码字典,然后从字典中检索数组。稍后,在tableView:numberOfRowsInSection:方法中,我将返回该数组的计数 然而,出于我之外的原因,在该点调用数组上的count会使应用程序崩溃,尽管在init中赋值之后直接调用count不会。此外,如果我用编程创建的数组(通过NSArray initWithObjects)替换初始赋值,它也可

我遇到了一个非常棘手的问题。我有一个UITableViewController,它在其init方法中从JSON或plist文件(我已经尝试了两者)解码字典,然后从字典中检索数组。稍后,在tableView:numberOfRowsInSection:方法中,我将返回该数组的计数

然而,出于我之外的原因,在该点调用数组上的count会使应用程序崩溃,尽管在init中赋值之后直接调用count不会。此外,如果我用编程创建的数组(通过NSArray initWithObjects)替换初始赋值,它也可以正常工作

init中的JSON解码:

NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Categories" ofType:@"json"];
SBJSON *jsonParser = [SBJSON new];
NSDictionary* dict = [jsonParser objectWithString:[NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]];
categories = [dict objectForKey:@"ContentCategories"];

// Outputs correct count
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);
编程初始化:

 categories = [[NSArray alloc] initWithObjects: [[NSDictionary alloc] initWithObjectsAndKeys:@"Junk", @"Title"]];

 // Outputs correct count
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);
UITableViewController行数方法:

// Outputs correctly if programmatically created, crashes if decoded from JSON/plist
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);
我尝试过将“categories”变量作为ivar、属性ivar和类变量,但没有成功


谢谢你的帮助

注意:将“categories”更改为属性并在所有设置/获取方法(例如,self.categories=…)前面添加“self.”可以实现这一点。出于某种原因,在numberOfRows方法(!)中仅调用“categories”就返回了UIWindow类型的对象。这对我来说似乎非常奇怪(我希望我只会遇到编译器错误),但我对obj-c还是比较陌生的。

我不熟悉JSON解析器,但如果它遵循Cocoa约定,objectWithString将返回一个自动删除的对象。这意味着,除非您保留它,否则它将在运行循环的下一次迭代中被释放。当Cocoa集合类解除分配时,它们释放包含的每个对象,因此类别也将被释放。这就是为什么它在一开始是有效的,但在程序中不是以后

它之所以能够通过将其设置为属性来工作,是因为创建的合成setter保留了类别(假设您使用retain参数设置了属性,我假设您这样做了),所以它不会被释放。这是正确的解决方案,干得好。:)在类别上调用retain也会起作用

Cocoa约定是,如果方法名包含“alloc”或“copy”,或以“new”开头,则返回的对象的retain计数为1,您负责释放它。否则,返回的对象的retain计数为零(它已被自动删除),并将在下一次迭代中通过runloop释放,除非您保留它(在这种情况下,您将负责稍后释放它)

我建议您阅读以下内容:

编辑: 它使用[[NSArray alloc]initWithObjects…]工作的原因是,因为该方法包含“alloc”,返回的数组尚未自动删除,因此在以后访问它时仍然存在