メモ帳の作成(7)~設定値の保存

2010. 07. 16
現状ではテキストビューの文字列の内容を編集したり、フォントの種類やサイズを変更しても、アプリケーションを終了すると元の状態に戻ってしまいます。

これらのパラメータをアプリケーションが終了しても保持しておくには、NSUserDefaultsクラスを利用します。


●NSUserDefaultsクラス

NSUserDefaultsクラスはシステムの初期設定と対話するプログラムインターフェイスを提供します。

システムの初期設定は、ユーザの設定に合わせてアプリケーションの動作をカスタマイズすることができます。

例えばアプリケーションで、どの位の大きさでユニットを表示するか、またはどの位の頻度で文書を自動保存するかなどを決めることができます。

アプリケーションは設定の値を割り当てて記録できるように、ユーザのデフォルトデータベースにパラメータを設定します。

パラメータは一般的に、アプリケーションが初期状態で起動する、または初期設定で動作する方法を決定する場合に参照します。

NSUserDefaultsオブジェクトは、実行時にユーザのデフォルトデータベースからアプリケーションの初期設定の読み込に使用します。

NSUserDefaultsは、初期値が必要になる度にユーザのデフォルトデータベースを開くことを避けるため、情報をキャッシュします。

synchronizeメソッドは、ユーザのデフォルトデータベースとメモリ内のキャッシュを、定期間隔で自動的に同期を取ります。

NSUserDefaultsクラスは、float、double、integer、Boolean、URLといった一般的な型へのアクセスに便利なメソッドを提供します。

デフォルトオブジェクトは、NSData、NSString、NSNumber、NSDate、NSArray、NSDictionaryのインスタンス(もしくはコレクションのインスタンスの組み合わせ)のプロパティリストである必要があります。

他の型のオブジェクトを格納する場合、通常はNSDataのインスタンスを生成してアーカイブする必要があります。

詳細は『User Defaults Programming Topics』を参照してください。

NSUserDefaultsが返す値が不変の場合であっても、値のオブジェクトは可変で設定します。

例えば、『MyStringDefault』という値を可変文字列で設定した場合、stringForKey:を使って文字列を取得すると不変となります。

デフォルトデータベースはユーザ毎に自動生成されます。

NSUserDefaultsクラスは、現在ホスト毎の設定をサポートしていません。

これを行うには、CFPreferences API(『Preferences Utilities Reference』を参照)を使用する必要があります。

NSUserDefaultsで正確にホスト毎の設定を読み込むには、NSUserDefaultsのコードにCFPreferencesのコードを混在させることで安全に行えます。

アプリケーションが管理環境をサポートする場合、NSUserDefaultsオブジェクトを使って、ユーザの承認を管理者が管理する設定を行うことができます。

管理環境は、コンピュータラボや教室などで管理者または教師が、特定の方法でシステムを構成することができます。

これらの状況では、ユーザ設定やデフォルト設定を教師が確立することができます。

この方法で設定を管理する場合、アプリケーションは任意の適切な制御を無効にして、その設定を編集することを防ぐ必要があります。

NSUserDefaultsクラスはスレッドセーフです。

NSURLとファイル参照URLの持続性

処理中にNSURLインスタンスを使ってファイルを参照する場合、ロケーションベーストラッキング(file:スキームURLは基本的にパス)とファイルシステム識別トラッキング(file:スキームURLはファイル参照URL)を区別することが重要です。

NSURLを永続化する場合は、その動作を考慮して取得する必要があります。

アプリケーションが識別子でリソースの位置を追跡する場合は、ユーザがファイルを移動しても見つけることができ、その後NSURLのブックマークデータを明示的に書き込むか、ファイル参照URLをエンコードします。

ファイル参照で明らかに制御を超えた追跡を要求する場合は、[NSUserDefaults setURL:forKey:]で出力されるNSUserDefaultsのブックマークの書き込みを信頼するには注意が必要です。

この時、+[NSURL URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:]を呼び出すと、I/Oまたは要求したユーザインターフェイスの相互作用でアプリケーションが処理できる可能性があります。


●設定値の保存の実装

NSUserDefaultsのインスタンスに、テキストビューの文字列(キー:MEMO)、フォント名(キー:FONT NAME)、フォントサイズ(キー:FONT SIZE)を保存します。

- (void)savePreferences {
    // NSUserDefaultsのインスタンスを取得
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // テキストビューの文字列を登録
    [defaults setObject:memoView.text forKey:@"MEMO"];

    // 選択されているフォントの名称を取得
    int row;
    row = [fontPicker selectedRowInComponent:0];
    NSString *fontName = [fontNames objectAtIndex:row];

    // フォント名(文字列)を登録
    [defaults setObject:fontName forKey:@"FONT NAME"];

    // 選択されているフォントサイズを取得
    row = [fontPicker selectedRowInComponent:1];
    NSInteger fontSize = [[fontSizes objectAtIndex:row] intValue];

    // フォントサイズ(int)を登録
    [defaults setInteger:fontSize forKey:@"FONT SIZE"];
}

521


・standardUserDefaults
(NSUserDefaultsクラス)

+ (NSUserDefaults *)standardUserDefaults

共有のデフォルトオブジェクトを返します。

共有のデフォルトオブジェクトがまだ存在しない場合は、以下のドメインの順序で名前を含むリストを検索して生成します。

・NSArgumentDomainで、アプリケーションの引数から解析したデフォルトを構成
・アプリケーションのバンドル識別子でドメインを識別
・NSGlobalDomainで、全てのアプリケーションで見られる意味からデフォルトを構成
・各ユーザの優先言語のための別ドメイン
・NSRegistrationDomainで、一時的なデフォルトを設定し、アプリケーションによる検索が常に成功するように値を設定

デフォルトは現在のユーザ用に初期化されます。

標準検索リストの後続の変更は、このメソッドが再度呼び出されても残ります。

検索リストはこのメソッドが呼び出された初回のみ、標準で保証されます。

共有インスタンスは、allocとinitWithUser:またはinitを使ってカスタムインスタンスを容易に生成することができます。


・setObject:forKey:
(NSUserDefaultsクラス)

- (void)setObject:(id)value forKey:(NSString *)defaultName

標準アプリケーションドメイン内の、指定したデフォルトキーの値を設定します。

valueパラメータはプロパティリストオブジェクト(NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary)のみ設定できます。

NSArrayとNSDictionaryオブジェクトの内容は、プロパティリストオブジェクトである必要があります。

詳細は『Property List Programming Guide』の『What is Property List?』を参照してください。

検索リスト内のアプリケーションドメインの前に、同じキーがドメインに存在する場合、objectForKey:メソッドで返される値はデフォルトの設定に影響を与えません。


●設定値の呼び出しの実装

このメソッドでは、最初に初回起動時のデフォルト値を設定し、その後設定値の呼び出しを行っています。

デフォルトの辞書の登録および呼び出しも、テキストビューの文字列(キー:MEMO)、フォント名(キー:FONT NAME)、フォントサイズ(キー:FONT SIZE)を設定しています。

設定値の呼び出しでは、値を取得した後にテキストビューおよびピッカービューに値を反映させています。

- (void)loadPreferences {
    // NSUserDefaulsのインスタンスを取得
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // デフォルト値の辞書を生成
    NSDictionary *defaultsDic = [NSDictionary dictionaryWithObjectsAndKeys:@"Please write memo.", @"MEMO", @"Helvetica", @"FONT NAME", [NSNumber numberWithInt:18], @"FONT SIZE", nil];

    // デフォルト値の辞書を登録
    [defaults registerDefaults:defaultsDic];

    // メモの文字列の取り出しとテキストビューへの設定
    memoView.text = [defaults stringForKey:@"MEMO"];

    // フォント名の取り出し
    NSString *fontName = [defaults stringForKey:@"FONT NAME"];

    // フォントサイズの取り出し
    NSInteger fontSize = [defaults integerForKey:@"FONT SIZE"];

    // テキストビューのフォントを設定
    memoView.font = [UIFont fontWithName:fontName size:fontSize];

    // ピッカービューのフォント名の選択行を設定
    NSUInteger index = [fontNames indexOfObject:fontName];
    [fontPicker selectRow:index inComponent:0 animated:NO];

    // ピッカービューのフォント名の選択行を設定
    NSString *strSize = [NSString stringWithFormat:@"%d", fontSize];
    index = [fontSizes indexOfObject:strSize];
    [fontPicker selectRow:index inComponent:1 animated:NO];
}

522


・dictionaryWithObjectsAndKeys:
(NSDictionaryクラス)

+ (id)dictionaryWithObjectsAndKeys:(id)firstObject , ...

指定した値とキーのセットを登録して構成された辞書を生成して返します。

このメソッドはdictionaryWithObjects:forKey:と似ており、キーと値のペアで指定する方法のみ異なります。

例:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
    @"value1", @"key1", @"value2", @"key2", nil];

firstObject:新しい辞書に追加する最初の値を指定します。

...:firstObjectに対する最初のキーを指定し、以降は値とキーを交互に指定するnull終端のリストになります。
キーがnilの場合、NSInvalidArgumentExceptionが発生します。


・registerDefaults:
(NSUserDefaultsクラス)

- (void)registerDefaults:(NSDictionary *)dictionary

登録ドメインに指定された辞書の内容を追加します。

登録ドメインが無い場合、指定した辞書を使って生成され、NSRegistrationDomainで検索リストの末尾に追加されます。

登録ドメインの内容はディスクに書き込まれないので、必要に応じてアプリケーションの開始時にこのメソッドを呼び出してください。

アプリケーションのリソースディレクトリにplistファイルを置くことができ、registerDefaults:を呼び出すことによってファイルから内容を読み込むことができます。

dictionary:キーと値を登録したい辞書を指定します。


・stringForKey:
(NSUserDefaultsクラス)

- (NSString *)stringForKey:(NSString *)defaultName

指定したキーに関連付けされている文字列を返します。

戻り値は指定したキーに関連付けされている文字列で、デフォルトが存在しない場合や文字列を含んでいない場合はnilを返します。

返される文字列は不変ですが、元となる値は可変文字列として設定します。

defaultName:現在のユーザのデフォルトデータベース内のキーを指定します。


・integerForKey:
(NSUserDefaultsクラス)

- (NSInteger)integerForKey:(NSString *)defaultName

指定したキーに関連付けされている整数値を返します。

戻り値は指定したキーに関連付けされている整数値で、指定したキーが存在しない場合には0を返します。

defaultName:現在のユーザのデフォルトデータベース内のキーを指定します。


・indexOfObject:
(NSArrayクラス)

- (NSUInteger)indexOfObject:(id)anObject

指定したオブジェクトと同じ値を配列から検索し、対応する最低インデックスを返します。

戻り値はanObjectと同じ値の配列の最低インデックスで、レシーバにanObjectと同じオブジェクトが無い場合はNSNotFoundを返します。

オブジェクトはisEqual:がYESを返すものと見なされます。

重要:anObjectがnilの場合は例外が発生します。


・selectRow:inComponent:animated:
(UIPickerViewクラス)

- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated

ピッカービューの指定したコンポーネントの行を選択します。

row:componentの行を識別する、0から始まる番号を指定します。

component:ピッカービューのコンポーネントを識別する、0から始まる番号を指定します。

animated:YESの場合、新しい値が選択された場合にホイール(コンポーネント)が回転するアニメーションを行い、NOを指定した場合は選択された新しい値がすぐに表示されます。


●savePreferencesメソッドとloadPreferencesメソッドの呼び出し位置

両メソッドを実装しただけでは何も起こりませんので、これらを既存のメソッドから呼び出す必要があります。

したがって、両メソッドはMemo.m内で既存メソッドより前に記述しておく必要があります。

loadPreferencesは、初期化メソッドであるinitではなく、nibファイル展開後のawakeFromNibの最後に[self loadPreferences];を追加して呼び出します。
(太字が追加した部分)

// Nibファイルからの読み込み完了後の初期化メソッド - (void)awakeFromNib {
    [super awakeFromNib];

    // 画面上部のツールバーとピッカービューを隠す
    topToolbar.alpha = 0.0f;
    fontPicker.alpha = 0.0f;

    [self loadPreferences];
}

525

正常に初期化されれば、これまでのInterface Builderのテキストビューにデフォルトで入っていた文字列ではなく、loadPreferencesで定義されている『Please write memo.』に変わるはずです。
(途中で色々試していて上手く動作しない場合は、iPhone Simulatorをリセットしてください)

524

savePreferencesは本書内で、

・テキストビューのテキスト編集終了通知メソッドであるtextViewDidEndEditing:

・ピッカービューの選択行の変更通知メソッドであるpickerView:didSelectRow:inComponent:

とありますので、両メソッドの最後に[self savePreferences];を追加して呼び出します。
(太字が追加した部分)

// テキスト編集終了通知
- (void)textViewDidEndEditing:(UITextView *)view {
    [topToolbar fadeTo:0.0f];    // 上部ツールバーをフェードアウト

    [self savePreferences];
}

526

- (void)pickerView:(UIPickerView *)view didSelectRow:(NSInteger)row inComponent:(NSInteger)compo {
    // フォント一覧側の選択行の番号を取得
    NSUInteger selectedFont = [view selectedRowInComponent:0];

    // 選択されたフォント名を取得
    NSString *fontName = [fontNames objectAtIndex:selectedFont];

    // サイズ一覧側の選択行の番号を取得
    NSUInteger selectedSize = [view selectedRowInComponent:1];

    // 選択されたフォントサイズを取得
    NSString *strFontSize = [fontSizes objectAtIndex:selectedSize];
    CGFloat fontSize = [strFontSize floatValue];

    // テキストビューにフォントを設定
    memoView.font = [UIFont fontWithName:fontName size:fontSize];

    [self savePreferences];
}

527


●設定値の保存確認時の注意点

設定値はXMLで書き出している都合上、Doneボタンを押したりフォントを選択した直後には反映されません。

当方の環境(MacBook Core2Duo/2.2GHz)では、反映されるまで15秒前後かかります。

したがって設定ファイル更新前にアプリケーションをタスクから消去したりすると、設定が反映されず、変更前の状態になります。

ファイルはデフォルトインストールしたiPhone Simulator 4.0の場合、

(ユーザ名)/ライブラリ/Application Support/iPhone Simulator/4.0/Applications/(セッション名?)/Library/Preferences/com.yourcompany.Memo.plist

にあります。

523

このファイルを選択して右カラムに詳細を表示させておき、Doneボタンやフォントを選択すると、ファイルが更新された際に選択が解除されて詳細が消えるので容易に確認できます。



参考文献

NSUserDefaults Class Reference

NSDictionary Class Reference

NSArray Class Reference

UIPickerView Class Reference

基礎からのiOS SDK基礎からのiOS SDK
(2010/10/09)
鶴薗 賢吾、松浦 健一郎 他

商品詳細を見る






bose_soundlink_revolve
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
03 | 2017/04 | 05
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

bose_soundlink_revolve
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