2009-06-21 44 views
2

在我的项目中,我正在使用propertyList来维护数据。 plist文件被命名为“DataBase.plist”。 DataBase.plist的根目录是一个字典,其中包含5个字典作为子项目...现在,子字典包含4个字符串,其中一个始终是具有密钥“URL”(不带引号)的Web地址.... i “M运行下面的代码以提取该URL关键字的值,但它不工作了..从属性列表中读取NSDictionary Keys

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLforAll = [[NSString alloc] init]; 
for (id key in rootDict) 
{ 
    if(key == rowString) 
    { 
     NSDictionary *dict = [rootDict objectForKey:key]; 
     URLforAll = [dict objectForKey:@"URL"]; 
    } 
} 

的rowstring是(我的字符串,其值是一样的,在选定单元格的文本测试它,它是准确的)。 请帮助我,如果你可以....我会很感激

+0

这个问题可以更清楚地命名,也许“从属性列表文件中读取NSDictionary键”。它确实没有看到与键值编码有关的任何事情(查看它),当然没有特定的iPhone。相应地重新标记。 – 2009-06-21 05:07:20

回答

3

尝试使用[key isEqualToString: rowString]而不是直接使用==比较key和rowString。我认为==比较了对象的指针值,即使字符串匹配,这些值也不相等。

另外 - 就像旁白一样,在设置之前,您不需要初始化URLforAll。当您将其设置为[dict objectForKey:@"URL"]时,您将失去指向您已创建的对象的指针,并且它将被泄漏。相反,只要说NSString *URLforAll = nil;或创建一个新的字符串和autorelease它,这样的对象会被自动清理:

NSString * URLforAll = [[[NSString alloc] init] autorelease]; 
+1

所有不错的建议。 ==你比较内存地址(指针)是正确的。与C++不同,Objective-C不支持重载操作符。事实上,即使是Java开发人员也面临同样的错误。我可能会避免首先创建一个自动释放对象 - 如果URL forAll(命名较差)在for循环之后为零,则创建一个对象。如果它是从一个方法返回的,它应该只能被自动释放。 – 2009-06-21 05:05:00

+0

第一次 - 谢谢你帮助-isequalToString完美地工作.... ..。 ....和上面的代码后,我添加[URLforAll发布];而不是使用[[[[NSSTring alloc] init] autorelease];内存是否仍然泄漏...如果它确实请告诉我怎么... 请告诉我...并且我读了一些使用autorelease for iphone的建议.... 和关于名称的URLofAll它被更改为这个问题......感谢百万人的帮助 – valiantb 2009-06-21 16:16:50

+1

你根本不需要分配/ init URLforALl。只需将它初始化为零即可。字典的objectForKey:方法将返回给你一个自动释放对象。 – amrox 2009-06-21 16:20:49

2

您还没有通过字典需要循环。只要问一下你想要的数据。

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease]; 
NNSString *URLString = [[rootDict objectForKey:key] objectForKey:@"URL"]; 

// do something or return URLString... 
3

此外,在您的代码:

NSString *URLforAll = [[NSString alloc] init]; 

这从不感觉。以下是一些问题:

  • 您分配了一个对象,然后用URLforAll = [dict objectForKey:@"URL"];不加区分地重写。所以你需要在覆盖之前释放它。
  • 它被分配(即,在循环结束时,你“自己”,并必须将其释放。但 [dict objectForKey:@"URL"]返回一个对象,你并不拥有。因此,在循环结束时,你不知道你是否拥有URLforAll与否。
  • 最后,[[NSString alloc] init]永远是有道理的,因为你应该只使用@"",它返回一个恒定的,空的,NSString这是不受retain/release/autorelease问题。

处理也与isEqualToString的问题,但忽略了AMROX更好的解决方案,代码将是:

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLforAll = @""; 
for (id key in rootDict) { 
     if ([key isEqualToString:rowString]) { 
       NSDictionary *dict = [rootDict objectForKey:key]; 
       URLforAll = [dict objectForKey:@"URL"]; 
     } 
} 
[[URLforAll retain] autorelease]; 
[rootDict release]; 

注意objectForKey可能返回一个内部参考的对象,当你释放字典,因此需要保留的对象,如果你想保持它周围长于字典的生活将变得无效。

amrox的使用:

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLString = [[rootDict objectForKey:key] objectForKey:@"URL"]; 
[[URLString retain] autorelease]; 
[rootDict release]; 
if (!URLString) { 
    URLString = @""; 
} 

是一个更好的解决方案,但你应该undertand有什么问题你原来的解决方案,以及。