この画像の二つのViewControllerで値を共有したいのですが、ViewController2のラベルに表示されるはずの100が表示されず、消えるはずのラベルが表示されたままです。

状態(画像)  
<https://teratail.storage.googleapis.com/uploads/contributed_images/997de6dc17a7b4a91f423c6487f0ba85.png>

順番としては、  
1.AppDelegate.swiftでtastを宣言する  
2.ViewControllerで、appDelegate.testに100を入れる  
3.ViewController2でtestをtest1で受け取り、ラベルに表示させる  
としたつもりです。

少し方法が違ってても全然良いので、異なるView Controllerで値を共有する方法を教えてください。

[appDelegate.swift]

```

    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    var test:String?
    
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
    
    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    
    }
    
```

[ViewController.swift]

```

    import UIKit
    
    class ViewController: UIViewController {
    @IBOutlet weak var B: UIButton!
    @IBOutlet weak var L: UILabel!
    @IBAction func BA(_ sender: AnyObject) {
        let appDelegate:AppDelegate = UIApplication.shared.delegate as!     AppDelegate
        appDelegate.test = String(100)
    }
    
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    }
    
```

[ViewController2.swift]

```

    import UIKit
    
    class ViewController2: UIViewController {
    var test1 = String()
    
    @IBOutlet weak var tetststs: UILabel!
    @IBOutlet weak var fsg: UIButton!
    @IBOutlet weak var erg: UILabel!
    
    @IBAction func sjrsm(_ sender: AnyObject) {
        tetststs.text = String(test1)
        print(test1)
        if test1 == String(100) {
            erg.isHidden = true
    
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate:AppDelegate = UIApplication.shared.delegate as!     AppDelegate
    
        var test1 = appDelegate.test
    
    
        // Do any additional setup after loading the view.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    }
    
```
CC BY-SA 3.0
2017-02-05T12:59:01.067
32398
2017-02-06T02:56:29.653
2017-02-06T02:56:29.653
76
20522
question
swift swift2 swift3
異なるView Controllerでの値(変数)の共有
細かい話は置いて、根本的にまずいのはここですね。

```

    override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate:AppDelegate = UIApplication.shared.delegate as!     AppDelegate
    
        var test1 = appDelegate.test //### `viewDidLoad()`のローカル変数を宣言している
    
    
        // Do any additional setup after loading the view.
    }
    
```

コメントの###部の1行はあらたに`viewDidLoad()`の本体の中だけで使うローカル変数`test1`を宣言しており、その変数は`var test1
= String()`で宣言されている、`ViewController2`のインスタンスプロパティ`test1`とは全く別のものということになります。

(ご質問の内容どおりのコードをビルドした場合、Xcodeに警告が表示されたはずです。現在のXcodeの警告は非常によく練られた内容になっているので、1つも無視するべきではありません。)

上の行を`self.test1 = appDelegate.test ??
""`とでもすれば、ご質問内容の一番肝心なところは治るはずですが、「`viewDidLoad()`の中で値をコピーする」と言うことをすると処理の実行順序によっては正しく値がコピーできない場合も出てきます。同じ名前の変数が別の場所に出てきて混乱しやすいということもあるでしょう。

どうせなら、複数のViewControllerからアクセスされるデータは、共通データの置き場所(あなたのコードの場合、`AppDelegate`)を直接参照することにしてはいかがでしょうか。どこでいつコピーするんだ、なんてことを迷う必要が無くなります。

```

    import UIKit
    
    class ViewController2: UIViewController {
        //###AppDelegateをアクセスしやすくしておく
        var appDelegate: AppDelegate {
            return UIApplication.shared.delegate as! AppDelegate
        }
    
        @IBOutlet weak var tetststs: UILabel!
        @IBOutlet weak var fsg: UIButton!
        @IBOutlet weak var erg: UILabel!
    
        @IBAction func sjrsm(_ sender: AnyObject) {
            tetststs.text = appDelegate.test ?? "" //###共通データは直接`appDelegate`内の値を参照する
            print(appDelegate.test ?? "")
            if appDelegate.test == String(100) {
                erg.isHidden = true
    
            }
        }
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
    
            //###`viewDidLoad()`の中では特に何もしなくて良い
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    
```

アプリが大規模になってきた場合には、`AppDelegate`とは別の場所(クラス)に置いた方が良い、と言うことになる場合もあるでしょうが、上記のような作りにしておけば、それほど大きな修正にはなりません。お試しください。

* * *

ところで今後もQAサイトをちょくちょく利用される可能性が高いのでしたら、できれば(例え動作確認用のお試しプロジェクトでも)もうちょっと意味のある名前にする癖をつけた方が良いと思います。正直`B`だの`L`だのでは、一体何をするためのbuttonやlabelなのか全く見当がつかないので、質問内容が伝わりにくくなります。
CC BY-SA 3.0
2017-02-05T13:53:22.170
32403
2017-02-05T13:53:22.170
13972
32398
answer