将CLLocation保存到plist文件

4
我正在尝试将多个位置保存到一个plist文件中以备后用,但经过一番搜索后我发现CLLocation数组本身不能被保存,因此我想知道有没有其他更好/更智能/更可靠的方法来实现这一目标。 我考虑创建一对类来将单个CLLocation对象“序列化”/“反序列化”为NSDictionary,然后将这些NSDictionary的数组存储到plist文件中,但我不确定是否还有其他更好的方式。非常感谢您提前的帮助。
编辑:这是我用来在plist中保存数据的函数(c_propertyName从答案中获取代码)。
    - (void) addLocation {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString *path = [documentsDirectory stringByAppendingPathComponent:@"/Locations.plist"];

        NSArray *keys = [curLocation c_propertyNames];
        NSDictionary *dict = [curLocation dictionaryWithValuesForKeys:keys];

        [dict writeToFile: path atomically:YES];
    }

编辑2-解决方案:

好的,我已经找到了答案。在下面,我发布了两个选项的解决方案。

3个回答

3

使用KVC很容易。

以下是NSObject类别的方法,用于获取属性名称(需要<objc/runtime.h>

- (NSArray *)c_propertyNames {
    Class class = [self class];
    u_int count = 0;

    objc_property_t *properties = class_copyPropertyList(class, &count);
    if (count <= 0) {
        return nil;
    }
    NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, count)];

    NSMutableSet *retVal = [NSMutableSet setWithCapacity:count];
    [set enumerateIndexesWithOptions:NSEnumerationConcurrent 
                          usingBlock:^(NSUInteger idx, BOOL *stop) {
                              const char *propName = property_getName(properties[idx]); 
                              NSString *name = [NSString stringWithUTF8String:propName];
                              [retVal addObject:name];
                          }];
    return [retVal allObjects];
}

然后像这样使用它:
NSArray *keys = [yourLocation c_propertyNames];
NSDictionary *dict = [yourLocation dictionaryWithValuesForKeys:keys];

然后保存该字典。

分类代码运行良好:它填充了“keys”NSArray,但是一旦我执行[dict writeToFile:path automatically:YES]; 就没有写入到文件中。如果您愿意,我已经更新了我的问题,并提供了相关代码。谢谢! - holographix
好的,我进行了几次实验,发现如果在NSDictionary中包含"clientLocation"键的元素,则不会将其写入到plist文件中,否则它可以正常工作。也许这是因为该字段是一个具有相当多字符的字符串所致。以下是该元素的内容:<00000000 ffff0000 94092907 20413b40 6a5c4eeb 797455c0 a6f71fc4 7fde7d40 00000000 00000000 00000000 0000f0bf 00000000 0000f0bf 00000000 0000f0bf 00000000 0000f0bf 00000000 0000f0bf 00000000 0000f0bf 00000000 0000f0bf bc043f09 c140b541 64000000 00000000 00000040 00000000>。 - holographix
好的,谜团解开了,我必须通过循环来解析数据。我会发布另一个解决方案,将我的代码与你的代码结合起来。 - holographix

3

我喜欢解决方案 2,但是如果你想要直接写入文件,那么序列化可以更加简单。

[NSKeyedArchiver archiveRootObject:arrayOfLocations toFile:path];

真不错.. :) 干得好。 - holographix

0

经过几个小时的搜索,我已经弄清了整个情况。

这里有几个解决方案:第一个比较“粗略”,因为这是我首先想到的,而第二个则更加优雅。不管怎样,我会放置它们,因为也许对某些人来说两种方法都很实用。

解决方案-1

在mit3z的帮助下,我能够组合各个部分来找到解决方案。

正如他所指出的那样,您可以将此方法实现到NSObject的类别中:

 - (NSArray *)c_propertyNames;

(查看他的回复以获取此部分代码和更多详细信息)

这使我有自由去做这样的事情:

- (void) addLocation {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"/Locations.plist"];

    NSArray *keys = [curLocation c_propertyNames]; // retrieve all the keys for this obj
    NSDictionary *values = [self.curLocation dictionaryWithValuesForKeys:keys];
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    for(NSString *key in keys) {
        NSString *aaa = [NSString stringWithFormat:@"%@", (NSString *)[values valueForKey:key]];
        [dict setValue:aaa forKey:key];
    }

    [dict writeToFile:path atomically:YES];
}

需要使用超级愚蠢的for循环将NSDictionary中的所有数据转换为NSString,以便可以将它们写入plist文件而不会出现问题。如果您只是创建字典,然后立即尝试保存它,那么您将无法成功。

通过这种方式,我可以将所有CLLocation obj“序列化”为dict,然后写入plist文件。

解决方案-2

我想出了一种非常简单(而且更优雅)的方法:使用NSCoding。由于我意识到CLLocation数据类型符合NSCoding,因此您可以通过NSKeyedArchiver调用数据归档器来获取描述数组的blob,然后将其直接存储到plist中,如下所示:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"/Locations.plist"];
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];

[data setValue:[NSKeyedArchiver archivedDataWithRootObject:arrayOfLocations] forKey:@"LocationList"];
[data writeToFile:path atomically:YES];
[data release];

就这么简单!:)

基于相同的原则,您可以通过NSKeyUnarchiver轻松获取您的数据:

self.arrayOfLocations = [[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData: (NSData *)[dict objectForKey:@"LocationList"]]];

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