0

2 つのビュー コントローラーがあり、それらを呼び出してviewAViewB

  • すべてのアクションはメイン ビューで行われます -ViewA
  • メニュー ボタンを押すと、 が表示されViewB、すべて正常で、メニューが表示されます

IBActionここで、ユーザーは 1 つのボタンに触れます。これは、プログラムで次のことを行う必要があるだけです。

  1. a の値を変更し、それをBOOL呼び出しますmyBOOLYES
  2. 解散ViewB
  3. myBOOL変数の現在の状態をYESback に渡しますViewA

BOOL両方のビューで合成された同じ設定プロパティを宣言しましたがNSLog、却下しViewBてバックアップをロードするとViewA、元に戻りますNO

だから私は接線を外れていることを知っていますBOOL.2つのコントローラー間で a の値を送信できるかどうかを知りたいだけです.送信できる場合は、例を示してください...検索でプロトコルとデリゲートNSStringの例が見つかりましたs を使用しようとするとBOOL、インポート ループに陥りますが、グローバル を作成する可能性があることを読みましたBOOL

4

7 に答える 7

7

このトピックに関する質問は、NSNotificationCenterどちらNSUserDefaultsもシングルトンであることに注意してください。

NSUserDefaults:

このクラスの目的は、クラス間で変数を渡すことではありません。その目的は、まあ、ユーザーのデフォルトを保存することです。(つまり、環境設定、設定など)。

NSNotificationCenter:

このクラスは非常に便利で、さまざまな用途があります。その 1 つは、任意のクラスが受け取る変数をブロードキャストすることです。受信クラスはオブザーバーと呼ばれます。このパターンはオブザーバー パターンと呼ばれます。

注:このNSUserDefaultsアプローチには、他のクラスが初期化される前に変数を設定できるという利点があり、いつでも取得できます。ただし、それは本当にずさんで (IMHO)、悪い習慣と見なされます。


のクイック アンド ダーティ コード サンプルNSNotificationCenter:

// upon initializing the class that wants to observe the changes, we add it as an observer.
// So, somewhere in the A.m, upon being initialized (init, maybe?).

- (id)init {
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(calledUponNotif:)
                                                     name:@"MyObserveKey"
                                                   object:nil];
    }
    return self;
}

// the selector should look something like this:
- (void)calledUponNotif:(NSNotification *)notif {
    id sentVar = [notif object];
}

// Somewhere in the B.m
    [[NSNotificationCenter defaultCenter] postNotificationName:@"MyObserveKey"
                                                        object:varToSend];

別の注意: postNotification メソッドを呼び出した後、他のクラスに登録されているセレクターが同期的に呼び出されるため、心配する必要はありません。

于 2012-08-12T08:47:42.190 に答える
3

ビューに依存しない値保持ツールがあります。以下を使用できます。

[[NSUserDefaults standardUserDefaults]setObject:<#(id)#> forKey:<#(NSString *)#>]

たとえば、A ビューに文字列やデータを入力すると、それらを上記の変数に格納できます。そして、Bビューでは、以下のコードでそれらを使用できます:

 [[NSUserDefaults standardUserDefaults]objectOrKey:<#(NSString *)#>]

NSUserDefaults以下は、以下を使用したデータの例です。

ss

ビュー A:

- (void)textFieldDidEndEditing:(UITextField *)sender
    {
        if (sender == homepage) {
            [[NSUserDefaults standardUserDefaults]
             setURL:[NSURL URLWithString:homepage.text] forKey:Ever5secHomepagePrefKey];
            if( [homepage canResignFirstResponder] ) {
                [homepage resignFirstResponder];   
            }
        } else if (sender == userId) {
            [[NSUserDefaults standardUserDefaults]
             setObject:userId.text forKey:Ever5secUserIdPrefKey];
objectForKey:Ever5secUserIdPrefKey]);
            if( [userId canResignFirstResponder] ) {
                [userId resignFirstResponder];   
            }
        } else if (sender == password) {
            [[NSUserDefaults standardUserDefaults]
             setObject:password.text forKey:Ever5secPasswordPrefKey];
            if( [password canResignFirstResponder] ) {
                [password resignFirstResponder];   
            }
        }
    }

ビュー B:

userId.text = [[NSUserDefaults standardUserDefaults]
               objectForKey:Ever5secUserIdPrefKey];
password.text = [[NSUserDefaults standardUserDefaults]
                 objectForKey:Ever5secPasswordPrefKey];
homepage.text = [[[NSUserDefaults standardUserDefaults]
                  URLForKey:Ever5secHomepagePrefKey]
                 description];
于 2012-08-12T00:07:36.830 に答える
3

これはカプセル化の良い答えではありませんが、プロトコルやデリゲートを使用できないと、カプセル化がうまくいくとは思えません。

あるView Controllerで設定し、別のView Controllerでアクセスできるグローバル変数を作成することもできます。

ViewControllerOne.h

  extern NSString *globalVariable;

  @interface ViewControllerOne

  @end

ViewControllerOne.m

 #import "ViewControllerOne.h"

 @implementation ViewControllerOne

 NSString *globalVariables = @"Some String in the variable to access in second controller";

 @end

ViewControllerTwo.m

 #import "ViewControllerTwo.h"
 #import "ViewControllerOne.h"

 @implemetation ViewControllerTwo

 - (void)viewDidLoad
 {
     NSLog("%@", globalVariables);
 }

 @end

これはコンソールに出力されます

 ****CONSOLE****
 Some String in the variable to access in second controller
于 2012-08-12T08:28:51.080 に答える
1

異なるビュー コントローラーでデータを保存および取得するために使用できる 2 つのオプションがあります。

1)NSUserDefaultsデータを保存し、他のView Controllerにアクセスするための最良のオプションです。

このNSUserDefaultsクラスは、 などの一般的な型にアクセスするための便利なメソッドを提供しますfloat, double, integer, Boolean

デフォルト オブジェクトは、プロパティ リスト、つまり、のインスタンス (またはコレクションの場合はインスタンスの組み合わせ) である必要がありますNSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary

これは、データを保存および取得するための非常に簡単で最適な方法です。

について読みたい場合はNSUserDefaults、ここでドキュメントを共有しています。[NsuserDefaults ドキュメント。][1]

2) クラスまたは他のビュー コントローラーの外部からアクセスできるようにする場合は、プロパティを作成します。

このようにプロパティを作成します。@property (nonatomic, retain) NSArray *arrayData;そして、この配列値を他のView Controllerでも使用できます。

プロパティは、オブジェクトのアクセサ メソッドを置き換えます。

于 2013-02-08T14:11:57.187 に答える
1

異なるビュー コントローラーでデータを保存および取得するために使用できる 2 つのオプションがあります。

1)NSUserDefaultsデータを保存し、他のView Controllerにアクセスするための最良のオプションです。

このNSUserDefaultsクラスは、 などの一般的な型にアクセスするための便利なメソッドを提供しますfloat, double, integer, Boolean

デフォルト オブジェクトは、プロパティ リスト、つまり、のインスタンス (またはコレクションの場合はインスタンスの組み合わせ) である必要がありますNSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary

これは、データを保存および取得するための非常に簡単で最適な方法です。

について読みたい場合はNSUserDefaults、ここでドキュメントを共有しています。 NsuserDefaults ドキュメント。

2) クラスまたは他のビュー コントローラーの外部からアクセスできるようにする場合は、プロパティを作成します。

このようにプロパティを作成します。@property (nonatomic, retain) NSArray *arrayData;そして、この配列値を他のView Controllerでも使用できます。

プロパティは、オブジェクトのアクセサ メソッドを置き換えます。

ここで私の答えを見ることができます。あるView Controllerから別のView Controllerに値を渡す

于 2013-02-08T14:15:58.577 に答える
1

NSNotificationCenter、NSUserDefaults、またはグローバル変数を使用する必要はありません。

View Controllerが関連している限り(そしてOPの質問を見ると、それらは確かにそうです)、View Controllerを設定して相互への参照を保持することができます(参照の1つはもちろん弱いです「保持」または「強い参照」サイクルを避けてください)。次に、各View Controllerは、必要に応じて他のView Controllerのプロパティを設定できます。例は次のとおりです...

注意: この概念は、関連する 2 つのビュー コントローラーに対して有効です。ただし、次のコードは次のことを前提としています。

  • 問題のビュー コントローラはナビゲーション コントローラを介して関連付けられ、2 番目のビュー コントローラはプッシュ セグエを介して最初のビュー コントローラに接続されます。
  • iOS 5.0 以上を使用しています (ストーリーボードを使用するため)。

FirstViewController.h

@interface FirstViewController : UIViewController

/* Hold the boolean value (or whatever value should be
   set by the second view controller) in a publicly
   visible property */
@property (nonatomic, assign) BOOL someBooleanValue;

/* Provide a method for the second view controller to 
   request the first view controller to dismiss it */
- (void)dismissSecondViewController;

@end

FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"

@implementation FirstViewController

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    /* Get the reference to the second view controller and set
       the appropriate property so that the secondViewController
       now has a way of talking to the firstViewController */
    SecondViewController *vc = [segue destinationViewController];
    vc.firstViewController = self;
}

- (void)dismissSecondViewController
{
    // Hide the secondViewController and print out the boolean value
    [self.navigationController popViewControllerAnimated:YES];    
    NSLog(@"The value of self.someBooleanValue is %s", self.someBooleanValue ? "YES" : "NO");
}

@end

SecondViewController.h

#import "FirstViewController.h"

@interface SecondViewController : UIViewController

// Create a 'weak' property to hold a reference to the firstViewController 
@property (nonatomic, weak) FirstViewController *firstViewController;

@end

SecondViewController.m

@implementation SecondViewController

/* When required (in this case, when a button is pressed),
   set the property in the first view controller and ask the
   firstViewController to dismiss the secondViewController */
- (IBAction)buttonPressed:(id)sender {
    self.firstViewController.someBooleanValue = YES;
    [self.firstViewController dismissSecondViewController];
}

@end

もちろん、この種の viewController 間通信を処理する最も正しい方法は、SecondViewController がその親/所有者オブジェクトの詳細を知る必要がないように、プロトコル/デリゲート/データ ソースを使用することです。ただし、概念を証明するためだけに、このようなソリューションを構築する方が迅速/簡単な場合があります。次に、すべてが順調で、コードを保持する価値がある場合は、プロトコルを使用するようにリファクタリングします。

ビュー コントローラがお互いを認識していない (そして認識すべきではない) 場合は、NSNotificationCenter を使用する必要がある場合があります。ビュー コントローラー間の通信にグローバル変数または NSUserDefaults を使用しないでください。

于 2013-02-08T14:07:33.293 に答える
0

ブロックの強力な機能を次のように使用するのが最善の方法だと思います。

ViewB.h で

typedef void (^CompletionHandler)(BOOL myBool);
@interface ViewB : UIViewController {
    CompletionHandler completionHandler;
}
- (void)dismissHandler:(CompletionHandler)handler;

In ViewB.m

- (void)dismissHandler:(CompletionHandler)handler {
    completionHandler = handler;
}
- (IBAction)dismiss:(id)sender {
    completionHandler (YES); // your yes no logic here
}

In ViewA.m

- (IBAction)showPopup:(id)sender {
    ViewB *vc = [[ViewB alloc] init];
    [self.view addSubview:vc.view];
    [vc dismissHandler:^(BOOL myBool) {
        if (myBool) {
                //Do your work;
        }
    }];
}
于 2013-02-25T10:18:43.263 に答える