2011-08-05 8 views
2

以前はコードを使用していた場所でIBの使用を試み始めています。私はiPad/iPhoneのポートレート/風景用のペン先を作成したので、4つのビューがあります。すべてのファイル所有者がUIViewControllerに設定されていますが、すべてパレットセットからNSObjectサブクラス "TargetObject"にオブジェクトが追加されています。 IBActions/IBOutletsの設定は問題ありません。いつものようにCtrlキーを押しながらドラッグして1つのペン先にコードを作成し、オブジェクトを右クリックして、アクション/アウトレットを他のペンの右のコントロールにドラッグして、ペン先。アイデアは、アプリケーションデリゲートが現在のデバイスの適切なビューコントローラを起動し、そのビューコントローラが方向に応じて正しいビューを読み込むというものです。共通ターゲットオブジェクトを使用して複数のビューのアクション/アウトレットを処理する方法は?

(このアプローチは必要ありません - このようなIBコントロールだけでレイアウトを並べ替えることは非常に苛立っていますので、この方法を実行することが可能かどうかを知りたい)

これらの1対多のビューとターゲットオブジェクトの背後にあるアイデアは、アプリ内のどこにでも使用できるということです。たとえば、コアデータにオブジェクトである何かが表示されている場合は、 と私は詳細ビュー/アプリケーションの複数の場所で編集できるようにしたいと思います。これは非常にMVCのやり方のようです。私が行うとき

問題は、ビューコントローラのloadViewメソッドで提供されます:

NSArray *portraitViewArray = [[NSBundle mainBundle] loadNibNamed:@"Weekview_iPad_Portrait" owner:self options:nil]; 
portraitWeekView = [portraitViewArray objectAtIndex:0]; 

NSArray *landscapeViewArray = [[NSBundle mainBundle] loadNibNamed:@"Weekview_iPad_Landscape" owner:self options:nil]; 
landscapeWeekView = [landscapeViewArray objectAtIndex:0]; 

// this object is intended to be a common target for portrait and landscape arrays. 
weekViewTarget = [portraitViewArray objectAtIndex:1]; 

UIInterfaceOrientation interfaceOrientation = self.interfaceOrientation; 

if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) 
    self.view = portraitWeekView; 
else 
    self.view = landscapeWeekView; 

あなたが推測として、すべてがターゲットオブジェクトがクラッシュしたとの対話縦向きではなく、風景の中に細かいです。 weekViewTargetオブジェクトは、ポートレート・ビューで作成されたオブジェクトを参照するため、参照で保持されていない別のインスタンスがランドスケープ・ビューで検索されています。ランドスケープビューでは、_viewDelegateはnilです。プライベートなので、コードで修正することはできません。

私は風景ターゲットオブジェクトを参照で保持することもできますが、向きが変わるたびに問題が発生します - UITableViewなどのステートフルコントロールの場合、データソース/デリゲートが変更され、回転時のユーザーエクスペリエンスが変わります。ターゲットオブジェクトが単純なアクションだけを実装し、別の共有オブジェクトを使用して、必要なテーブルビューまたはテキストビューのデータソース/デリゲートオブジェクトを実装することを保証しない限り、

私が考えていることの1つは、ターゲットをシングルトンにすることです。ハックのように見えますが、ここではうまくいかない時が来ます。

一般的なターゲットオブジェクトを使用してモデルに要素を加えて、複数のビューを作成してペン先として実装する正しい方法はありますか?

  • 進展 - 物事は私が独自の型に各ターゲットのポインタを与える場合は作業を開始:

    WeekViewTarget *forwardTarget; 
    

と、次のように使用されていないハンドラのforwardTargetが設定されている間、実際のハンドラのforwardTarget = nilをしましょう:

weekViewTarget = [portraitViewArray objectAtIndex:1]; 
forwardedWeekViewTarget = [landscapeViewArray objectAtIndex:1]; 
forwardedWeekViewTarget.forwardTarget = weekViewTarget; 

、その後は各IBActionで次の操作を行います。

- (IBAction)timeBlockTapped:(id)sender { 

    if(forwardTarget != nil) { 
     [forwardTarget performSelector:@selector(timeBlockTapped:) withObject:sender]; 
    } else { 
     NSLog(@"Got a tap event with sender %@", [sender description]); 
    } 
} 

まだ気分が良くなりません。

+0

風景/肖像画の回転に別のxibをデザインする必要はありません。あなたはちょうど別のxibをiPhoneとiPad用に分けなければなりません。クラッシュ中にコンソールに表示されるエラーメッセージを投稿できますか? –

+0

クラッシュが分かっています。これは、portraitViewArrayのように、landscapeViewArrayのloadNibNamedから返されたNSObjectにぶら下がっていないことです。これで、元の投稿の「進捗状況」の後に記述された変更がすべて処理されます。私はそれがすべきだと思うよりもまだ少し難しく複雑です。離散的なポートレート/風景のペン先の代わりに、ストラットとスプリングを使用する方法はありますか?これまでこれまでに多くの成功を収めていませんでした。 –

答えて

16

アダム、プロキシ(別名外部)オブジェクトのように聞こえます。

ニブからオブジェクトグラフをインスタンス化する際にあなたの問題

NSBundleとUINibが自動リリース配列を返します。特に保持しないオブジェクトは、イベントループの最後に配列が解放されたときに解放されます。明らかに、互いを参照するペン先のオブジェクトは、所有者が保持されている限り保持されます。

アクションターゲットオブジェクトの2番目のインスタンスが掛かっていないため、解放されています。

あなたが本当に望むのは、両方のNIBが参照できるターゲットオブジェクトの単なるインスタンスです。したがって、NIBにそのオブジェクトのインスタンスをインスタンス化させることはできません。しかし、NIBはそのオブジェクトインスタンスへの参照を作成できる必要があります。

こんにちは、どうしたらいいですか?

策:プロキシ/外部は基本的に外部のオブジェクトを使用すると、NIBに置くプロキシです

オブジェクト。 NIBのオブジェクトグラフをインスタンス化すると、実際のインスタンスがフィードされます。 NIBローダーは、NIBのプロキシを外部提供のインスタンスに置き換え、Interface Builderでプロキシに割り当てたターゲットまたはアウトレットを設定します。

行うにはどのように "外部オブジェクト" ではなくNSObjectのインスタンス内のInterface Builderのドラッグで

  1. 。 Xcode 4.xのFile's Ownerと一緒に上のセクションに表示されます。
  2. これを選択し、「IDインスペクタ」で適切な種類のクラスに設定します。
  3. "属性インスペクタ"で識別子文字列を "TargetObject"(または以下のコードで使用する文字列)に設定します。
  4. 利益!

コード

id owner = self; // or whatever 
id targetObject = self.targetObject; // or whatever... 

// Construct a dictionary of objects with strings identifying them. 
// These strings should match the Identifiers you specified in IB's 
// Attribute Inspector. 
NSDictionary *externalObjects = [NSDictionary dictionaryWithObjectsAndKeys: 
            targetObject, @"TargetObject", 
            nil]; 

// Load the NIBs ready for instantiation. 
UINib *portraitViewNib = [UINib nibWithNibName:@"Weekview_iPad_Portrait" bundle:nil]; 
UINib *landscapeViewNib = [UINib nibWithNibName:@"Weekview_iPad_Landscape" bundle:nil]; 

// Set up the NIB options pointing to your external objects dictionary. 
NSDictionary *nibOptions = [NSDictionary dictionaryWithObjectsAndKeys: 
           externalObjects, UINibExternalObjects, 
           nil]; 

// Instantiate the objects in the nib passing in the owner 
// (coincidentally also a proxy in the NIB) and your options dictionary. 
NSArray *portraitViewArray = [portraitViewNib instantiateWithOwner:owner 
                  options:nibOptions]; 
NSArray *landscapeViewArray = [landscapeViewNib instantiateWithOwner:owner 
                  options:nibOptions]; 

self.view = [(UIInterfaceOrientationIsPortrait(interfaceOrientation)) ? portraitViewArray : landscapeViewArray) objectAtIndex:0]; 

ノート

あなたはニブをロードするためにNSBundleを使用しています。 UINibを使用する必要があります。 NIBファイルを読む方がはるかに高速です。また、オブジェクトのインスタンシエーションからNIBのロードを分離します。つまり、init、awakeFromNib、またはviewDidLoadにNIBをロードし、NIBの内容をインスタンス化することはできません。その後、NIBの実際のオブジェクトが必要な最後の瞬間にinstantiateWithOwnerを呼び出すことができます。

UITableViewControllerを使用している場合は、viewDidLoadで表のセル・ニブをロードしますが、-tableView:cellForRowAtIndexPath:でそのタイプのセルが必要になるまで実際にはインスタンス化しません。

+0

鮮やかな - まさに私がやりたかったこと。 –

+0

これについての文書はほとんどありません(とにかく見つけることができます)。ありがとう – bandejapaisa

+0

うわー、私はこれまで聞いたことがない。それはとても美しいです。 – Dustin

0

interfaceOrientationに基づいて、方向を特定し、xibのコントロールのフレームをリセットできます。 For more, this will guide you...

+0

はい、すべてのことを認識して、ここのオブジェクトは、静的、プリコンパイラ定数、またはマジックナンバーをどこからでも取得して、サブビューを再配置することができます。 1つのターゲットオブジェクトを持つことができるすべてのフレームを定義する場合は、各方向のケースごとにすべてのビジュアル要素のフレームを含む辞書を与え、それらのフレームを回転に適用します。たぶん...簡単だけど、ペン先のペン先に置いて、ペン先に入れて、数字から離れたい。 –

関連する問題