- iOS 10.0+
- tvOS 11.4+
- macOS 10.13+
- Xcode 11.0+
MTKView provides significant functionality, allowing you to quickly get started writing Metal code, sometimes you want more control over how your Metal content is rendered. This sample app demonstrates how to create a simple Metal view derived directly from an
UIView. It uses a
CAMetal object to hold the view’s contents.
Configure the Sample Code Project
This sample has targets for iOS, tvOS, and macOS. There are significant differences between apps that use UIKit and AppKit. Because of these differences, this sample creates two different classes. The iOS and tvOS versions of the sample use the
AAPLUIView class, and the macOS version uses the
AAPLNSView class. Both are derived from a common
This sample provides a number of options you can enable when building the app, such as whether to animate the view’s contents or handle updates through system events. You control these options by changing the preprocessor definitions in the
Configure the View With a Metal Layer
For Metal to render to the view, the view must be backed by a
All views in UIKit are layer backed. To indicate the type of layer backing, the view implements the
layer class method. To indicate that your view should be backed by a
CAMetal, you must return the
CAMetal class type.
In AppKit, you make the view layer backed by setting the view’s
wants property. The app explicitly creates a
CAMetal object and assigns it to the view’s
Render to the View
To render to the view, create a
MTLRender object that targets a texture provided by the layer. The
AAPLRenderer class stores the render pass descriptor in the
_drawable instance variable. Most of the properties of this descriptor are set up automatically when you initialize the renderer. The code configures the render pass to clear the contents of the texture, and to store any rendered contents to the texture when the render pass completes.
You also need to set the texture that the render pass renders into. Each time the app renders a frame, the renderer obtains a
CAMetal from the Metal layer. The drawable provides a texture for Core Animation to present onscreen. The renderer updates the render pass descriptor to render to this texture:
The rest of the rendering code is similar to that found in other Metal samples. For an explanation of a typical rendering path, see Using a Render Pipeline to Render Primitives.
Implement a Render Loop
To animate the view, the sample sets up a display link. The display link calls the view at the specified interval, synchronizing updates to the display’s refresh interval. The view calls the renderer object to render a new frame of animation.
AAPLUIView creates a
CADisplay in the
setup method. Because you need to know which screen the window is on before creating the display link, you call this method when UIKit calls your view’s
did method. UIKit calls this method the first time the view is added to a window and when the view is moved to another screen. The code below stops the render loop and initializes a new display link.
AAPLNSView uses a CVDisplayLink instead of a
CADisplay is not available on macOS.
CADisplay API look different, but, in principle, have the same goal, which is to allow callbacks in sync with the display.
AAPLNSView creates a
CVDisplay in the
setup method. The
setup method is called from
view, which AppKit calls immediately after loading the view. If the view is moved to another screen, AppKit also calls
view, and like the previous code for UIKit, the AppKit view must recreate the display link for the new screen.
The macOS version of this code performs a few additional steps. After creating the display link, it sets the callback and a parameter to pass to the callback. If you want rendering to happen on the main thread, it passes a dispatch source object; otherwise, it passes a reference to the view itself. Finally, it tells the display link which display the window is located on, and sets a notification to be called when the window is closed.