Search code examples
swiftuikitmetal

Can't access MTKView


I'm new to UIKit and I'm trying to write a Metal app to run on an iPhone 12. Here's the code in AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()
        return true
    }
}

Here's the code in ViewController.swift:

class ViewController: UIViewController, MTKViewDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Access the Metal view
        if let view = self.view! as? MTKView {  // Isn't working
            view.device = MTLCreateSystemDefaultDevice()
            view.delegate = self
            print("Obtained MTKView")
        } else {
            print("Failed to obtain MTKView")   // The result
        }
    }
    func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
    func draw(in view: MTKView) {}
}

This code compiles and runs, but it doesn't access the MTKView. It prints the Failed to obtain MTKView message. Any ideas? Thanks.

EDIT: I've tried self.view! and self.view, but neither work.


Solution

  • If you aren't using the storyboard, you can create a new MTKView like this:

    class ViewController: UIViewController, MTKViewDelegate {
    
        var metalView: MTKView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            
            /// Make a MetalKit view
            let metalView = MTKView()
                
            /// add positioning constraints
            metalView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                metalView.topAnchor.constraint(equalTo: view.topAnchor),
                metalView.rightAnchor.constraint(equalTo: view.rightAnchor),
                metalView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
                metalView.leftAnchor.constraint(equalTo: view.leftAnchor)
            ])
            
            metalView.device = MTLCreateSystemDefaultDevice()
            metalView.delegate = self
            
            self.metalView = metalView /// assign to the property, so you can access this later
        }
    
        func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
        func draw(in view: MTKView) {}
    }