2009-02-11 93 views
98

我最近一直試圖將我的iPhone應用程序的搜索結果存儲在NSUserDefaults集合中。我也使用它來成功保存用戶註冊信息,但由於某種原因,試圖存儲自定義位置類的NSMutableArray始終爲空。在NSUserDefaults中將自定義對象存儲在NSMutableArray中

我試圖轉換的NSMutableArray到NSData的元素作爲這個帖子的,但我得到了相同的結果(Possible to save an integer array using NSUserDefaults on iPhone?

我已經嘗試了代碼示例:

節省:

[prefs setObject:results forKey:@"lastResults"]; 
[prefs synchronize]; 

NSData *data = [NSData dataWithBytes:&results length:sizeof(results)]; 
[prefs setObject:data forKey:@"lastResults"]; 

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:results]; 
[prefs setObject:data forKey:@"lastResults"]; 

負載:

lastResults = (NSMutableArray *)[prefs objectForKey:@"lastResults"]; 

NSData *data = [prefs objectForKey:@"lastResults"]; 
memcpy(&lastResults, data.bytes, data.length); 

NSData *data = [prefs objectForKey:@"lastResults"]; 
lastResults = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

經過以下建議下面我也implemente d NSCoder在我對象(忽略的NSString其臨時的過度使用):

#import "Location.h" 


@implementation Location 

@synthesize locationId; 
@synthesize companyName; 
@synthesize addressLine1; 
@synthesize addressLine2; 
@synthesize city; 
@synthesize postcode; 
@synthesize telephoneNumber; 
@synthesize description; 
@synthesize rating; 
@synthesize priceGuide; 
@synthesize latitude; 
@synthesize longitude; 
@synthesize userLatitude; 
@synthesize userLongitude; 
@synthesize searchType; 
@synthesize searchId; 
@synthesize distance; 
@synthesize applicationProviderId; 
@synthesize contentProviderId; 

- (id) initWithCoder: (NSCoder *)coder 
{ 
    if (self = [super init]) 
    { 
     self.locationId = [coder decodeObjectForKey:@"locationId"]; 
     self.companyName = [coder decodeObjectForKey:@"companyName"]; 
     self.addressLine1 = [coder decodeObjectForKey:@"addressLine1"]; 
     self.addressLine2 = [coder decodeObjectForKey:@"addressLine2"]; 
     self.city = [coder decodeObjectForKey:@"city"]; 
     self.postcode = [coder decodeObjectForKey:@"postcode"]; 
     self.telephoneNumber = [coder decodeObjectForKey:@"telephoneNumber"]; 
     self.description = [coder decodeObjectForKey:@"description"]; 
     self.rating = [coder decodeObjectForKey:@"rating"]; 
     self.priceGuide = [coder decodeObjectForKey:@"priceGuide"]; 
     self.latitude = [coder decodeObjectForKey:@"latitude"]; 
     self.longitude = [coder decodeObjectForKey:@"longitude"]; 
     self.userLatitude = [coder decodeObjectForKey:@"userLatitude"]; 
     self.userLongitude = [coder decodeObjectForKey:@"userLongitude"]; 
     self.searchType = [coder decodeObjectForKey:@"searchType"]; 
     self.searchId = [coder decodeObjectForKey:@"searchId"]; 
     self.distance = [coder decodeObjectForKey:@"distance"]; 
     self.applicationProviderId = [coder decodeObjectForKey:@"applicationProviderId"]; 
     self.contentProviderId = [coder decodeObjectForKey:@"contentProviderId"]; 
    } 
} 

- (void) encodeWithCoder: (NSCoder *)coder 
{ 
    [coder encodeObject:locationId forKey:@"locationId"]; 
    [coder encodeObject:companyName forKey:@"companyName"]; 
    [coder encodeObject:addressLine1 forKey:@"addressLine1"]; 
    [coder encodeObject:addressLine2 forKey:@"addressLine2"]; 
    [coder encodeObject:city forKey:@"city"]; 
    [coder encodeObject:postcode forKey:@"postcode"]; 
    [coder encodeObject:telephoneNumber forKey:@"telephoneNumber"]; 
    [coder encodeObject:description forKey:@"description"]; 
    [coder encodeObject:rating forKey:@"rating"]; 
    [coder encodeObject:priceGuide forKey:@"priceGuide"]; 
    [coder encodeObject:latitude forKey:@"latitude"]; 
    [coder encodeObject:longitude forKey:@"longitude"]; 
    [coder encodeObject:userLatitude forKey:@"userLatitude"]; 
    [coder encodeObject:userLongitude forKey:@"userLongitude"]; 
    [coder encodeObject:searchType forKey:@"searchType"]; 
    [coder encodeObject:searchId forKey:@"searchId"]; 
    [coder encodeObject:distance forKey:@"distance"]; 
    [coder encodeObject:applicationProviderId forKey:@"applicationProviderId"]; 
    [coder encodeObject:contentProviderId forKey:@"contentProviderId"]; 

} 

回答

176

對於陣列中加載自定義對象,這是我用搶的數組:

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"]; 
if (dataRepresentingSavedArray != nil) 
{ 
    NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray]; 
    if (oldSavedArray != nil) 
     objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray]; 
    else 
     objectArray = [[NSMutableArray alloc] init]; 
} 

您應該檢查從用戶默認返回的數據不爲零,因爲我相信解除封存從零導致崩潰。

存檔很簡單,使用下面的代碼:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"]; 

由於f3lix指出的那樣,你需要使你的自定義對象均符合歐盟的NSCoding協議。像下面添加方法應該做的伎倆:

- (void)encodeWithCoder:(NSCoder *)coder; 
{ 
    [coder encodeObject:label forKey:@"label"]; 
    [coder encodeInteger:numberID forKey:@"numberID"]; 
} 

- (id)initWithCoder:(NSCoder *)coder; 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     label = [[coder decodeObjectForKey:@"label"] retain]; 
     numberID = [[coder decodeIntegerForKey:@"numberID"] retain]; 
    } 
    return self; 
} 
+0

我已經將你的代碼和實現NSCoder的對象複製到原型中,但是desp ite來自UserDefaults的NSData有數據,最終數組仍然有0的計數。任何想法?我會嘗試將我的原型上傳到某處 – 2009-02-13 16:31:50

0

請參閱「NSUserDefaults的爲什麼沒能挽救的NSMutableDictionary在iPhone SDK? 「(Why NSUserDefaults failed to save NSMutableDictionary in iPhone SDK?


如果你想(反)序列化的自定義對象,你必須提供的功能(反)序列化的數據(NSCoding協議)。該解決方案你是指與INT作品數組,因爲數組是不是對象,而是一個連續的內存塊。

+0

我認爲您的權利,我會看看到NSCoding(除非你有一個建議linky),本身是由上NSString的對象是所有的,所以我想我可以寫我自己的串行器,並把它們全部放入一個字符串數組 – 2009-02-11 14:56:07

+0

好吧,所以我已經實現了NSCode,但仍然沒有使用NSArchiver – 2009-02-11 16:29:53

0

我認爲它看起來像你的代碼不保存結果陣列的問題。它的加載數據嘗試使用

lastResults = [prefs arrayForKey:@"lastResults"]; 

這將返回數組s通過鑰匙特化。

0

我會建議不要試圖在默認數據庫中存儲這樣的東西。

SQLite很容易拾取和使用。我在我的一個屏幕錄像(http://pragprog.com/screencasts/v-bdiphone)中插入了一段關於我寫的簡單包裝(您可以在不購買SC的情況下獲得代碼)。

在應用程序空間中存儲應用程序數據要乾淨得多。

所有這一切說,如果它仍然是有道理的把這個數據放入默認的數據庫,然後看到帖子f3lix張貼。

+1

謝謝你的建議,但我真的不想開始編寫SQL查詢我在你的例子中看到)只是爲了一個有幾個字符串的對象 – 2009-02-11 16:58:39

13

我想你已經在你的initWithCoder方法得到一個錯誤,至少在所提供的代碼,你不回的「自我」的對象。

- (id) initWithCoder: (NSCoder *)coder 
{ 
    if (self = [super init]) 
    { 
     self.locationId = [coder decodeObjectForKey:@"locationId"]; 
     self.companyName = [coder decodeObjectForKey:@"companyName"]; 
     self.addressLine1 = [coder decodeObjectForKey:@"addressLine1"]; 
     self.addressLine2 = [coder decodeObjectForKey:@"addressLine2"]; 
     self.city = [coder decodeObjectForKey:@"city"]; 
     self.postcode = [coder decodeObjectForKey:@"postcode"]; 
     self.telephoneNumber = [coder decodeObjectForKey:@"telephoneNumber"]; 
     self.description = [coder decodeObjectForKey:@"description"]; 
     self.rating = [coder decodeObjectForKey:@"rating"]; 
     self.priceGuide = [coder decodeObjectForKey:@"priceGuide"]; 
     self.latitude = [coder decodeObjectForKey:@"latitude"]; 
     self.longitude = [coder decodeObjectForKey:@"longitude"]; 
     self.userLatitude = [coder decodeObjectForKey:@"userLatitude"]; 
     self.userLongitude = [coder decodeObjectForKey:@"userLongitude"]; 
     self.searchType = [coder decodeObjectForKey:@"searchType"]; 
     self.searchId = [coder decodeObjectForKey:@"searchId"]; 
     self.distance = [coder decodeObjectForKey:@"distance"]; 
     self.applicationProviderId = [coder decodeObjectForKey:@"applicationProviderId"]; 
     self.contentProviderId = [coder decodeObjectForKey:@"contentProviderId"]; 
    } 

    return self; // this is missing in the example above 


} 

我用

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:results]; 
[prefs setObject:data forKey:@"lastResults"]; 

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"lastResults"]; 
if (dataRepresentingSavedArray != nil) 
{ 
     NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray]; 
     if (oldSavedArray != nil) 
       objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray]; 
     else 
       objectArray = [[NSMutableArray alloc] init]; 
} 

和它的工作非常適合我。

與問候,

斯特凡

相關問題