Section 12/161 menit

12. Troubleshooting & Kesalahan Umum

12. Troubleshooting & Kesalahan Umum

Error: Model Tidak Ditemukan di Bundle

swift
// ❌ Salah: tidak cek apakah file ada
let model = try ImageClassifier()

// ✓ Benar: verifikasi file ada dan generate class sukses
guard Bundle.main.url(forResource: "ImageClassifier", withExtension: "mlmodelc") != nil else {
    fatalError("ImageClassifier.mlmodel tidak ditemukan. Pastikan file sudah ditambahkan ke target.")
}
let model = try ImageClassifier()

Error: Input Shape Mismatch

swift
// Pastikan input image memiliki ukuran yang sesuai model
// Cara cek di Xcode: klik .mlmodel → lihat bagian "Inputs"

// ❌ Salah: kirim image ukuran sembarang
let input = try ModelInput(imageWith: cgImage)  // Model butuh 224x224, input 1080x1920

// ✓ Benar: resize ke ukuran yang dibutuhkan model
func resizeCGImage(_ image: CGImage, to size: CGSize) -> CGImage? {
    let context = CGContext(
        data: nil,
        width: Int(size.width),
        height: Int(size.height),
        bitsPerComponent: image.bitsPerComponent,
        bytesPerRow: 0,
        space: image.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
        bitmapInfo: image.bitmapInfo.rawValue
    )
    context?.draw(image, in: CGRect(origin: .zero, size: size))
    return context?.makeImage()
}

let resized = resizeCGImage(cgImage, to: CGSize(width: 224, height: 224))!
let input = try ModelInput(imageWith: resized)

Performance: Jangan Init Model di Setiap Request

swift
// ❌ Salah: init model setiap predict — overhead besar
func predictEveryTime(image: UIImage) throws -> String {
    let model = try ImageClassifier()  // ~50-200ms overhead per call
    let input = try ImageClassifierInput(imageWith: image.cgImage!)
    return try model.prediction(input: input).classLabel
}

// ✓ Benar: singleton atau lazy property
final class MLManager {
    static let shared = MLManager()
    
    private lazy var classifier: ImageClassifier = {
        (try? ImageClassifier(configuration: MLModelConfiguration()))!
    }()
    
    func predict(image: UIImage) throws -> String {
        guard let cgImage = image.cgImage else { throw ClassificationError.invalidImage }
        let input = try ImageClassifierInput(imageWith: cgImage)
        return try classifier.prediction(input: input).classLabel
    }
}

Memory Warning dengan Model Besar

swift
// Model LLM atau generative bisa menggunakan ratusan MB RAM
// Subscribe ke memory warning dan unload jika diperlukan

class LargeModelManager: ObservableObject {
    private var model: LargeModel?
    
    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleMemoryWarning),
            name: UIApplication.didReceiveMemoryWarningNotification,
            object: nil
        )
    }
    
    @objc private func handleMemoryWarning() {
        model = nil  // Release model dari memory
        print("Model unloaded due to memory warning")
    }
    
    func getModel() throws -> LargeModel {
        if model == nil {
            model = try LargeModel(configuration: MLModelConfiguration())
        }
        return model!
    }
}

Debug: Cek Compute Unit yang Aktual Digunakan

swift
// Gunakan Instruments → Core ML Instrument untuk profiling
// Atau log melalui MLComputePlan
func logActiveComputeDevice(modelURL: URL) async {
    if let plan = try? await MLComputePlan.load(contentsOf: modelURL, configuration: .init()) {
        // Periksa di Xcode debug output atau Instruments
        print("Model loaded with compute plan")
    }
}