Metal Camera Tutorial Bonus: Running Metal project in iOS Simulator

2 minute read

In the Metal Camera Tutorial series we have created a simple app that renders camera frames on screen in real time. However, this app uses Metal framework, which is not available in iOS Simulator. Basically, your app won’t even build if you select simulator as a build device, which is a shame in case you want to add unit tests for example, being able to run them without actual device connected to your machine.

Some parts of Metal have stub implementations for desktop processor architectures, which means you can at least build the app (only to find out it’s not working as expected on the simulator). Other parts, like MetalKit don’t even exist for Simulator, so you will have to wrap the imports into conditional compilation blocks, like that:

import UIKit
import Metal

#if arch(i386) || arch(x86_64)
#else
    import MetalKit
#endif

We check if current processor architecture is a desktop one, and in this case simply don’t import any ARM-only frameworks. Beware that the classes from MetalKit are not available either, so you will need to wrap any code using them too:

public class MTKViewController: UIViewController {

#if arch(i386) || arch(x86_64)
#else
    /// `UIViewController`'s view
    private var metalView: MTKView!
#endif

    // MARK: - Public overrides
    
    override public func loadView() {
        super.loadView()
#if arch(i386) || arch(x86_64)
        NSLog("Failed creating a default system Metal device, since Metal is not available in iOS Simulator.")
#else
        assert(device != nil, "Failed creating a default system Metal device. Please, make sure Metal is available on your hardware.")
#endif
        initializeMetalView()
        initializeRenderPipelineState()
    }
    
    // MARK: - Private Metal-related properties and methods
    
    /**
     initializes and configures the `MTKView` we use as `UIViewController`'s view.
     
     */
    private func initializeMetalView() {
#if arch(i386) || arch(x86_64)
#else
        metalView = MTKView(frame: view.bounds, device: device)
        metalView.delegate = self
        metalView.framebufferOnly = true
        metalView.colorPixelFormat = .BGRA8Unorm
        metalView.contentScaleFactor = UIScreen.mainScreen().scale
        metalView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        view.insertSubview(metalView, atIndex: 0)
#endif
    }
}

With those compilation time checks you clearly won’t get your app running normally in iOS Simulator. However, it will let you build it, and, for example, cover the code not requring Metal with unit tests. You could add a stubbed camera session to verify camera permissions and delegates, for instance — well, you get the idea.

Where do I go from here?

This was the bonus part of Metal Camera Tutorial series, where we explore ways of achieving lowest-overhead access to hardware to grab camera frames, convert them to textures and render on screen in real time:

You can check out the final project from this Metal Camera Tutorial on GitHub.

Follow @alexstaravoitau Star Fork Download

Leave a Comment