Swift - How to pass a view controller's reference to a sub UIView class?

ios, swift, uiview, uiviewcontroller

Solution

Following the MVC pattern, a ViewController knows about its Views, but the View shouldn't know about the ViewController. Instead you should declare delegate protocol for `GameBoardUIView` that your `ViewController` adopts as follows:

// Delegate protocol declared here
protocol GameBoardUIViewDelegate: class {
    func checkIfNextMoveExistsForGameBoardUIView(gameBoardUIView: GameBoardUIView)
}

class GameBoardUIView: UIView {

    // GameBoardUIView has a delegate property that conforms to the protocol
    // weak to prevent retain cycles
    weak var delegate:GameBoardUIViewDelegate?

    func move() {
        if !gameBoard.checkNextMoveExist() {
            delegate?.checkIfNextMoveExistsForGameBoardUIView(gameBoardUIView: self)
        }
    }

}

// View controller subclass adopts the protocol
class GameViewController: UIViewController, GameBoardUIViewDelegate {

    @IBOutlet var gameBoardUIView: GameBoardUIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        gameBoardUIView.delegate = self
    }

    // Delegte protocol method
    func checkIfNextMoveExistsForGameBoardUIView(gameBoardUIView: GameBoardUIView) {

        let alert = UIAlertController(title: "Game Over", message: nil, preferredStyle: .alert)

        alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: {(action: UIAlertAction!) in
            print("Game Over")
        }))

        // If you need to feed back to the game view you can do it in the completion block here
        present(alert, animated: true, completion: nil)
    }
}

Problem

I have a UIViewController and a UIView inside it. When I try to add an alert inside the UIView, I have to use the controller to present the UIAlertController. How do I pass the reference of UIViewController to the UIView class? Or alternatively how do I create a delegate of controller? ``` class GameViewController: UIViewController { @IBOutlet var gameBoardUIView: GameBoardUIView ... } class GameBoardUIView: UIView { ... func move() { if !gameBoard.checkNextMoveExist() { var alert = UIAlertController(title: "Game Over", message: nil, preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Cancel, handler: {(action: UIAlertAction!) in println("Game Over") })) })) // Following would fail because self is not a UIViewController here // self.presentViewController(alert, animated: true, completion: nil) } } } ```

Original source

Related problems