5

I (başvuru belgeleri klasöründe) bir .plist dosyasındaki verilerin bir demet depolamak ediyorum ve bu gibi yapılandırılmış oluyor: Sadece
NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFile] ile geri almak durumundaÇok boyutlu NSMutableArrays'i depolamanın ve almanın en iyi yolu nedir?

Dictionary { 
    "description" = "String Value", 
    "sections" = Array (
     Array (
      Number, 
      ... 
      Number 
     ), 
     Array (
      Number, 
      ... 
      Number 
     ) 
    ), 
    "items" = Array (
     Array (
      Number, 
      ... 
      Number 
     ), 
     Array (
      Number, 
      ... 
      Number 
     ) 
    ) 
} 

yapmayacağım Sayı nesnelerini değiştirebilir, doğru mu? Bu yüzden şu anda verilerde yineleniyorum ve her şeyin değişebilir bir versiyonunu oluşturuyorum ve bir örnekte çalıştı, ama şimdi her şey değişebilir olduğunda bana mutating method sent to immutable object'u anlatıyor.

Bunu yapmanın daha kolay/daha iyi yolu var mı? Bir fark yaratırsa, verilerim sadece tamsayı ve boole'lardır.

+0

Bize bu yöntemi hangi nesneyle gönderdiğimiz gibi biraz daha fazla bilgi verebilir ve muhtemelen yeni sürümü oluşturmak için kullandığınız kodu ve çalışma zamanı hatası tarafından oluşturulan kodu gönderir misiniz? –

+0

Ayrıca değerleri düzenlemeye başlamadan önce dizilerin değiştirilebilir kopyalarını mı yapıyorsunuz? – vfn

cevap

9

Tüm bunları yazmak yerine özel sınıf önemsiz, NSPropertyListSerialization kullanmalısınız. Özellikle, propertyListWithData:options:format:error: yöntemine bakın. Örnek kullanım: Bu, tüm kaplar kesilebilir yapmak ama değiştirilemez yaprak düğümleri (örneğin NSStrings) tutacak

NSMutableDictionary *d = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:@"path/to/file"] 
                    options:NSPropertyListMutableContainers 
                    format:NULL 
                    error:NULL]; 

. Ayrıca yaprakların değişebilir hale getirilmesi için bir seçenek de var.

+0

+1 Bu ilgi çekicidir.Apple'ın belgeleri, “options” parametresinin, okunurken (burada gösterildiği gibi) kullanılmayacağını belirtir; ancak aslında, plist dosyasını * yazarken * kullanılır, böylece veriler okunabilir olduğunda değiştirilebilir. Bkz. Http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSPropertyListSerialization_Class/Reference/Reference.html –

+0

Mülkün OO avantajlarını elde etmek için özel bir sınıf için hala tartışacağım. erişimciler, okuma ve yazma yöntemlerini kapsüllemek için kullanılır; ancak bu teknik, basit bir okuma-değiştirme-yazma işleminin söz konusu olduğu durumlar için kesinlikle yardımcı olacaktır. Harika şeyler! –

+0

Evet, kolaylık sağlamak için özel sınıf yoluna gittim, ancak bu oldukça basit görünüyor. Giriş için teşekkürler. – kbanman

8

Genellikle yükleme ve kaydetme işlemlerini gerçekleştirecek bir veya daha fazla özel sınıf oluşturmayı daha kolay buluyorum.

MyThing.h

@interface MyThing : NSObject 
{ 
    NSString * description; 
    NSMutableArray * sections; 
    NSMutableArray * items; 
} 
@property (copy) NSString * description; 
@property (readonly) NSMutableArray * sections; 
@property (readonly) NSMutableArray * items; 
- (void)loadFromFile:(NSString *)path; 
- (void)saveToFile:(NSString *)path; 
@end 

MyThing.m

@implementation MyThing 
@synthesize description; 
@synthesize sections 
@synthesize items; 

- (id)init { 
    if ((self = [super init]) == nil) { return nil; } 
    sections = [[NSMutableArray alloc] initWithCapacity:0]; 
    items = [[NSMutableArray alloc] initWithCapacity:0]; 
    return self; 
} 

- (void)dealloc { 
    [items release]; 
    [sections release]; 
} 

- (void)loadFromFile:(NSString *)path { 
    NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:path]; 
    [self setDescription:[dict objectForKey:@"description"]]; 
    [sections removeAllObjects]; 
    [sections addObjectsFromArray:[dict objectForKey:@"sections"]]; 
    [items removeAllObjects]; 
    [items addObjectsFromArray:[dict objectForKey:@"items"]]; 
} 

- (void)saveToFile:(NSString *)path { 
    NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys: 
          description, @"description", 
          sections, @"sections", 
          items, @"items", 
          nil]; 
    [dict writeToFile:path atomically:YES]; 
} 

@end; 

önüne aldığımızda: Bu açıkça mutableArrays diziler dönüştürme sağlar tamamlandığında, tüm paketleme ve ambalajlama kodunu loadFromFile ve saveToFile yöntemlerinde kapsülleyebilirsiniz. Bu yaklaşımın önemli faydası da ana program çok daha kolay alır olduğunu ve bu özellikler olarak veri yapısının elemanlarını erişmesine izin verir:

MyThing * thing = [[MyThing alloc] init]; 
[thing loadFromFile:@"..."]; 
... 
thing.description = @"new description"; 
[thing.sections addObject:someObject]; 
[thing.items removeObjectAtIndex:4]; 
... 
[thing saveToFile:@"..."]; 
[thing release]; 
+0

Vay, bu tam bir cevap, efendim :) Bu çok mantıklı, neden aklımdan geçmediği konusunda hiçbir fikrim yok. Teşekkürler bir demet! – kbanman

1

Ne istiyorsun derin değişken kopyasıdır. Kakao bunu yapmanın bir yolunu içermez. Bir kaç kişi daha önce bu tür derin kopya uygulamaları yazmıştır (example).

Ancak, Core Foundation, her ikisi de özellik listesi nesnelerini derin değişkenli kopyalar oluşturmak için disk desteği ve detable veri türleri olarak diskte özellik listelerinde okuma desteği olan CFPropertyList API içerir. (Ve, elbette, Core Foundation'ın emlak listesi türleri arasında Cocoa ile köprüsüz bir köprü var, yani bir NSArray bir CFArray ve tam tersi.)

İlgili konular