2010-11-18 2 views
5

私は約1ヶ月前にiPhone用のプログラミングを始めました。だからそこの誰かが私を助けてくれるかもしれない。Cocoa Objective Cのクラス間でデータを送信

私は@propertyと@synthesiseがどのように動作し、setterとgetterを使うのかを理解していると思いますが、問題があります。

私はクラス、関数、クラス1とクラス2の3つのクラスがあります。

関数は、すべてのデータを保持するクラスであり、Class1およびClass2がそのデータを読み込み、新しいデータを書き込む(データを修正する)関数です。しかし、Class1とClass2の両方は、基本的にデータの青写真であるため、関数のインスタンスを作成します。

もしClass1がいくつかのデータを書き込んだり(5)、関数をClass2が取得した場合、Class2は0を返します。Class1は関数のインスタンスに5を書き込んだだけです。 。

私は最初にオフになったと思いますか?次に、Class1とClass2が同じデータを取得して設定することができるように、どのように行うのですか。

ありがとうございました。これは私がまだ学んでいない話題を含んでいるかもしれないが、それが何であるかを知りたいので、私はそれを愛でることができます。

答えて

6

クラス1とクラス2が "共有オブジェクト"の同じインスタンスを使用することを確実にするために、多くのオプションがあります。

  1. は明確ではなく、インスタンス自身を作成するために、クラス1とクラス2を可能にするよりも、外部からのクラス1とクラス2の同じインスタンスを渡します。または
  2. Functionsクラスにシングルトン初期化子を指定し、Class1とClass2がこれを使用することを確認します。または
  3. レジストリパターンと呼ばれるデザインパターンを使用して、クラス1とクラス2が関数クラスのインスタンスをレジストリから取得するようにします。または
  4. 依存性注入(複合)を使用します。

    Functions *funcs = [[Functions alloc] init]; 
    
    Class1 *obj1 = [[Class1 alloc] initWithFunctions:funcs]; 
    Class2 *obj2 = [[Class2 alloc] initWithFunctions:funcs]; 
    /* or alternatively use setters after initialization */ 
    

    シナリオ(2)は次の最も簡単であり、非常に一般的です:

シナリオ(1)は、まさにこのように書きますので、理解するのが最も簡単です。 Cocoaは、多くのクラスにシングルトン初期化子を提供します。イニシャライザのプレフィックスとして+shared...が表示されている場合は、おそらくシングルトンが返されます。

@implementation Functions 

+(id)sharedFunctions { 
    static Functions *sharedFunctions = nil; 

    @synchronized(self) { 
    if (sharedFunctions == nil) { 
     sharedFunctions = [[self alloc] init]; 
    } 

    return sharedFunctions; 
    } 
} 

@end 

静的変数は、あなたが遅延し、それが(1回だけ発生)初期値だのチェックを使用して、その中にオブジェクトのインスタンスをロードすることができることを意味しており、一度だけ初期化されます。このメソッドへの以降の呼び出しでは、同じインスタンスが返されます。

Functions *f1 = [Functions sharedFunctions]; 
Functions *f2 = [Functions sharedFunctions]; 

/* f1 == f2; */ // always 

オプション(3)は、他の言語と比較して客観的なCではあまり見られず、シングルトンと同じ目標を達成します。そのアイデアは、あなたがキーで調べることができるオブジェクトの辞書を持っているということです。レジストリ内の項目へのアクセスが必要なものはすべて、レジストリに独自のインスタンスを要求するだけです。通常、レジストリ自体はシングルトンになります。

オプション(4)は、実際には非常に洗練されたソリューションであり、複雑さを増すだけで多くの利点があります。依存関係が常に緩やかに結合されていることが保証されていること(つまり、実装をスワップアウトし、独立した単体テストを独立させるほうがずっと簡単です)という利点があります。複雑さは、必要なもののインスタンスを取得するための非標準的なメカニズムに由来します。

依存性注入は、オブジェクトがそれ自身の依存関係をインスタンス化しないというアイデアを中心に展開されています。これらの依存関係を提供するために他のものに頼るのではなく、それは依存性注入容器として知られているものです。依存性注入コンテナは事実上レジストリパターンの最上位レイヤーです。これは、コンテナがあらかじめ作成された依存関係のインスタンスを保持するか、新しいインスタンスをインスタンス化する方法を知るためです。

最も単純なケースでは、依存性注入はまさに私がオプション(1)で示したものです。これを達成するために依存性注入コンテナは必要ありません。

複雑さのレベルをシフトすると、依存性注入はDIコンテナのコンセプトをもたらします。これは、既存のデザインパターン(レジストリ、オプション(3)、シングルトン

DIコンテナを完全に実装することは、おそらくこの質問の範囲を超えていますが、パブリックインターフェイスの観点からは、 1つの実装は次のようになります:

DIContainer *container = [DIContainer sharedContainer]; 

[container registerClass:[ClassA class]]; 
[container registerClass:[ClassB class]]; 
[container registerDependentProperty:@selector(setClassA:) 
         withInstanceOf:[ClassA class] 
          forClass:[ClassB class]]; 

ClassB *obj = [container makeInstanceOfClass:[ClassB class]]; 
NSLog(@"ClassB's -classA type = %@", [[obj classA] class]); 

私はちょうど私の頭の上からそれを打ちました。この投稿の真ん中ですので、それが100%正確であるとは思わないでください。コンテナは、ClassBのインスタンスを初期化するときに、ClassAのインスタンスを使用して-setClassA:を呼び出す必要があります。コンテナに定義されているルールに従って初期化されます(この場合、ClassAの依存関係はありません。プレーンなインスタンスを返すあなたはもっと離れて、この答えから何も取っていない場合は、単に覚えて

オプション(1)及び(2);。)

+2

お元気ですか、本当に便利です。私はオプション2に行って、うまくいきます。オプション3と4は私の頭の中を少し行きましたが、私は少し眠った後、明日にそれらを読んでいきます。午前中にもう少し意味をなさないかもしれません。しかし、助けてくれてありがとう、非常に便利です。 :-D – Baza207

+1

問題はない、私はオプション(2)で行くあなたの選択は良いものだと思う。オプション(1)は、テストするのが難しい(不正なテスト環境)ため、多くの開発者の間でシングルトンが多少悪い評判を持っているため、「技術的に」最高です。しかし、正しく使用しても問題ありません。実際、Objective-Cは他の言語と同じように単一の排他的初期化子/コンストラクタを持っていないので、シングルトンは100%強制されていないので、どのような場合でもテストで回避することができます。オプション3は非常に簡単ですが、オプション(4)は経験豊かな開発者でさえ混乱させるテーマです。 – d11wtq

+0

私はこの質問が古いことを知っていますが、これは完全に私を助けました。 +1 –

0

これはオブジェクト指向プログラミングに関する一般的な質問ですが、解決策はObjective-Cにも当てはまります。あなたがしたいことは、関数のインスタンスを1つ作成することです。そのインスタンスは、Class1とClass2のインスタンス間で共有する必要があります。

Functions *f = [[Functions alloc] init]; 
Class1 *c1 = [[Class1 alloc] init]; 
Class2 *c2 = [[Class2 alloc] init]; 
// set the value of a instance variable of f to the value of aValue from c1 
[f setSomeValue:[c1 aValue]]; 
// now change it to c2's aValue 
[f setSomeValue:[c2 aValue]]; 
+0

これは意味があります。だから私はあなたがClass1ファイルでそれにClass1のビットを置くだけClass2ファイルでClass2のビットを入れていると思います。 initは両方の関数インスタンスに入りますが? 私は物事を繰り返す場合は申し訳ありませんが、私はこのようなものを何度も繰り返してきており、私の心はちょっと喧嘩しています。 – Baza207

1

「Cocoa Fundamentals Guide」を読む必要があります。あなたの質問に関連するセクションはCommunicating with Objectsです。

+0

リンクへの歓声。 :-) – Baza207

0

は、オンライン参照の多くはそこにありますが、私はこれを見つけました本は素晴らしい資産になるStephen G. Kochan著Objective-C 2.0プログラミング(第2版)。それは素晴らしい出発地です。

関連する問題