Communitygithub.com

JordanCoin/ios-skills-collection

在 iOS 应用中集成并优化 Core ML 模型,实现设备端机器学习推理。涵盖模型加载(.mlmodelc、.mlpackage)、使用自动生成类和 MLFeatureProvider 进行预测、计算单元配置(CPU、GPU、神经引擎)、MLTensor、VNCoreMLRequest、MLComputePlan、多模型流水线以及部署策略。适用于加载 Core ML 模型、进行预测、配置计算单元或分析模型性能。

ios-skills-collection 是什么?

该技能为 iOS 开发者提供了完整的 Core ML 模型集成指南,专注于 Swift 侧的模型加载、配置、预测、性能分析和部署。它详细介绍了如何使用自动生成的类或 MLDictionaryFeatureProvider 进行类型安全或动态的预测,并支持异步和批处理模式以提升吞吐量。技能涵盖了 iOS 18 引入的 MLTensor 和 MLState 等现代 API,用于高效的数据预处理和状态化管理序列模型,以及 MLComputePlan 用于在推理前检查操作的计算设备分配。此外,它还提供了与 Vision 框架集成的现代(CoreMLRequest)和传统(VNCoreMLRequest)方法,并针对模型部署(包内、按需资源)、内存管理和常见陷阱给出了最佳实践建议。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/JordanCoin/ios-skills-collection/tree/HEAD/skills/dpearson2699--coreml

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Core ML Swift 集成

在 iOS 应用中加载、配置和运行 Core ML 模型。本技能涵盖 Swift 端的模型加载、预测、MLTensor、性能分析和部署。目标为 iOS 26+ 和 Swift 6.3,除非特别说明,向后兼容至 iOS 14。

范围边界: Python 端的模型转换、优化(量化、调色板化、剪枝)和框架选择归属于 apple-on-device-ai 技能。本技能仅负责 Swift 集成。

有关完整的代码模式,包括基于 Actor 的缓存、批量推理、图像预处理和测试,请参阅 references/coreml-swift-integration.md。

目录

加载模型

自动生成的类

当您将 .mlpackage 或 .mlmodelc 拖入 Xcode 时,它会生成一个带有类型化输入/输出的 Swift 类。尽可能使用此类。

import CoreML

let config = MLModelConfiguration()
config.computeUnits = .all

let model = try MyImageClassifier(configuration: config)

手动加载

当模型在运行时下载或存储在 bundle 外部时,从 URL 加载。

let modelURL = Bundle.main.url(
    forResource: "MyModel", withExtension: "mlmodelc"
)!
let model = try MLModel(contentsOf: modelURL, configuration: config)

异步加载 (iOS 16+)

在不阻塞主线程的情况下加载模型。对于大型模型建议使用此方法。

let model = try await MLModel.load(
    contentsOf: modelURL,
    configuration: config
)

运行时编译

在设备上将 .mlpackage 或 .mlmodel 编译为 .mlmodelc。对于从服务器下载的模型很有用。

let compiledURL = try await MLModel.compileModel(at: packageURL)
let model = try MLModel(contentsOf: compiledURL, configuration: config)

缓存编译后的 URL——每次启动时重新编译会浪费时间。将 compiledURL 复制到持久位置(例如,Application Support)。

模型配置

MLModelConfiguration 控制计算单元、GPU 访问和模型参数。

计算单元决策表

值使用何时选择
.allCPU + GPU + 神经引擎默认。让系统决定。
.cpuOnly仅 CPU后台任务、音频会话或 GPU 繁忙时。
.cpuAndGPUCPU + GPU需要 GPU,但模型包含 ANE 不支持的操作。
.cpuAndNeuralEngineCPU + 神经引擎对兼容模型实现最佳能效。
let config = MLModelConfiguration()
config.computeUnits = .cpuAndNeuralEngine

// 允许低优先级后台推理
config.computeUnits = .cpuOnly

配置属性

let config = MLModelConfiguration()
config.computeUnits = .all
config.allowLowPrecisionAccumulationOnGPU = true // 更快,轻微精度损失

进行预测

使用自动生成的类

生成的类提供类型化的输入/输出结构体。

let model = try MyImageClassifier(configuration: config)
let input = MyImageClassifierInput(image: pixelBuffer)
let output = try model.prediction(input: input)
print(output.classLabel)        // "golden_retriever"
print(output.classLabelProbs)   // ["golden_retriever": 0.95, ...]

使用 MLDictionaryFeatureProvider

当输入是动态的或编译时未知时使用。

let inputFeatures = try MLDictionaryFeatureProvider(dictionary: [
    "image": MLFeatureValue(pixelBuffer: pixelBuffer),
    "confidence_threshold": MLFeatureValue(double: 0.5),
])
let output = try model.prediction(from: inputFeatures)
let label = output.featureValue(for: "classLabel")?.stringValue

异步预测 (iOS 17+)

let output = try await model.prediction(from: inputFeatures)

批量预测

一次性处理多个输入以获得更好的吞吐量。

let batchInputs = try MLArrayBatchProvider(array: inputs.map { input in
    try MLDictionaryFeatureProvider(dictionary: ["image": MLFeatureValue(pixelBuffer: input)])
})
let batchOutput = try model.predictions(from: batchInputs)
for i in 0..<batchOutput.count {
    let result = batchOutput.features(at: i)
    print(result.featureValue(for: "classLabel")?.stringValue ?? "unknown")
}

有状态预测 (iOS 18+)

对需要在预测之间维护状态的模型(序列模型、LLM、音频累加器)使用 MLState。创建一次状态并将其传递给每次预测调用。

let state = model.makeState()

// 每次预测前向传递模型内部状态
for frame in audioFrames {
    let input = try MLDictionaryFeatureProvider(dictionary: [
        "audio_features": MLFeatureValue(multiArray: frame)
    ])
    let output = try await model.prediction(from: input, using: state)
    let classification = output.featureValue(for: "label")?.stringValue
}

State 不是 Sendable——请从单个 actor 或任务中使用它。调用 model.makeState() 为并发流创建独立的状态。

MLTensor (iOS 18+)

MLTensor 是一个 Swift 原生的多维数组,用于预处理/后处理。操作是惰性执行的——调用 .shapedArray(of:) 来物化结果。

import CoreML

// 创建
let tensor = MLTensor([1.0, 2.0, 3.0, 4.0])
let zeros = MLTensor(zeros: [3, 224, 224], scalarType: Float.self)

// 重塑
let reshaped = tensor.reshaped(to: [2, 2])

// 数学运算
let softmaxed = tensor.softmax()
let normalized = (tensor - tensor.mean()) / tensor.standardDeviation()

// 与 MLMultiArray 的互操作
let multiArray = try MLMultiArray([1.0, 2.0, 3.0, 4.0])
let fromMultiArray = MLTensor(multiArray)
let backToArray = tensor.shapedArray(of: Float.self)

处理 MLMultiArray

MLMultiArray 是非图像模型输入和输出的主要数据交换类型。当自动生成的类期望数组类型特征时使用它。

// 创建一个 3D 数组:[batch, sequence, features]
let array = try MLMultiArray(shape: [1, 128, 768], dataType: .float32)

// 写入值
for i in 0..<128 {
    array[[0, i, 0] as [NSNumber]] = NSNumber(value: Float(i))
}

// 读取值
let value = array[[0, 0, 0] as [NSNumber]].floatValue

// 从数据指针创建以实现零拷贝互操作
let data: [Float] = [1.0, 2.0, 3.0]
let fromData = try MLMultiArray(dataPointer: UnsafeMutableRawPointer(mutating: data),
                                 shape: [3],
                                 dataType: .float32,
                                 strides: [1])

有关高级 MLMultiArray 模式,包括 NLP 分词和音频特征提取,请参阅 references/coreml-swift-integration.md。

图像预处理

图像模型需要 CVPixelBuffer 输入。对于来自相机或相册的照片,使用 CGImage 转换。Vision 的 VNCoreMLRequest 会自动处理此操作;仅当直接使用 MLModel 预测时才需要手动转换。

import CoreVideo

func createPixelBuffer(from cgImage: CGImage, width: Int, height: Int) -> CVPixelBuffer? {
    var pixelBuffer: CVPixelBuffer?
    let attrs: [CFString: Any] = [
        kCVPixelBufferCGImageCompatibilityKey: true,
        kCVPixelBufferCGBitmapContextCompatibilityKey: true,
    ]
    CVPixelBufferCreate(kCFAllocatorDefault, width, height,
                        kCVPixelFormatType_32ARGB, attrs as CFDictionary, &pixelBuffer)

    guard let buffer = pixelBuffer else { return nil }
    CVPixelBufferLockBaseAddress(buffer, [])
    let context = CGContext(
        data: CVPixelBufferGetBaseAddress(buffer),
        width: width, height: height,
        bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(buffer),
        space: CGColorSpaceCreateDeviceRGB(),
        bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
    )
    context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
    CVPixelBufferUnlockBaseAddress(buffer, [])
    return buffer
}

有关其他预处理模式(归一化、中心裁剪),请参阅 references/coreml-swift-integration.md。

多模型流水线

当预处理或后处理需要单独的模型时,链式调用模型。

// 顺序推理:预处理器 -> 主模型 -> 后处理器
let preprocessed = try preprocessor.prediction(from: rawInput)
let mainOutput = try mainModel.prediction(from: preprocessed)
let finalOutput = try postprocessor.prediction(from: mainOutput)

对于 Xcode 管理的流水线,在 .mlpackage 中使用管道模型类型。每个子模型在其最佳计算单元上运行。

Vision 集成

使用 Vision 运行 Core ML 图像模型,并自动进行图像预处理(调整大小、归一化、色彩空间、方向)。

现代方法:CoreMLRequest (iOS 18+)

import Vision
import CoreML

let model = try MLModel(contentsOf: modelURL, configuration: config)
let request = CoreMLRequest(model: .init(model))
let results = try await request.perform(on: cgImage)

if let classification = results.first as? ClassificationObservation {
    print("\(classification.identifier): \(classification.confidence)")
}

传统方法:VNCoreMLRequest

let vnModel = try VNCoreMLModel(for: model)
let request = VNCoreMLRequest(model: vnModel) { request, error in
    guard let results = request.results as? [VNRecognizedObjectObservation] else { return }
    for observation in results {
        let label = observation.labels.first?.identifier ?? "unknown"
        let confidence = observation.labels.first?.confidence ?? 0
        let boundingBox = observation.boundingBox // 归一化坐标
        print("\(label): \(confidence) at \(boundingBox)")
    }
}
request.imageCropAndScaleOption = .scaleFill

let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer)
try handler.perform([request])

有关完整的 Vision 框架模式(文本识别、条码检测、文档扫描),请参阅 vision-framework 技能。

性能分析

MLComputePlan (iOS 17.4+)

在进行预测之前,检查每个操作将使用的计算设备。

let computePlan = try await MLComputePlan.load(
    contentsOf: modelURL, configuration: config
)
guard case let .program(program) = computePlan.modelStructure else { return }
guard let mainFunction = program.functions["main"] else { return }

for operation in mainFunction.block.operations {
    let deviceUsage = computePlan.deviceUsage(for: operation)
    let estimatedCost = computePlan.estimatedCost(of: operation)
    print("\(operation.operatorName): \(deviceUsage?.preferredComputeDevice ?? "unknown")")
}

Instruments

在 Instruments 中使用 Core ML 仪器模板来分析:

  • 模型加载时间
  • 预测延迟(每个操作细分)
  • 计算设备调度(每个操作 CPU/GPU/ANE)
  • 内存分配

在调试器外运行以获得准确结果(Xcode: Product > Profile)。

模型部署

Bundle vs 按需资源

策略优点缺点
打包在应用中即时可用,离线工作增加应用下载大小
按需资源初始下载更小首次使用前需要下载
后台资源 (iOS 16+)提前下载设置更复杂
CloudKit / 服务器最大灵活性需要网络,设置时间更长

大小注意事项

  • App Store 限制:应用包 4 GB
  • 蜂窝网络下载限制:200 MB(可以请求例外)
  • 对大于 50 MB 的模型使用 ODR 标签
  • 预编译为 .mlmodelc 以跳过设备端编译
// 按需资源加载
let request = NSBundleResourceRequest(tags: ["ml-model-v2"])
try await request.beginAccessingResources()
let modelURL = Bundle.main.url(forResource: "LargeModel", withExtension: "mlmodelc")!
let model = try await MLModel.load(contentsOf: modelURL, configuration: config)
// 完成后调用 request.endAccessingResources()

内存管理

  • 进入后台时卸载: 当应用进入后台时释放模型引用,以释放 GPU/ANE 内存。返回前台时重新加载。
  • 后台任务使用 .cpuOnly: 后台处理无法使用 GPU 或 ANE;设置 .cpuOnly 可避免静默回退和资源争用。
  • 共享模型实例: 切勿从同一编译模型创建多个 MLModel 实例。使用 actor 提供共享访问。
  • 监控内存压力: 大型模型(>100 MB)可能触发内存警告。注册 UIApplication.didReceiveMemoryWarningNotification,并在内存压力下释放缓存的模型。

有关包含生命周期感知加载和缓存淘汰的基于 actor 的模型管理器,请参阅 references/coreml-swift-integration.md。

常见错误

不要: 在主线程上加载模型。 应该: 使用 MLModel.load(contentsOf:configuration:) 异步 API 或在后台 actor 上加载。 原因: 大型模型可能需要几秒钟来加载,从而冻结 UI。

不要: 每次应用启动时都将 .mlpackage 重新编译为 .mlmodelc。 应该: 使用 MLModel.compileModel(at:) 编译一次,并持久化缓存编译后的 URL。 原因: 编译成本高昂。将 .mlmodelc 缓存到 Application Support 中。

不要: 除非有特定原因,否则硬编码 .cpuOnly。 应该: 使用 .all 并让系统选择最佳计算单元。

...(内容已截断以便翻译)

审查清单

  • 模型加载使用异步 API 或在后台执行?
  • 编译后的模型 URL 已缓存并持久化?
  • 计算单元配置符合部署目标?
  • 对于有状态模型,状态管理正确(actor 隔离)?
  • 图像预处理与模型输入要求匹配?
  • 内存压力处理已实现(卸载、重新加载)?
  • 性能已使用 MLComputePlan 分析?
  • 部署策略适合模型大小和使用模式?

参考

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

JordanCoin/ios-skills-collection

Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries. Use when the user asks about GitHub issues, pull requests, workflows, or wants to interact with GitHub repositories from the command line — including tasks like check CI status, create PR, list issues, or query the GitHub API.

JordanCoin/ios-skills-collection

Create media playback experiences using AVKit. Use when adding video players with AVPlayerViewController, enabling Picture-in-Picture, routing media with AirPlay, using SwiftUI VideoPlayer views, configuring transport controls, displaying subtitles and closed captions, or integrating AVFoundation playback with system UI.

JordanCoin/ios-skills-collection

Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing, region monitoring, CLLocationUpdate async streams, or location authorization flows. Also use when working with maps, coordinates, addresses, places, directions, distance calculations, or location-based features in Swift apps.

JordanCoin/ios-skills-collection

Display and manipulate PDF documents using PDFKit. Use when embedding PDFView to show PDF files, creating or modifying PDFDocument instances, adding annotations (highlights, notes, signatures), extracting text with PDFSelection, navigating pages, generating thumbnails, filling PDF forms, or wrapping PDFView in SwiftUI.

JordanCoin/ios-skills-collection

Implement, review, or improve in-app tips and onboarding using Apple's TipKit framework. Use when adding feature discovery tooltips, onboarding flows, contextual tips, first-run experiences, coach marks, or working with Tip protocol, TipView, popoverTip, tip rules, tip events, or feature education UI.

JordanCoin/ios-skills-collection

When the user wants to optimize their Google Play Store listing — title, short description, full description, keywords, ratings, or Play Store-specific features. Use when the user mentions "Google Play", "Android", "Play Store", "Play Console", "short description", "full description indexed", "Google Play ASO", or wants Google Play-specific keyword, creative, or ratings strategy. For iOS App Store optimization, see aso-audit and metadata-optimization.

JordanCoin/ios-skills-collection

When the user wants to implement, optimize, or use App Clips for app discovery and conversion. Use when the user mentions "App Clip", "app clip code", "mini app", "instant app", "App Clip card", "App Clip link", "no download required", "instant experience", or wants to understand how App Clips appear in App Store search. For general App Store discoverability, see aso-audit. For marketing campaigns, see ua-campaign.

JordanCoin/ios-skills-collection

When the user wants to plan a launch strategy for a new app or major update. Also use when the user mentions "app launch", "launch plan", "launch checklist", "pre-launch", "launch day", or "how to launch my app". For ongoing ASO after launch, see aso-audit. For paid acquisition during launch, see ua-campaign.

JordanCoin/ios-skills-collection

When the user wants to analyze their own app's actual performance data from App Store Connect — real downloads, revenue, IAP, subscriptions, trials, or country breakdowns synced via Appeeky Connect. Use when the user asks about "my downloads", "my revenue", "how is my app performing", "ASC data", "sales and trends", "my subscription numbers", "App Store Connect metrics", or wants to compare periods or top markets. For third-party app estimates, see app-analytics. For subscription analytics depth, see monetization-strategy.

JordanCoin/ios-skills-collection

When the user wants a full ASO health audit, review their App Store listing quality, or diagnose why their app isn't ranking. Also use when the user mentions "ASO audit", "ASO score", "why am I not ranking", "listing review", or "optimize my app store page". For keyword-specific research, see keyword-research. For metadata writing, see metadata-optimization.

JordanCoin/ios-skills-collection

Always use when working on any iOS, macOS, Swift, SwiftUI, Xcode, or Apple platform project. Routes to the correct specialized skills based on development phase and task context. This collection contains 210 skills from 28 authors covering the full iOS lifecycle.

相关技能