##※この記事は間違いでした、こっちを見てねhttp://qiita.com/koitaro/items/b3a924245fd72f22871a
今回は、おデブになりがちなUITableViewを使ったUIViewControllerを例に、スッキリさせる魔法のルールをご紹介させていただこうと思います。
なお説明が長くなってしまうので細かい部分の処理や説明はやっていないのでご了承下さい。
まず、普通にTableViewを使おうとすると最低でもこんな感じになるとおもいます。
#import "HogeNGViewController.h"
#define CELL_HEIGHT 50
@interface HogeNGViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic) NSMutableArray* hogeArray;
@end
@implementation HogeNGViewController
- (void)viewDidLoad {
[super viewDidLoad];
UITableView* tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.hogeArray.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return CELL_HEIGHT;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* tableViewCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@""];
[tableViewCell setBackgroundColor:[self.hogeArray objectAtIndex:indexPath.row]];
return tableViewCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
@end
###これに魔法を掛けると、こうなります!!!
#import "HogeViewController.h"
#import "HogeView.h"
#import "HogeModel.h"
@interface HogeViewController ()
@property (nonatomic) HogeModel* hogeModel;
@end
@implementation HogeViewController
- (void)loadView
{
HogeView* hogeView = [[HogeView alloc]initWithFrame:self.view.bounds];
[self.setView:hogeView];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.hogeModel = [[HogeModel alloc]init];
hogeView.hogeModel = self.hogeModel;
}
@end
#はじめに
結論から言ってしまえば、MVCで書きましょうということです。
MVCについてはアプリ開発者であれば良く知っていると思います。なぜなら、アプリ開発の入門書には必ずと言っていい程MVCの説明が書いてあるからです。
しかし、MVCの概念については説明するものの、そのMVCを具体的にどうやってコードに落とし込むかが書かれている書籍をほとんど見た事がありません。(何かあれば教えてください。)
なのでここで説明する事は、概念ではなく、具体的ないくつかのルールに従って書く事で勝手にMVCになって、見やすいコードがかけますよ、というものです。
#UIViewController毎にModelファイルとViewファイルを作る
こんな感じですね。
#UIViewControllerのViewにaddSubviewするのは一つのViewだけ
UIViewControllerの中で、ボタンや画像を貼付けたりせずに、そういったものは全てViewでやりましょうということです。
#Viewから直接Modelを弄らせる
ボタンをクリックした等のイベントハンドラやUITableViewのdataSourceメソッド、delegateメソッドはModelに書き、コントローラーを噛ます必要は無いので、ViewにModelの参照を渡して直接Modelを弄れるようにしてあげましょう。
#KVOでモデルのプロパティを監視する
モデルの状態を見てViewを更新させる必要があるため、モデルが更新されたことを通知してもらう必要があるので、その方法としてKVOを使います。何を使うかは状況によっては変わってくるかなと思いますが、TableViewの場合、Arrayの値が変わった時点でTableを更新させるので、非常に相性がよいと思います。
#おわり
少し分かりづらいかもしれませんが、雰囲気が伝わってくれれば嬉しいです。
需要があれば、ちょこちょこ追記していきたいと思います。
ご指摘、ご批判、頂ければありがたいです。
以下に一応ViewとModelのコードをのせておきます。
#import "HogeView.h"
#import "HogeModel.h"
@interface HogeView()
@property (nonatomic) UITableView* tableView;
@end
@implementation HogeView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.tableView = [[UITableView alloc]initWithFrame:frame style:UITableViewStylePlain];
[self addSubview:self.tableView];
}
return self;
}
- (void)setHogeModel:(HogeModel *)hogeModel{
_hogeModel = hogeModel;
self.tableView.dataSource = _hogeModel;
self.tableView.delegate = _hogeModel;
[_hogeModel addObserver:self forKeyPath:@"hogeArray" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// 変化した値がなにかを判別
if ([keyPath isEqual:@"hogeArray"]) {
// 処理したいキーだった場合は処理
[self.tableView reloadData];
}
}
@end
#import "HogeModel.h"
#define CELL_HEIGHT 50
@interface HogeModel()
@property (nonatomic) NSMutableArray* hogeArray;
@end
@implementation HogeModel
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.hogeArray.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return CELL_HEIGHT;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@""];
[cell setBackgroundColor:[self.hogeArray objectAtIndex:indexPath.row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}