天天看點

NSCoding協定 NSCoding Protocol Reference

由于 Sqlite資料庫的blob資料和NSData的相容比較好,我想嘗試把一個NSArray存入Sqlite。 Sqlite不支援數組的直接存儲,是以我尋找了一些數組轉化為NSData的方法。網上大多數的解決辦法都是針對于字元數組,eg:   NSArray *array01= [[ NSArray alloc ] initWithObjects : @"1" , @"2" , @"3" , nil ]; 這種數組的解決辦法很簡單,循環周遊數組,然後把每次取出的NSString轉碼成NSData類型,然後對最終的NSData資料進行一次次的循環拼接,實作把數組中所有的字元串拼接成一個完整的NSData,eg:   NSMutableData *data01 =[[ NSMutableData alloc ] init ];

    for (NSString *str in array01) {

       NSString*newStr = [str stringByAppendingString:@","];//添加間隔,為了區分數組的每個元素

       NSData *temp =[newStr dataUsingEncoding:NSASCIIStringEncoding];//建立中間變量存儲将nsstring轉碼成nsdata的資料

       [data01 appendData:temp];//data資料拼接到最終資料data01上

       [temp release];

    }

這樣就實作了一個NSArray字元數組到NSData的轉換。轉換回來也很簡單,把NSData轉換成NSString,然後将NSString分割(這也就是我們為str添加末尾“,”的原因),eg:

     NSString *string01 = [[NSString alloc]initWithData:data01 encoding:NSUTF8StringEncoding];//将NSData資料轉換成NSString類型資料

    NSArray *array02 = [string01 componentsSeparatedByString:@","];//字元串根據@“,”拆分成一個數組,将數組還原

        但是這樣太麻煩了,經過了這麼多次轉換,我就在思考有沒有更簡單的方法,NSData和NSArray的直接轉換。無意間看到了一個網站,我看到了一個方法,運用的是“歸檔”,下面我們來說一下這個方法的實作,eg:

NSData *data02 = [NSKeyedArchiver archivedDataWithRootObject:array01];//通過歸檔對NSArray進行轉碼,儲存了數組的序列

一句代碼就完成了!而且還儲存了數組的有序性。轉換回去也同樣是一句話哦:),eg:

    NSArray *array02 = [NSKeyedUnarchiver unarchiveObjectWithData:data02];//通過發歸檔進行NSData反轉碼,傳回有序列的數組

是不是很友善呢??不是很,是太友善了吧。但是這個時候問題又來了,我如果在數組裡存放的不是NSString類型的對象呢,如果存了自定義的類,是否也可以自動跳轉呢?(有點異想天開。。),于是我自己建立了一個Student類,嘗試相同的方式轉換,發現程式無法運作了,問了同僚,他告訴了我這個秘密。原來所有原生的類都是實作了NSCoding協定,在歸檔的過程中進行了轉碼,是以才可以歸檔成功。我研究了一下NSCoding協定,下面是API給我們的資訊:

NSCoding Protocol Reference

encodeWithCoder:

Encodes the receiver using a given archiver. (required)

- (void)encodeWithCoder:( NSCoder  *) encoder

Parameters
encoder
An archiver object.
Availability
  • Available in iOS 2.0 and later.
Declared In

NSObject.h

initWithCoder:

Returns an object initialized from data in a given unarchiver.(required)

- (id)initWithCoder:( NSCoder  *) decoder

Parameters
decoder
An unarchiver object.
Return Value

self

, initialized using the datain decoder.

Availability
  • Available in iOS 2.0 and later.
Declared In

NSObject.h

NSCoding協定中隻有兩個方法,都是require的方法,一個是把本身的類進行轉碼,一個是逆轉換成類對象,傳回一個對象,我們實戰一下這個協定的用法,看看是否好用,首先寫一個自定義Student類:

@interfaceStudent : NSObject<NSCoding>

@property (nonatomic, retain) NSString *name;

@property (nonatomic, retain) NSString *ID;

-(Student *)initWithName :(NSString*)newName 

                 and : (NSString *)newID;

@end

Student類需要實作協定NSCoding,.m檔案中是這樣的:

@implementationStudent

@synthesize name = _name,ID = _ID;

//初始化學生類

-(Student *)initWithName:(NSString *)newName and:(NSString *)newID{

   self = [super init];

   if (self) {

       self.name = newName;

       self.ID= newID;

    }

   return self;

}

//學生類内部的兩個屬性變量分别轉碼

-(void)encodeWithCoder:(NSCoder *)aCoder{

   [aCoder encodeObject:self.name forKey:@"name"];

   [aCoder encodeObject:self.IDforKey:@"ID"];

}

//分别把兩個屬性變量根據關鍵字進行逆轉碼,最後傳回一個Student類的對象

-(id)initWithCoder:(NSCoder *)aDecoder{

   if (self = [super init]) {

       self.name = [aDecoder decodeObjectForKey:@"name"];

       self.ID= [aDecoder decodeObjectForKey:@"ID"];

    }

   return self;

}

@end

自定義類Student實作了NSCoding協定以後,就可以進行歸檔轉換了,具體實作:

   Student *stu1 = [[Student alloc]initWithName:@"124" and:@"111"];//學生對象stu1

   Student *stu2 = [[Student alloc]initWithName:@"223" and:@"222"];//學生對象stu2

   NSArray *stuArray =[NSArray arrayWithObjects:stu1,stu2, nil];//學生對象數組,裡面包含stu1和stu2

   NSData *stuData = [NSKeyedArchiver archivedDataWithRootObject:stuArray];//歸檔

   NSLog(@"data = %@",stuData);

   NSArray *stuArray2 =[NSKeyedUnarchiver unarchiveObjectWithData:stuData];//逆歸檔

   NSLog(@"array2 = %@",stuArray2);

運作結果如下:

2012-09-25 10:44:24.944MagazineDemo[720:f803] data = <62706c69 73743030d4010203 0405082b 2c542474 6f705824 6f626a65 63747358 2476657273696f6e 59246172 63686976 6572d106 0754726f 6f748001 aa090a1117181920 24252655 246e756c 6cd20b0c 0d105a4e 532e6f62 6a65637473562463 6c617373 a20e0f80 02800680 09d31213 0c141516 524944546e616d65 80048003 80055331 32345331 3131d21a 1b1c1f58 24636c6173736573 5a24636c 6173736e 616d65a2 1d1e5753 74756465 6e74584e534f626a 65637457 53747564 656e74d3 12130c21 22168008 8007800553323233 53323232 d21a1b27 2aa22829 574e5341 72726179 584e534f626a6563 74574e53 41727261 79120001 86a05f10 0f4e534b 6579656441726368 69766572 00080011 0016001f 00280032 0035003a 003c0047004d0052 005d0064 00670069 006b006d 00740077 007c007e 008000820086008a 008f0098 00a300a6 00ae00b7 00bf00c6 00c800ca 00cc00d000d400d9 00dc00e4 00ed00f5 00fa0000 00000000 02010000 00000000002d0000 00000000 00000000 00000000 010c>

2012-09-25 10:44:24.944MagazineDemo[720:f803] array2 = (

   "<Student: 0x6883490>",

   "<Student: 0x68dd3c0>"

)

成功啦:)自定義類Student轉碼成功.