85430


以下のようにAppDelegateを設定すると、UIViewContorllerの上にUIViewContorllerを乗っけられるのですが、この状態で上のビュー(OverlayViewController)のボタンを押しても,下のビュー(ViewController)の関数が呼び出されません。

なぜでしょうか？

`RecorgingButtonTapped---------`はprintされるのに、`pushRecording---------`はprintされないという状況です。特にエラーが出るわけでもないのに、pushRecordingを通過しないので不思議です。

これらの画面の上に画面を乗せるのは、以下のApple公式のサンプルをもとに作成しています。  
<https://developer.apple.com/documentation/arkit/streaming_an_ar_experience>

**appDelegate.swift**

[code]

    import UIKit
    
    ///- Tag: AppDelegate
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
        var overlayWindow: UIWindow!
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            guard let window = window,
                  let windowScene = window.windowScene else { fatalError() }
            
            // Create a window for the overlay.
            overlayWindow = UIWindow(windowScene: windowScene)
            
            let storyBoard = UIStoryboard(name: "Main", bundle: nil)
            let overlayViewController = storyBoard.instantiateViewController(
                identifier: "OverlayViewController")
            overlayWindow.rootViewController = overlayViewController
            overlayWindow.makeKeyAndVisible()
            
            // Make sure the overlayWindow is always above the main window.
            overlayWindow.windowLevel = window.windowLevel + 1
            
            // Make the overlayWindow transparent so that the main window remains visible underneath.
            overlayWindow.backgroundColor = .clear
            
            return true
        }
    }
    
[/code]

**ViewController.swift**

[code]

    import UIKit
    import Foundation
    
    class ViewController: UIViewController,ViewControllerDelegate {
    
        func pushRecording()
        {
            print("pushRecording---------")
            
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            OverlayViewController().delegate = self // delegateを登録
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
    
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    
[/code]

**OverlayViewController.swift**

[code]

    import UIKit
    import Foundation
    import ReplayKit
    
    protocol ViewControllerDelegate: AnyObject  {
        func pushRecording()
    }
    
    class OverlayViewController: UIViewController {
    
        var delegate: ViewControllerDelegate?
        
        @IBAction func RecorgingButtonTapped(_ sender: Any)
        {
            print("RecorgingButtonTapped---------")
            delegate?.pushRecording()
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    }
    
[/code]

**Main.storyboad**

[![画像の説明をここに入力](https://i.stack.imgur.com/NEg9D.png)](https://i.stack.imgur.com/NEg9D.png)


CC BY-SA 4.0
2022-01-01T09:52:34.833
85429
2022-01-01T13:18:53.343
2022-01-01T13:18:53.343
36446
36446
question
swift
画面のオーバーレイを使用中に別のビューの関数をdelegateで呼び出せない


> なぜでしょうか？

正しいインスタンスに`delegate`を設定することができていないからです。

この行:

[code]

            OverlayViewController().delegate = self // delegateを登録
    
[/code]

であなたは、

  * アプリの実行と全く関係を持たない`OverlayViewController`のインスタンスを生成し
  * そのインスタンスの`delegate`を設定し
  * せっかく`delegate`を設定しながら、そのインスタンスを捨てる

と言うことをやっています。

オブジェクト指向言語を使っている場合、常に「どのインスタンスを使っているのか」をもっと意識し、単にコンパイルエラーが出なくなるだけでよしとしない癖をつけないといけません。

特にUIKitベースのプログラミングの場合、`OverlayViewController()`のように、引数のない`init()`でview
controllerのインスタンスを生成するコードを見たら、99%間違っていると思った方が良いでしょう。

「`delegate`のメソッドが呼び出されるかどうか」だけでそれ以外のチェックはしていませんが、例えば上の1行を以下のように書き換える必要があるでしょう。

[code]

            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let overlayViewController = appDelegate.overlayWindow.rootViewController as! OverlayViewController
            overlayViewController.delegate = self
    
[/code]


CC BY-SA 4.0
2022-01-01T11:14:08.387
85430
2022-01-01T11:14:08.387
13972
85429
answer