こういう人に向けて発信しています。
・クラスごとの複雑なデータを管理したい人
・APIから返却されたデータを管理したい人
・Objective-C初心者
どういう時に活用するべきか
API通信後にJSONが返却されたデータをModel化してあげると
datamodel.value
のように取り出しやすいのでオススメです。
CustomModel.h
# import <Foundation/Foundation.h>
@interface CustomModel : NSObject<NSCopying>
@property (nonatomic) NSString *accountID;
@property (nonatomic) NSString *passwordID;
/**
本メソッドを呼び出してカスタムモデルを初期化する。
*/
- (instancetype)initMode:(NSDictionary *)modelDict;
@end
CustomModel.m
# import "CustomModel.h"
@implementation CustomModel
# pragma mark - Initialize
- (instancetype)initMode:(NSDictionary *)modelDict{
self = [super init];
self.accountID = modelDict[@"accountID"];
self.passwordID = modelDict[@"passwordID"];
return self;
}
# pragma mark - NSCopying
//hクラスの記述して外部クラスから参照できなくてもOK
- (instancetype)copyWithZone:(NSZone *)zone {
CustomModel *copyModel = [[[self class] allocWithZone:zone] init];
if(copyModel){
copyModel.accountID = self.accountID;
copyModel.passwordID = self.passwordID;
}
return copyModel;
}
@end
使用例
NSDictionary *initDic = @{@"accountID": @"iga34egineer",
@"passwordID": @"1234"};
CustomModel *customModel = [[CustomModel alloc]initMode:initDic]; //Aモデルを初期化する。
CustomModel *backupModel = customModel.copy; //AモデルをBモデルにコピーする。
customModel.accountID = @"reset"; //Aモデルに変更を加えているが、Bモデルに影響はしない。
注意点
copyに関しては実装しておいた方が良いと思います。
そもそもcopyに関しては同一内容で別インスタンスで持つという意味ですが、
アプリ開発でこういうケースは結構多く活用します。
メニュー画面から対応するカスタムモデルを元に画面遷移して
ViewControllerを描画して各種モデルの内容を変更するが、
元のメニュー画面のデータには影響させないとかね。
逆に言うと、Bモデルを操作した内容をAモデルにも連動して変更を行いたい時は
.copyを取り除いてください。
インスタンスを同一にしたくないが中身を同一でコピーしたい場合について
方法は二種類あります。
(1).copyを使用する(本記事のように)
(2)プロパティ属性で「(nonatomic,copy)」のようにcopy属性を付与する。
一応今回は(1)の方がコードで見た時分かりやすいかと思いますが、
設計上考えるとプロパティ属性で付与してあげる事が一番かと思います。
基本的な構造として、copyするオブジェクトって処理の都度copy属性にする、しないって切り替わらないと思うのですよ。
それも考えると一度付与した状態で変わらないプロパティ属性で良さそうなのと、
コードでのcopyですと常にcopy記述が必要になります。
もし作業者が代わり、
copyを忘れてしまった場合などはインスタンスがコピー元と同一のインスタンスとなってしまいます。
追加:モデルの中身が同一かどうかの判定式を追加
割とカスタムクラスモデルの中身が同一かのチェックって行うんですよね。
追加してみました。
//CustomModel.m
# pragma mark - Equal Check
/**
内容が同一かどうか(注意:インスタンスが同一かではない)
*/
- (BOOL)isEqualModel:(CustomModel *)model{
if(![self.accountID isEqualToString:model.accountID]) return NO;
if(![self.passwordID isEqualToString:model.passwordID]) return NO;
return YES;
}
CustomModel.hにも記載して外部クラスから参照できるようにして下さい。
使用例
CustomModel *customModel = [[CustomModel alloc]initMode:initDic]; //Aモデルを初期化する。
CustomModel *backupModel = customModel.copy; //AモデルをBモデルにコピーする。
customModel.accountID = @"reset"; //Aモデルに変更を加えているが、Bモデルに影響はしない。
if([customModel isEqualModel:backupModel]){
NSLog(@"モデルの中身が同一");
}else{
NSLog(@"モデルの中身が同一ではない");
}
上記コードでコメントアウトしている場合としていない場合で
if文の内容が変わります。
このように呼び出してカスタムクラスモデル内の中身が同一かチェックします。