Environment setup
Use Xcode 27 (the SDK version this course uses) on macOS. Create an iOS or macOS SwiftUI app target, add the target's deployment settings, and drag the exported .aimodel into the target's model/resources build phase. In Xcode, add the Core AI framework to the target's Frameworks, Libraries, and Embedded Content, and install the Metal Toolchain from Xcode Settings > Components.
xcode-select --install
xcodebuild -version
# In Xcode: File > New > Project > App, Interface: SwiftUI
# Add CoreAI to the target and add the .aimodel to Copy Bundle Resources.
# Xcode Settings > Components > install Metal Toolchain.Build once with the bundled model before you add image or chat UI. Core AI and NDArray names can change with the SDK version, so check the exact names in the installed Xcode docs. Do not copy an API name you have not checked.
Metal can run an operation, but an app needs a host: a program that loads a graph, chooses its function, prepares resources, and passes buffers. Core AI is that host. In the original course, the Xcode lesson shows the API. Here, start from the lower requirement: a prepared function you can call must receive and return exactly the tensors described by clothing.aimodel.
Read the model file as a contract
AIModel owns the loaded model file. Its main function is represented by an InferenceFunction. An NDArray carries the typed, shaped data for the call. Names and setup details can change with the SDK version, so use the model viewer and the installed Xcode 27 beta docs for exact Swift names.
// Shape-first pseudocode. Confirm the exact Core AI SDK calls in Xcode.
let model = try AIModel(contentsOf: clothingURL)
let main = try model.function(named: "main")
let image = NDArray(float32: pixels, shape: [1, 1, 28, 28])
let logits = try main.infer(["image": image])
// logits is [1, 10]; softmax and label mapping are display work.
The code is a shape sketch, not a claim about one exact SDK spelling. The rule that stays the same is what matters: load clothing.aimodel, get main, pass image, read logits.
Preparation is not something a tap should do
Load and prepare in app setup, or in a task that runs once. A PhotosPicker callback should make a tensor and call the function that is already prepared. Reloading on every tap breaks the profiling idea from lesson 02. It also wastes the work that makes repeated inference useful.
What the runtime must give Metal
- It must keep the graph's supported operations and the preparation for this device.
- It must turn the array description into buffers with the right type, layout, and lifetime.
- It must make the prepared function reusable, so profiling can see inference rather than setup.
The next layer is the UI. SwiftUI does not own the model. It must give Core AI one valid array. Continue to SwiftUI as a thin helper, or revisit the original course's clothing app lesson.
Key concepts
AIModelloads the file.InferenceFunctionismain.NDArraycarries typed shaped data.- The contract is
clothing.aimodeltomaintoimage[1, 1, 28, 28]tologits[1, 10]. - Load and prepare once at app start. Every image reuses the prepared function.
- Softmax and label mapping are display work after
logits.
Takeaways
- A picker callback should build a tensor and call an already prepared function.
- Exact Swift names can change with the SDK. The shape contract does not.
- The runtime must turn array descriptions into buffers with the right type and layout.