首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何编辑多级属性列表?

如何编辑多级属性列表?
EN

Stack Overflow用户
提问于 2014-07-17 23:49:53
回答 1查看 120关注 0票数 0

我要更改此属性列表profileData.plist中的值

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>profiles</key>
    <array>
        <dict>
            <key>Name</key>
            <string>Default Profile</string>
            <key>size</key>
            <integer>0</integer>
        </dict>
    </array>
    <key>settings</key>
    <dict>
        <key>length</key>
        <string>cm</string>
    </dict>
</dict>
</plist>

我想将密钥size的整数设置为1。我就是这样做的:

代码语言:javascript
运行
复制
// reading Property List as described in Property List Programming Guide
NSError *error = nil;
NSPropertyListFormat format;
NSString *plistPath;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                     NSUserDomainMask, YES) objectAtIndex:0];
plistPath = [rootPath stringByAppendingPathComponent:@"profileData.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
    plistPath = [[NSBundle mainBundle] pathForResource:@"profileData" ofType:@"plist"];
}
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSMutableDictionary *temp = (NSMutableDictionary *)[NSPropertyListSerialization
                                      propertyListWithData:plistXML
                                      options:NSPropertyListMutableContainersAndLeaves
                                      format:&format
                                      error:&error];
if (!temp) {
    DNSLog(@"Error reading plist: %@, format: %ld", error, (long)format);
}

// getting the right dictionary
NSMutableArray *profiles = [temp objectForKey:@"profiles"];
NSMutableDictionary profile0 = [profiles objectAtIndex:0];

// Setting new integer
[profile0 setObject:[NSNumber numberWithInt:1] forKey:@"size"];

// saving objects in reverse
[profiles replaceObjectAtIndex:0 withObject:profile0];
[temp setObject:profiles forKey:@"profiles"];

// writing property list
[temp writeToFile:plistPath atomically:YES];

这段代码可以工作。

我的问题是:这是最好的方法吗?从磁盘读取属性列表是可以的。但是,有必要将属性列表的所有“级别”保存在单独的可变对象中,然后将所有这些对象反向设置到属性列表的最高级别吗?

对我来说,这样做似乎有点复杂,即使当我想象一个具有更多级别的属性列表时也是如此。如果可以这样做那就太好了:

代码语言:javascript
运行
复制
[temp setObject:[NSNumber numberWithInt:1] forKeyPath:@"profiles.0.size"];
EN

回答 1

Stack Overflow用户

发布于 2014-07-18 00:51:30

代码语言:javascript
运行
复制
/*The nature of using a plist or XML in XCode requires you to load the entire contents of the file into memory before doing anything with it (unless you're using a 3rd-party DOM parser for XML), just as you've done here. NSArray & NSDictionary then have the `writeToFile: atomically:` method you're already using to write changes back to disk. 

Of course you can access and change the temp NSMutableDictionary at whichever level you like, but if you want to save the changes then this is pretty much how you have to do it. 

As you imagined, this can be bad for larger/complex data or if you're saving changes all the time. 

I'd suggest you refactor this into multiple methods - right now you're loading the data, making the changes, AND writing back out to file all in the same place, which means you have to do all of that each time.

Break things up so you can do these tasks independently:

 - load plist from disk 
 - create temp copy of plist data as @property
 - make a change to tempdata @property (passing in whatever argument you need); 
 - write changes to disk

This would allow you to make multiple changes to the temp data as needed & only update the data model on disk when you have a bunch to do at once or need to ensure it's up to date (say, before the app goes into the background). This would cut the # of read/writes, but requires you to consider how fresh you need your data model to be & when's the best time to update the changes. 

If you're not stuck w/using plists, you could also look into using JSON, which is faster & lighter, and XCode now has pretty good native support, but writing to a file is the exact same process. For persisting larger, more complex data sets and making easier changes to individual items you might want to consider CoreData.   

..................................
1 other note ... In these lines: 

    NSMutableArray *profiles = [temp objectForKey:@"profiles"];
    NSMutableDictionary profile0 = [self.profiles objectAtIndex:0];

You're declaring `*profiles` within the method, not as a property of the object, so you shouldn't refer to it as `self.profiles`. Surprised this works w/o causing an error (unless you have both? In that case it won't work as expected). After refactoring to separate methods an @property is what you'll want.*/

根据下面的评论进行编辑:

我明白了--在这种情况下,你上面的建议似乎很接近,但方法名是setValue:(id) forKeyPath:(NSString *),而不是setObject...。此外,您还可以对NSNumber使用Obj-C文本语法。

也许可以试试这样的东西:[temp setValue:@1 forKeyPath:@"temp.profiles.0.size"];

(注:尚未对此进行测试。不确定是否需要完整路径(包括keyPath中的temp )。请参阅苹果的KVC programming guideKVC Protocol reference

我不认为这种方法会对速度或性能产生明显的影响,但我还没有对其进行测试。这还假设您正在访问的对象肯定是具有这些特定键的字典。如果结构或键发生变化,这里不会进行自省或错误处理。您的初始方法的一个好处是,您显式地说明了他们可以访问的对象类型&方法/属性,而这是一种开放式的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24808151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档