4

後で使用するためにいくつかの場所を plist ファイルに保存するのに苦労しています。少しグーグルした後、CLLocation の配列自体を保存できないことがわかったので、それを行う方法について疑問に思っていました。

単一の CLLocation オブジェクトを NSDictionary に「シリアライズ」/「デシリアライズ」し、それらの NSDictionaries の配列を 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 — 解決策:

わかりました、私はすべてを理解しました。すぐ下に、私自身の質問に対する 2 つのオプションの解決策を投稿しました。

4

3 に答える 3

3

I like solution 2 but serialization can be simpler if all one is trying to do is write straight to a file.

[NSKeyedArchiver archiveRootObject:arrayOfLocations toFile:path];
于 2013-02-19T19:10:02.913 に答える
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];

次に、その辞書を保存します。

于 2012-04-19T13:44:05.650 に答える
0

数時間の検索の後、シナリオ全体を把握しました。ここにいくつかの解決策があります。最初のものは、私が思いついた最初のものなので、より「汚い」ものですが、2番目のものはよりエレガントです。いずれにせよ、どちらも誰かの役に立つかもしれないので、両方とも残しておきます。

解決策 — 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];
}

NSDictionary 内のすべてのデータを NSStrings に変換するには、superdumb for ループが必要です。これにより、問題なく 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"]]];
于 2012-04-19T22:16:30.867 に答える