2012年6月13日水曜日

NSUserDefaultsを使って、簡単なデータを保存する!iphoneアプリの作りかた

iphoneアプリを作っていて、またハマってしまったのでメモ。
今日は、NSUserDefaultsを使って、簡単なデータを保存する方法です。



【やりたいことを画像で説明します!】
文章で説明するのはちょっと大変なので、
画像を貼ってご説明したいと思います。



←こういうテーブルビューがあって、
 データを追加したり、削除したりすることが出来ます。

←追加ボタンを押したところ。
 ピッカーで選択した情報が、
 テーブルビューに反映されます。

←削除ボタンを押したところ。
 削除ボタンが「完了」に変わって、
 情報の左側にマイナスマークが出ます。

←マイナスマークを選択すると、
 Deleteボタンが出てきて、
 Deleteボタンを押すと、情報が削除されます。












こんな感じでテーブル内の情報を編集し、
その情報を次にアプリを開いた時も保存しておけるように、
今回はNSUserDefaultsを使用しました!


【それでは早速中身の解説です!】


これが全部のソースですが、
ちょっと長いので、すこしづつ解説していきたいと思います。

-----

@implementation okiniiri
@synthesize customButton1;
@synthesize categoryTableView;
@synthesize picker;
@synthesize donebtn;
@synthesize doneview;
@synthesize sakujyobtn;
@synthesize contents;


- (void)viewDidLoad {
    [super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
//-- カスタムボタンの設定 その1 --//
self.customButton1 = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
self.customButton1.frame = CGRectMake(8.0, 5.0, 30.0, 30.0);
[self.customButton1 setImage:[UIImage imageNamed:@"back.png"] forState:UIControlStateNormal];
[self.customButton1 addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
[self.view insertSubview:self.customButton1 atIndex:2];

//arrayforkeyで保存されているファイルを呼び出す
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *array;
array = [_userDefaults arrayForKey:@"datacontent"];
if (array) {
//ファイルがあった場合は、contentsにかき出す
contents =  [array mutableCopy];
} else {
//ファイルがなかったら、arrayforkeyでファイルを作成、保存する
contents = [[NSMutableArray alloc] initWithObjects:@"aa",@"a", @"b", @"c", nil];
NSArray *array = contents;
[_userDefaults setObject:array forKey:@"datacontent"];
[_userDefaults synchronize];
}

 
activities = [[NSMutableArray alloc] initWithObjects:
@"11111",  
@"222222",  
@"33333"
@"4444",  
nil];
sakujyobtn.title = @"削除";
}

//テーブルのセルの行を決定
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [contents count];
}
//テーブルに表示する内容を決定する
- (UITableViewCell *)tableView:(UITableView *)tableView 
cellForRowAtIndexPath:(NSIndexPath *)indexPath {

//同じ形式のセルを使うため、そのセルを再利用する
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
    if (cell == nil) {

//基本となるセルがまだ出来てなかったらセルを作成する
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
  reuseIdentifier:@"identifier"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell autorelease];
    }
    
//indexpathに表示するテキストを決定する
    if (indexPath.row < [contents count]) {
        cell.textLabel.text = [contents objectAtIndex:indexPath.row];
    }
    return cell;
}

//セル選択時のアクションを設定
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

// NSString* message = [contents objectAtIndex:indexPath.row];
NSString *message = [contents objectAtIndex:indexPath.row];
if (message == @"aaaaaa") {
NSURL *url = [NSURL URLWithString:@"https://www.facebook.com/sharer/sharer.php?u=http://douwashindan3310.appspot.com/kekka12.html"];
[[UIApplication sharedApplication] openURL:url];
} else {
NSURL *url = [NSURL URLWithString:@"http://www.atmarkit.co.jp/fcoding/articles/objc/05/objc05b.html"];
[[UIApplication sharedApplication] openURL:url];
}


}

//セルを本当に削除する
-(void)tableView:(UITableView *)tableView 
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
forRowAtIndexPath:(NSIndexPath *)indexPath 
{
if (UITableViewCellEditingStyleDelete == editingStyle) {
//データソースからデータを削除
[contents removeObjectAtIndex:indexPath.row];
//テーブルから該当セルを削除
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
withRowAnimation:UITableViewRowAnimationFade];

//データを読み込んで削除=========================
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arr;
arr = [_userDefaults arrayForKey:@"datacontent"]; //読み込み
arr = contents;
[_userDefaults setObject:arr forKey:@"datacontent"];
[_userDefaults synchronize];
//データを読み込んで削除=========================

} else if (UITableViewCellEditingStyleInsert == editingStyle) {
//データソースに1件追加
[contents insertObject:@"new item" atIndex:(contents.count - 1)];
//テーブルにセルを追加
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
withRowAnimation:UITableViewRowAnimationTop];
}
}
-(IBAction)setEditing:(BOOL)editing animated:(BOOL)animated {

// 編集モードにする
if(self.categoryTableView.editing == NO) {
[self.categoryTableView setEditing:YES animated:YES];
sakujyobtn.title = @"完了";
} else if(self.categoryTableView.editing == YES)  {
[self.categoryTableView setEditing:NO animated:YES];
sakujyobtn.title = @"削除";
}
[super setEditing:editing animated:YES];
}

-(UITableViewCellEditingStyle)tableView:(UITableView*)tableView
  editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
{
return UITableViewCellEditingStyleDelete;
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
 }

- (void)viewDidUnload {
    [super viewDidUnload];
}

//-- アクションの設定 --------------------------------//
// 戻るボタンが押された時のアクションを設定します。
//-------------------------------------------------//
- (void)action:(id)sender
{
//表示していたビューを消す
[self dismissModalViewControllerAnimated:YES];
}

//-- アクションの設定 --------------------------------//
// 追加ボタンが押された時のアクションを設定します。
//-------------------------------------------------//
-(IBAction)setEditingadd:(BOOL)editing animated:(BOOL)animated {
picker = [[[UIPickerView alloc] initWithFrame:CGRectMake(0,265,320,200)] autorelease];
picker.delegate = self;
picker.dataSource = self;
[self.view addSubview:picker];
doneview = [[[UIView alloc]initWithFrame:CGRectMake(0,225,320,40)] autorelease];
doneview.backgroundColor = [UIColor blackColor];
doneview.alpha = 0.5;
[self.view addSubview:doneview];
donebtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
donebtn.frame = CGRectMake(230, 232, 80, 30);
[donebtn setTitle:@"完了" forState:UIControlStateNormal];
[donebtn addTarget:self
action:@selector(done:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:donebtn];
}


//列数の設定(設定する列の数をreturnで返す)
- (NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}

//!!行も列も番号は0から始まるので注意
//列(componentの値で渡される)に対する、行数の設定(設定する行の数をreturnで返す)
- (NSInteger) pickerView: (UIPickerView*)pView
 numberOfRowsInComponent:(NSInteger) component {
  return [activities count];
}


//列(componentの値)、行(rowの値)に対する表示するものを設定
- (NSString*)pickerView: (UIPickerView*)pView
titleForRow:(NSInteger) row forComponent:(NSInteger)component {
return [activities objectAtIndex:row];
}
// 呼ばれるdoneメソッド
-(void)done:(UIButton*)button{
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:contents.count inSection:0];
/*NSInteger component = [picker selectedRowInComponent:0];
NSString* datatitle = [NSString stringWithFormat:@"%d",component];*/
//NSString *activity = [contents objectAtIndex: [picker selectedRowInComponent:0]];
NSString *activity = [activities objectAtIndex: [picker selectedRowInComponent:0]];
NSString *message = [[NSString alloc] initWithFormat: @"%@", activity];
[contents addObject:message];

//読み込んで追加=========================
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arr;
NSMutableArray *mArr;
arr = [_userDefaults arrayForKey:@"datacontent"]; //読み込み
mArr = [NSMutableArray arrayWithArray:arr];
[mArr addObject:message];
arr = mArr;
[_userDefaults setObject:arr forKey:@"datacontent"];
[_userDefaults synchronize];
//読み込んで追加=========================

//[contents addObject:datatitle];
[self.categoryTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
  withRowAnimation:UITableViewRowAnimationTop];
// ここに何かの処理を記述する
// (引数の button には呼び出し元のUIButtonオブジェクトが引き渡されてきます)
self.picker.hidden = YES;
self.donebtn.hidden = YES;
self.doneview.hidden = YES;
}

- (void)dealloc {
    [super dealloc];
[contents release];
}

@end
-------


ほんとに長いですね。
今回は、『NSUserDefaultsを使って、簡単なデータを保存する』がテーマなので、
ココをじっくり説明したいと思います。



1、まずはビューを開いたときに、以前登録してあるデータがあるか参照します。
- (void)viewDidLoadのところですね。
2、登録したデータがなかったら、データを用意して保存します。


//NSUserDefaultsを使うために初期設定をします。
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
//arrayForKeyで指定したキーで以前のデータを呼び出します。
NSArray *array;
array = [_userDefaults arrayForKey:@"datacontent"];


if (array) {
//ファイルがあった場合は、呼び出したデータを
//テーブルに表示させるためのNSMutableArrayに読み込みます。
//NSMutableArrayにNSArrayの情報をいれるには、mutableCopyを使います。
contents =  [array mutableCopy];

else {

//ファイルがなかったら、arrayforkeyでファイルを作成、保存します。
//最初からテーブルに表示させるデータをcontentsに用意します。
contents = [[NSMutableArray allocinitWithObjects:@"aa",@"a"@"b"@"c"nil];

//contentsの中身を保存させるために、arrayに代入します。
//NSUserDefaultsは、NSMutableArrayのデータを保持することが出来ないので。。
NSArray *array = contents;

//どのキーで保存するかを指定します。
[_userDefaults setObject:array forKey:@"datacontent"];
//データを上書き保存します。
[_userDefaults synchronize];
}




3、追加した情報を同じキーで上書き保存します。
左下の追加ボタンで情報を追加した際にデータが上書きされる様に設定します。



//まずはデータを読み込みます。
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arr;
NSMutableArray *mArr;
arr = [_userDefaults arrayForKey:@"datacontent"]; 
mArr = [NSMutableArray arrayWithArray:arr];

//追加する情報をaddObjectで追加します。
[mArr addObject:message];
arr = mArr;

//同じキーを指定して上書き保存します。
[_userDefaults setObject:arr forKey:@"datacontent"];
[_userDefaults synchronize];


4、削除した情報を同じキーで上書き保存します。



//まずはデータを読み込みます。
NSUserDefaults *_userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arr;
arr = [_userDefaults arrayForKey:@"datacontent"]; //読み込み

//現在の情報を上書きするために配列に代入します。
arr = contents;

//キーを指定して上書き保存します。
[_userDefaults setObject:arr forKey:@"datacontent"];
[_userDefaults synchronize];


これで保存することが出来ました!
ぜひおためし下さい。

1 件のコメント:

  1. はじめまして。このコードサンプルとしてxcode4.5で実装テストしてみたいのですが、サンプルのproject_fileを頂くことは可能でしょうか?
    ご検討宜しくお願いします。

    返信削除