Communitygithub.com

JordanCoin/ios-skills-collection

在 iOS App 中整合並最佳化 Core ML 模型,實現裝置端機器學習推論。涵蓋模型載入(.mlmodelc、.mlpackage)、使用自動產生類別與 MLFeatureProvider 進行預測、計算單元配置(CPU、GPU、神經網路引擎)、MLTensor、VNCoreMLRequest、MLComputePlan、多模型管線及部署策略。適用於載入 Core ML 模型、進行預測、配置計算單元或分析模型效能時使用。

ios-skills-collection 是什麼?

此技能專注於在 iOS 應用程式中整合 Core ML 模型,提供從 Swift 端的模型載入、配置、預測到效能分析與部署的完整指南。支援 iOS 26+ 及 Swift 6.3,並向下相容至 iOS 14。技能詳細說明如何利用自動產生的 Swift 類別或 MLDictionaryFeatureProvider 進行預測,並包含 MLTensor(iOS 18+)等新 API 的使用範例。此外,還涵蓋多模型管線、Vision 框架整合、使用 MLComputePlan 進行效能分析以及模型部署策略(如隨軟體包、隨選資源或背景資源)。技能也強調記憶體管理的最佳實踐與常見錯誤的迴避方法,適合所有需要在 iOS 上部署 Core ML 模型的開發者。

相容平台~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 App 中載入、配置並執行 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 + 神經網路引擎預設值。讓系統決定。
.cpuOnlyCPU背景任務、音訊工作階段,或 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
}

狀態並非 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)。

模型部署

隨軟體包 vs 隨選資源

策略優點缺點
隨軟體包包含立即可用,可離線運作增加 App 下載大小
隨選資源初始下載較小首次使用前需要下載
背景資源 (iOS 16+)提前下載設定較複雜
CloudKit / 伺服器最大靈活性需要網路,設定時間較長

大小考量

  • App Store 限制:App Bundle 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()

記憶體管理

  • 進入背景時卸載: 當 App 進入背景時釋放模型參考,以釋放 GPU/ANE 記憶體。返回前景時重新載入。
  • 背景任務使用 .cpuOnly: 背景處理無法使用 GPU 或 ANE;設定 .cpuOnly 可避免無聲的降級與資源競爭。
  • 共享模型實例: 切勿從同一個已編譯模型建立多個 MLModel 實例。請使用 Actor 提供共享存取。
  • 監控記憶體壓力: 大型模型(>100 MB)可能觸發記憶體警告。註冊 UIApplication.didReceiveMemoryWarningNotification 並在記憶體壓力下釋放快取的模型。

有關具有生命週期感知載入和快取回收機制的 Actor 模型管理器,請參閱 references/coreml-swift-integration.md。

常見錯誤

不要: 在主執行緒上載入模型。 應該: 使用 MLModel.load(contentsOf:configuration:) 非同步 API 或在背景 Actor 上載入。 原因: 大型模型可能需要數秒鐘來載入,這會凍結使用者介面。

不要: 每次 App 啟動時都將 .mlpackage 重新編譯為 .mlmodelc。 應該: 使用 MLModel.compileModel(at:) 編譯一次,並將編譯後的 URL 持久性地快取。 原因: 編譯成本很高。請將 .mlmodelc 快取在 Application Support 中。

不要: 除非有特定原因,否則不要硬編碼 .cpuOnly。 應該: 使用 .all 讓系統選擇最佳計算單元。

[...已截斷以進行翻譯]

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.

相關技能