Environment setup
Use Xcode 27 (the SDK version this course uses) on macOS. Create an iOS or macOS SwiftUI app target, set 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 under Frameworks, Libraries, and Embedded Content. 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 between SDK versions. Check the exact names in the Xcode docs you have installed. Do not copy a name you have not checked.
Assume Xcode 27 beta and a real device. The simulator is fine to check that things are wired up. It is not a source of real timing numbers. Neural Engine, specialisation (getting the model ready for this device), and load costs only make sense on the hardware that will run the clothing app.
Start with the debug gauge
Run the app with the Core AI framework linked. Open the Debug navigator. When Core AI is in the process, the debug gauge shows live Inference, Load, and Specialization activity.
Pick the same sample a few times. Watch the first pick separately from later picks. Open the Activity table and check that model setup did not run again in the photo handler.
Use the gauge's More menu to open the Core AI Debugger for the graph and tensors, or export inputs as .npy for replay.
Record a Core AI Instruments trace
Choose Product > Profile, then select the Core AI template. Record the bundled sample and a picked image several times. Look at the first setup events before the later inference runs.
- Attach a real iPhone, iPad, or Mac.
- Start recording and trigger the clothing classifier several times.
- Stop, then inspect specialisation and load before later inference.
Read the event colours
- Specialization is green.
- Load is cyan.
- Setup is magenta.
- Inference is blue.
Expand the Core AI tracks from the model down to the main function. Confirm that the blue inference intervals belong to clothing.aimodel, not another model in the process.
Good and bad traces
- Good: specialise and load once, then later picks show steady blue inference.
- Bad: green specialisation or cyan loads appear on every pick.
- Bad: setup work runs inside the PhotosPicker callback.
.task or app setup. Keep the pick handler on matching image tensors and prediction.Prepare once, predict many
final class Predictor {
private var function: InferenceFunction?
func prepare() async throws {
let url = Bundle.main.url(
forResource: "clothing", withExtension: "aimodel"
)!
let model = try await AIModel.specialize(contentsOf: url)
function = try model.loadFunction(named: "main")
}
func predict(_ image: NDArray) throws -> InferenceOutputs {
guard let function else { throw PredictorError.notReady }
return try function.run(
inputs: ["image": image], states: [:], outputViews: nil
)
}
}The exact types depend on the SDK. The structure does not: prepare once, then run many times with descriptors that match the model. Check the names against the Xcode 27 docs.
Sources: Apple Core AI and WWDC26 session 324.
Key concepts
- Use a real iPhone, iPad, or Mac for timing. The simulator only checks wiring.
- The Core AI debug gauge shows Inference, Load, and Specialization live.
- Instruments event colors: green Specialization, cyan Load, magenta Setup, blue Inference.
- A good trace specialises and loads once, then shows steady inference on later picks.
Takeaways
- The first pick should look different from later picks in the trace.
- Green specialisation or cyan load on every photo pick is a prepare-once bug.
- Expand tracks to confirm later intervals belong to
clothing.aimodelfunctionmain.