【问题标题】:Why doesen't it work to write this NSMutableArray to a plist?为什么将此 NSMutableArray 写入 plist 不起作用?
【发布时间】:2010-04-27 15:09:19
【问题描述】:

已编辑。

嘿,我正在尝试将 NSMutableArray 写入 plist。 编译器没有显示任何错误,但无论如何它都不会写入 plist。 我也在真机上试过,不只是模拟器。

基本上,这段代码的作用是,当您单击UITableViewCellaccessoryView 时,它会按下indexPath,编辑NSMutableArray 并尝试将NSMutableArray 写入plist。然后它重新加载提到的数组(从多个 plist 中)并从数组中重新加载 UITableView 中的数据。

代码:

NSIndexPath *indexPath = [table indexPathForRowAtPoint:[[[event touchesForView:sender] anyObject] locationInView:table]];

[arrayFav removeObjectAtIndex:[arrayFav indexOfObject:[NSNumber numberWithInt:[[arraySub objectAtIndex:indexPath.row] intValue]]]];

NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:@"arrayFav.plist"];
NSLog(@"%@ - %@", rootPath, plistPath); 


[arrayFav writeToFile:plistPath atomically:YES];    

// Reloads data into the arrays
[self loadDataFromPlists];

// Reloads data in tableView from arrays
[tableFarts reloadData];

CFShow() 在数组之后删除其中一个显示:

<CFArray 0x6262110 [0x2c810a0]>{type = mutable-small, count = 4, values = (
    0 : <CFNumber 0x6502e10 [0x2c810a0]>{value = +3, type = kCFNumberSInt32Type}
    1 : <CFNumber 0x6239de0 [0x2c810a0]>{value = +8, type = kCFNumberSInt32Type}
    2 : <CFNumber 0x6239dc0 [0x2c810a0]>{value = +10, type = kCFNumberSInt32Type}
    3 : <CFNumber 0x6261420 [0x2c810a0]>{value = +40, type = kCFNumberSInt64Type}

DEBUG-INFO:writeToPlist 显示 YES,我尝试在再次填充之前释放所有数组,将它们设置为 nil,将 atomically 设置为 NO。

【问题讨论】:

  • 你为什么要使用numberWithInt:创建一个NSNumber然后调用intValue呢?为什么不直接使用 int...?
  • 因为indexOfObject:需要一个对象。
  • 请先显示您在哪里创建对象并将对象添加到arrayFav 的代码?很可能,对象包含某些与 plist 不兼容的类型。
  • NSString *plistFavPath = [[NSBundle mainBundle] pathForResource:@"arrayFav" ofType:@"plist"]; arrayFav = [[NSMutableArray alloc] initWithContentsOfFile:plistFavPath];
  • 返回 YES 表示已成功写入文件。为什么你认为没有?您是否在模拟器上运行它并查看应用程序文件夹中的 plist 文件?问题可能在于您对文件的阅读而不是写作。

标签: iphone objective-c nsmutablearray plist


【解决方案1】:

正如下面的 cmets 中所讨论的,这里的实际问题是 plist 正在从两个不同的位置读取和写入。在应用程序的某处,有一段代码可以将文件读入类似于这样的数组:

NSString *plistFavPath = [[NSBundle mainBundle] pathForResource:@"arrayFav" 
                                                         ofType:@"plist"]; 
arrayFav = [[NSMutableArray alloc] initWithContentsOfFile:plistFavPath];

此逻辑从应用程序包中读取数组,该包是只读位置,是分布式应用程序的一部分。稍后当编辑的数组被持久化时,使用类似这样的代码:

NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                          NSUserDomainMask,
                                                          YES) objectAtIndex:0];
NSString *plistPath = [rootPath 
                          stringByAppendingPathComponent:@"arrayFav.plist"];
NSLog(@"%@ - %@", rootPath, plistPath); 
[arrayFav writeToFile:plistPath atomically:YES];   

这里的结果是更新的文件被写入应用程序的文档目录,但从未从那里读取,看起来文件没有正确保存。要更正此问题,您应该更改读取文件的代码以使用您正在写入的相同路径。

如果您需要在数组被编辑之前分发默认版本的 plist 以在初始启动时使用,您可以继续在您的包中包含该文件的一个版本,然后将代码添加到您的应用程序委托以检查如果文件存在于文档目录中并且不存在,则将包的默认文件版本复制到适当的位置。

【讨论】:

  • 什么..?不?我正在使用这种方法获取路径:NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *plistPath = [rootPath stringByAppendingPathComponent:@"arrayFav.plist"];
  • 在这种情况下,在我看来,您可能正在做的是从一个地方(您的应用程序包)读取 plist 并将其写入另一个地方(您的应用程序文档目录)。因此,您将拥有两个 plist 副本。当我在对上面原始问题的评论中询问您是如何开始创建数组时,您提供的代码表明您正在从包中读取文件,因此我假设您正在尝试将更新后的文件写入相同的地方。将文件写入Documents目录后,当你重新加载它时,你是如何获得路径的?
  • 换句话说,你在哪里这样做: NSString *plistFavPath = [[NSBundle mainBundle] pathForResource:@"arrayFav" ofType:@"plist"]; arrayFav = [[NSMutableArray alloc] initWithContentsOfFile:plistFavPath];这只是第一次读取文件,还是每次启动时都会发生,导致您保存到 docs 目录的更改被忽略?
  • 杰森,你是对的,我正在阅读和写作两个不同的地方。如果您编辑您的答案,我会选择它作为正确的答案。
  • 谢谢您,我现在就可以修复它! :)
【解决方案2】:
[yourMutableArray writeToFile:fileName atomically:YES];

这应该可行。 NSMutableArray 继承自 NSArray,它有一个 method 来写入 plist。

【讨论】:

  • 谢谢,应该可以,但它似乎不起作用。查看更新后的帖子。
  • 应该可以。检查您的数组内容以确保其中只有 NSString、NSData、NSArray 或 NSDictionary 对象。检查 writeToFile 返回的 BOOL 结果。阅读 writeToFile 的描述了解更多详情。
  • 数组实际上包含NSNumber-s。这和它有什么关系吗?
【解决方案3】:

如果您的数组包含自定义对象,writeToFile:atomically: 将不起作用。

如果您的数组包含不是 Plist 对象的自定义对象(NSArray、NSDictionary、NSString、NSNumber 等),那么您将无法使用此方法。此方法仅适用于 Plist 对象。

另一种选择是使用 NSCoding 协议,并以这种方式将对象写入磁盘。

【讨论】:

  • 数组包含NSNumber-s。
  • 编辑:根据 CFShow 它实际上包含 CFNumbers。
【解决方案4】:

是的

看看Property List Programming Guide

phoneNumbers 是一个 NSMutableArray

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
    NSString *error;
    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *plistPath = [rootPath stringByAppendingPathComponent:@"Data.plist"];
    NSDictionary *plistDict = [NSDictionary dictionaryWithObjects:
            [NSArray arrayWithObjects: personName, phoneNumbers, nil]
            forKeys:[NSArray arrayWithObjects: @"Name", @"Phones", nil]];
    NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict
                            format:NSPropertyListXMLFormat_v1_0
                            errorDescription:&error];
    if(plistData) {
        [plistData writeToFile:plistPath atomically:YES];
    }
    else {
        NSLog(error);
        [error release];
    }
    return NSTerminateNow;
}

【讨论】:

  • 是的,但是我如何从一个 NSMutableArray 中创建一个 NSDictionay?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-11
  • 2021-06-06
相关资源
最近更新 更多