Nav(17)~Detail Edit(2)

2011. 01. 16
●データ変換を行うPresidentクラスの作成

詳解 Objective-C 2.0』によりますと、アーカイブとは複数のオブジェクトをその相互関係も含めてバイト列に変換したもの(バイナリファイル)で、オブジェクトをデータ変換してバイト列にすることをエンコード(アーカイブ化)、その逆をデコード(アンアーカイブ化)と呼びます。

今回使用するプロパティリストPresidents.plistはアーカイブなので、データをデコードして取り出す(デコーダー)、またはエンコードしてデータを格納する(コーダー)メソッドを定義したクラスPresidentを作成します。

Classesを右クリックして『追加』→『新規ファイル...』を選択し、左ペインのiOSからCocoa Touch Classを選択、右上ペインでObjective-C class(Subclass ofはNSObject)で、ファイル名をPresidentとして作成します。

1073


●ヘッダファイルPresident.hの編集

アーカイブ化したプロパティリストのデータ変換を行うには、NSCodingプロトコルを採用し、エンコードを行うencodeWithCoder:メソッドとデコードを行うinitWithCoder:メソッドを実装する必要があります。

またプロパティリストPresidents.plistの中身は辞書なので、データを取得するためのキーとプロパティを宣言します。
(太字が追加した部分)

#import <Foundation/Foundation.h>

#define kPresidentNumberKey @"President"
#define kPresidentNameKey @"Name"
#define kPresidentFromKey @"FromYear"
#define kPresidentToKey @"ToYear"
#define kPresidentPartyKey @"Party"


@interface President : NSObject <NSCoding> {
    int number;
    NSString *name;
    NSString *fromYear;
    NSString *toYear;
    NSString *party;

}

@property int number;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *fromYear;
@property (nonatomic, retain) NSString *toYear;
@property (nonatomic, retain) NSString *party;


@end

1074

最初に#defineで定義している5つの定数は、プロパティリストPresidents.plistの辞書から値を取り出すためのキーです。

辞書は歴代米国大統領のデータが格納されていて、初代からの連番になっているint値Presidentと、文字列として大統領の名前Name、任期の開始年FromYear、終了年ToYear、所属政党Partyとなっています。

次にクラス宣言でNSCodingプロトコルを採用しています。

そして各データ取得のためのインスタンス変数およびプロパティの宣言を行っています。


●ソースファイルPresident.mの編集

ソースファイルでは5つのプロパティと、NSCodingの2つの必須メソッドencodeWithCoder:とinitWithCoder:の実装を行います。
(太字が追加した部分)

#import "President.h"

@implementation President

@synthesize number;
@synthesize name;
@synthesize fromYear;
@synthesize toYear;
@synthesize party;


- (void)dealloc {
    [name release];
    [fromYear release];
    [toYear release];
    [party release];

    [super dealloc];
}

#pragma mark -
#pragma mark NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeInt:self.number forKey:kPresidentNumberKey];
    [aCoder encodeObject:self.name forKey:kPresidentNameKey];
    [aCoder encodeObject:self.fromYear forKey:kPresidentFromKey];
    [aCoder encodeObject:self.toYear forKey:kPresidentToKey];
    [aCoder encodeObject:self.party forKey:kPresidentPartyKey];
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.number = [aDecoder decodeIntForKey:kPresidentNumberKey];
        self.name = [aDecoder decodeObjectForKey:kPresidentNameKey];
        self.fromYear = [aDecoder decodeObjectForKey:kPresidentFromKey];
        self.toYear = [aDecoder decodeObjectForKey:kPresidentToKey];
        self.party = [aDecoder decodeObjectForKey:kPresidentPartyKey];
    }
    return self;
}


@end

1075

最初に5つのプロパティの実装と、deallocで4つのプロパティ解放を行います。
(ビューは扱わないのでviewDidUnloadはありません)

プロパティnumberはint値なので、deallocでの解放は行いません。
(記述すると『Invalid receiver type 'int'』という警告が発生します)

次にNSCodingプロトコルの必須メソッド2つを実装します。

引数名が本書やサンプルコードと異なりますが、Xcodeで入力した際に自動補間された値をそのまま流用したためで、内容は変わりません。

encodeWithCoder:メソッドは、指定したアーカイバでレシーバをエンコードするメソッドで、ここではencodeInt:forKey:encodeObject:forKey:メソッドを使用して、5つのプロパティをそれぞれのキーでエンコードしています。

initWithCoder:メソッドイニシャライザで、指定したアンアーカイバの中のデータから、初期化したオブジェクトを返すメソッドで、decodeIntForKey:decodeObjectForKey:メソッドを使用して、5つのプロパティをそれぞれのキーでデコードしています。

initWithCoder:メソッドでは最初にスーパークラスによる初期化を行っていますが、『super initWithCoder:aDecoder』ではなく『super init』となっています。

詳解 Objective-C 2.0』によると『スーパークラスがNSCodingプロトコルに適合していない場合は [super init] でよい』と説明されており、PresidentクラスのスーパークラスはNSObjectクラスで、NSObjectクラス自体はNSCodingプロトコルに適合していないため、このような記述になっています。
(NSCodingプロトコルに適合しているかどうかは、クラスリファレンスの冒頭にある『Conforms to』欄にNSCodingが含まれているかどうかで判別できます)

また無条件で初期化せずにif文で判定しているのは、瀧内元気さんの『something new and exciting/Objective-Cのオブジェクト初期化処理について』や、手塚文博さんの『viva Cocoa/Objective-C 入門 第4章 MyClip プロジェクト』によると、スーパークラスでの初期化が正常に行われなかった場合に初期化処理をスルーするためとなっています。

ちなみに、encodeInt:forKey:とencodeObject:forKey:はNSKeyedArchiverクラス、decodeIntForKey:とdecodeObjectForKey:はNSKeyedUnarchiverクラスのメソッドで、これらのメソッドはNSCoderクラスに同名メソッドがありますが、NSCoderはNSKeyedArchiverおよびNSKeyedUnarchiverのスーパークラスであり、NSCoderは抽象クラスですので同クラスのメソッドを直接呼び出すことはなく、実際に呼び出すのはNSKeyedArchiverとNSKeyedUnarchiverクラスのメソッドということになります。


encodeWithCoder:

- (void)encodeWithCoder:(NSCoder *)encoder

指定したアーカイバでレシーバをエンコード(アーカイブ)します。

encoder:アーカイバオブジェクト(アーカーブするNSCoderのインスタンス)を指定します。


initWithCoder:

- (id)initWithCoder:(NSCoder *)decoder

指定したアンアーカイバの中のデータから、初期化したオブジェクトを返します。

decoder:アンアーカイバオブジェクトを指定します。


encodeInt:forKey:

- (void)encodeInt:(int)intv forKey:(NSString *)key

指定したint値を関連付けするキーを指定してエンコードします。

intv:エンコードする値を指定します。

key:intvに関連付けするキーを指定します。
この値はnil以外にする必要があります。


encodeObject:forKey:

- (void)encodeObject:(id)objv forKey:(NSString *)key

指定したオブジェクトを関連付けするキーを指定してエンコードします。

objv:エンコードする値を指定します。
この値はnilになる場合があります。

key:objvに関連付けするキーを指定します。
この値はnil以外にする必要があります。


decodeIntForKey:

- (int)decodeIntForKey:(NSString *)key

指定したキーに関連付けされた整数値をデコードします。

戻り値はkeyに関連付けされた整数値です。

keyが存在しなかった場合は0を返します。

アーカイブされていた値が整数でも異なるサイズでエンコードされていた場合、型は変換されます。

アーカイブされていた値がデフォルトの整数のサイズよりも大きくて収まらない場合、メソッドはNSRangeExceptionを発生させます。

key:現在デコードするスコープ内にアーカイブされているキーを指定します。
keyはnil以外である必要があります。


decodeObjectForKey:

- (id)decodeObjectForKey:(NSString *)key

指定したキーに関連付けされたオブジェクトをデコードして返します。

戻り値はkeyに関連付けされたオブジェクトです。

keyが存在しなかった場合、またはkeyがnilの場合はnilを返します。

key:現在デコードするスコープ内にアーカイブされているキーを指定します。
keyはnil以外である必要があります。


●サブビューコントローラPresidentsViewControllerと詳細ビューコントローラPresidentDetailControllerクラスの作成

両クラスとも旧版の本書ではUIViewController subclassテンプレートを使用していますが、どちらもテーブルビューを扱うので、ここでは素直にUITableViewController subclassテンプレートを使用して作成します。

Classesを右クリックして『追加』→『新規ファイル...』を選択し、左ペインのiOSからCocoa Touch Classを選択、右上ペインでUIViewController subclass(オプションはUITableViewController subclass)で、ファイル名をPresidentsViewControllerとPresidentDetailControllerとして作成します。
(サブビューコントローラは複数形のPresidents、詳細ビューコントローラは単数形のPresidentなことに注意してください)

1076



参考文献

NSCoding Protocol Reference

NSCoder Class Reference

NSKeyedArchiver Class Reference

NSKeyedUnarchiver Class Reference

something new and exciting/Objective-Cのオブジェクト初期化処理について 

viva Cocoa/Objective-C 入門 第4章 MyClip プロジェクト

詳解 Objective-C 2.0 第3版詳解 Objective-C 2.0 第3版
(2011/12/28)
荻原 剛志

商品詳細を見る

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る






Lifestyle 650 home entertainment system
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
10 | 2017/11 | 12
Sun Mon Tue Wed Thu Fri Sat
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Lifestyle 650 home entertainment system
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR