さて、iPhoneの教材の大部分は、アプリ全体のデザインに十分な注意を払っていないため、あなたの不満を理解しています。彼らは目の保養のインターフェースのためのビーラインを作り、データの処理がそもそもアプリの完全な目的であるにもかかわらず、アプリがデータを処理する方法にリップサービスのみを支払います!
教材は、iPhone /CocoaAPI全体のベースとなるModel-View-Controllerデザインパターンを説明するのに十分な時間を費やしていません。教材があなたを信じさせたように、UIビューがプログラムのコアであるという誤った信念の下で、機能を間違ったオブジェクトに詰め込もうとし続けるため、何かを理解するのに苦労しています。この誤解の下では、Appleのドキュメントでさえ、何も意味がありません。
一歩下がって考え直す必要があります。表示するデータとそれをいつ表示するかを決定するのは、ビューの機能ではありません。アプリのデータを保持、管理、または保存することは、テーブルビューコントローラーの機能ではありません。これらの関数は、データモデルオブジェクトに適切に属しています(おそらく聞いたことはありません)。データモデルタスクをビューとビューコントローラに分割しようとしているため、問題が発生しています。
どうやら、テーブルビューコントローラのプロパティとしてテーブルのデータを保持しているため、アプリにはデータモデルすらありません。これは単純なチュートリアルの例でよく見られますが、最も些細なアプリ以外の複雑さの下で崩壊するのは悪い設計です。
代わりに、データは独自のカスタムオブジェクトに保存および管理する必要があります。これがデータモデルです。あなたの場合、データが2つの配列に分散しているように見えるので、次のようなデータモデルオブジェクトを作成します。
@interface MyDataModel : NSObject {
@protected
NSArray *arrayOne;
NSArray *arrayTwo;
@public
NSArray *currentlyUsedArray;
}
@property(nonatomic, retain) NSArray *currentlyUsedArray;
-(void) switchToArrayOne;
-(void) switchToArrayTwo;
-(void) toggleUsedArray;
@end
#import "MyDataModel.h"
@interface MyDataModel ()
@property(nonatomic, retain) NSArray *arrayOne;
@property(nonatomic, retain) NSArray *arrayTwo;
@end
@implementation MyDataModel
- (id) init{
if (self=[super init]) {
self.arrayOne=//... initialize array from some source
self.arrayTwo=//... initialize array from some source
self.currentlyUsedArray=self.arrayOne; //whatever default you want
}
return self;
}
-(void) switchToArrayOne{
self.currentlyUsedArray=self.arrayOne;
}
-(void) switchToArrayTwo{
self.currentlyUsedArray=self.arrayTwo;
}
- (void) toggleUsedArray{
if (self.currentlyUsedArray==self.arrayOne) {
self.currentlyUsedArray=self.arrayTwo;
}else {
self.currentlyUsedArray=self.arrayOne;
}
}
(実際のデータはカプセル化されており、他のオブジェクトはにしかアクセスできないことに注意してくださいcurrentlyUsedArray
。データモデルは、データの内部状態に基づいて、提供するデータを決定します。)
このデータモデルオブジェクトは、どこからでもアクセスできる場所にある必要があります。最良の方法はシングルトンにすることですが、手っ取り早い方法はアプリデリゲートの属性としてパークすることです。
したがって、テーブルビューコントローラには、次のプロパティがあります。
MyDataModel *theDataModel;
@property (nonatomic, retain) MyDataModel *theDataModel;
その後、実装で
@synthesize theDataModel;
-(MyDataModel *) theDataModel; {
if (theDataModel; !=nil) {
return theDataModel; ;
}
id appDelegate=[[UIApplication sharedApplication] delegate];
self.theDataModel=appDelegate.theDataModelProperty;
return theDataModel;
}
次に、テーブルビューデータソースメソッドで:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
cell.textLabel.text=[self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
return cell;
}
アプリ内のどこかのイベントで配列を切り替える必要がある場合は、アプリデリゲートからデータモデルオブジェクトを呼び出して、適切な配列切り替えメッセージを送信するだけです。
id appDelegate=[[UIApplication sharedApplication] delegate];
[appDelegate.theDataModelProperty toggleUsedArray];
これで、後続のすべてのデータ操作は、その特定のテーブルビューであろうと、他の完全に無関係なビューであろうと、適切な配列からのデータを使用します。
なぜこのすべてのトラブルを経験するのですか?これにより、アプリケーションがモジュール化されます。データ管理を毎回書き直すことなく、それぞれが異なる方法でデータを表示するさまざまなビューを簡単に追加できます。データモデルを使用して、テーブル、Webビュー、またはコマンドラインに表示されるデータを管理できます。データモデルをまったく別のアプリに簡単に移動することもできます。
このモジュール性により、大規模で複雑なアプリの管理が非常に簡単になります。データを操作および制御するオブジェクトは1つだけです。まれにしか使用されないコードセグメントのマイナーエラーによってアプリ全体が破棄されることを心配する必要はありません。ビューを簡単にプラグインしたり、アプリを壊すことなく簡単に削除したりできます。
これはもちろん些細な例ですが、良い習慣を示しています。
ただし、これにより、どのデータをいつロードするかを知っているテーブルビューの問題をどのように解決できるのでしょうか。単純ですが、そうではありません。ロードするデータやロードするタイミングを知ることは、テーブルビューの仕事ではありません。データモデルはwhat-dataを処理し、tableviewコントローラーはwhenを処理します。(たとえば、URLの更新時にデータモデルに通知を発行させることもできます。その後、View Controllerは通知に登録しreloadData
、データモデルが変更されるたびに呼び出すことができます。)
MVCの機能を容赦なくコンパートメント化してカプセル化することで、保守とデバッグが容易なシンプルで再利用可能なコンポーネントから複雑なアプリを作成します。
ほとんどの教材は、この非常に重要な概念にリップサービスを支払うだけです。