實作 NSCoding

NSCoding 是一個 protocol,裡頭只有兩個 method 要實作

@protocol NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;
@end

encodeWithCoder: 的用途是將我們的物件透過 NSCoder 轉成 NSData,至於 initWithCoder: 剛好相反,就是透過 NSCoder,再把 NSData 轉回物件。

假如我們現在有一個叫做 KKSongTrack 的 class,用來代表 KKBOX 裡頭的一首歌,裡頭只有 songName、albumName 與 artistName 三個 property,這三個 property 都是 NSString。

@interface KKSongTrack : NSObject <NSCoding>
@property (strong, nonatomic) NSString *songName;
@property (strong, nonatomic) NSString *albumName;
@property (strong, nonatomic) NSString *artistName;
@end

在實作的時候,我們就可以用 NSCoder 的相關 method 對資料做 encode 與 decode。由於我們的 property 都是 NSString,都是 Objective-C 物件,所以我們選擇 encodeObject:forKey: 以及 decodeObjectForKey:。實作如下:

#import "KKSongTrack.h"

static NSString *const kSongNameKey = @"song_name";
static NSString *const kAlbumNameKey = @"album_name";
static NSString *const kArtistNameKey = @"artist_name";

@implementation KKSongTrack

- (NSString *)description
{
  return [NSString stringWithFormat:@"<%@ %p %@ - %@ - %@>",
    NSStringFromClass([self class]), self,
    self.songName, self.albumName, self.artistName];
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    if (self) {
        self.songName = [coder decodeObjectForKey:kSongNameKey];
        self.albumName = [coder decodeObjectForKey:kAlbumNameKey];
        self.artistName = [coder decodeObjectForKey:kArtistNameKey];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.songName forKey:kSongNameKey];
    [aCoder encodeObject:self.albumName forKey:kAlbumNameKey];
    [aCoder encodeObject:self.artistName forKey:kArtistNameKey];
}

@end

除了 Objective-C 物件型別外,NSCoder 還有處理 BOOL、整數以及浮點數相關的 method 可以使用。

接下來如果我們想把歌曲轉成 NSData:

KKSongTrack *song = [[KKSongTrack alloc] init];
song.songName = @"orz 之歌";
song.albumName = @"orz 專輯";
song.artistName = @"orz";
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:song];

把 NSData 再轉回 KKSongTrack:

KKSongTrack *decodeSong = [NSKeyedUnarchiver unarchiveObjectWithData:data];

results matching ""

    No results matching ""