InspireFaceInspireFace1.2.4.d3
Home
Get started
Get and build the SDK
Examples
  • English
  • 简体中文
GitHub
Home
Get started
Get and build the SDK
Examples
  • English
  • 简体中文
GitHub
  • Introduction
  • Get started
  • Features
  • Guides

    • Architecture and lifetime
    • Model packs
    • Image inputs and coordinates
    • Sessions and tracking
    • Face analysis
    • Recognition and FeatureHub
    • Facial landmarks
    • Liveness detection
    • Face capture
    • More API recipes
  • Language and platform

    • C API
    • C++
    • Python
    • Android
    • Apple
    • iOS
    • macOS
    • HarmonyOS
  • Get and build the SDK

    • Overview and downloads
    • Source and common options
    • Linux
    • macOS
    • Android
    • iOS
    • HarmonyOS
    • NVIDIA TensorRT
    • Rockchip NPU
    • Python packaging
  • Hardware deployment

    • ARM
    • NVIDIA TensorRT
    • Rockchip NPU
    • Python on Rockchip
  • InspireCV
  • Complete examples
  • API coverage
  • Performance
  • Image processing benchmarks
  • Troubleshooting

Objective-C and Swift

Use the same Apple API on iOS and macOS. Objective-C classes own the native handles; the Swift overlay adds throws, feature options and scoped access to borrowed results. C structs remain available when you need to work directly with buffers.

Start with the platform setup for iOS or macOS. These interfaces belong to the current development SDK; an older prebuilt package may contain only the C/C++ library. See Get and build the SDK for available downloads and source builds.

Modules and types

LanguageImportLibraries
Objective-C / Objective-C++#import <InspireFace/InspireFaceApple.h>InspireFace
Swiftimport InspireFaceSwiftInspireFace and InspireFaceSwift
C / C++#include <InspireFace/inspireface.h>InspireFace

The framework includes a Clang module and the Swift overlay includes module interfaces. An application using these modules does not need a custom bridging header. Enable ARC for Objective-C code. Use .mm only when the same file also contains C++.

Objective-CSwiftResponsibility
IFRuntimeInspireFaceRuntimeLoad the model pack and configure the process runtime.
IFSessionFaceSessionDetection, tracking, feature extraction and optional analysis.
IFImageStreamImageStreamDescribe image input; borrow pixels or retain a compatible pixel buffer.
IFImageBitmapImageBitmapOwn pixels, load files, draw and save images.
IFFaceSnapshotFaceSnapshotOwn a copy of a frame's detection results.
IFFeatureBufferFaceFeatureBufferOwn an embedding buffer and compare features.
IFFeatureHubFeatureHubManage the process-level face database.
IFCaptureSessionFaceCaptureSessionSelect capture candidates over a sequence.
IFFaceTokenFaceTokenUtilitiesCopy tokens and read landmarks.
IFDiagnosticsInspireFaceDiagnosticsVersion information, error messages and resource diagnostics.

Detect an image file

The following complete function launches the runtime, detects faces in a file and releases its resources on success or failure. Pass filesystem paths to a model resource file such as Pikachu and a JPEG or PNG image. A successful result of zero means no face was found.

This is a standalone first-run check. In an application, keep the runtime and session alive across frames; move launch and session creation into the owning worker's setup, and close them during teardown.

Complete file detection example
Objective-C
#import <InspireFace/InspireFaceApple.h>

BOOL DetectFile(NSString *modelPath, NSString *imagePath,
                HInt32 *faceCount, NSError **error) {
    *faceCount = 0;
    if (![IFRuntime launchAtPath:modelPath error:error]) return NO;
    IFSession *session = nil;
    IFImageBitmap *bitmap = nil;
    IFImageStream *stream = nil;
    BOOL success = NO;
    do {
        session = [[IFSession alloc] initWithOptions:0
                                               mode:HF_DETECT_MODE_ALWAYS_DETECT
                                       maximumFaces:10
                                         pixelLevel:320
                                    framesPerSecond:-1
                                              error:error];
        if (!session) break;
        bitmap = [[IFImageBitmap alloc] initWithContentsOfFile:imagePath
                                                     channels:3 error:error];
        if (!bitmap) break;
        HFImageBitmapData pixels = {0};
        if (![bitmap getBorrowedData:&pixels error:error]) break;
        HFImageData input = {pixels.data, pixels.width, pixels.height,
                             HF_STREAM_BGR, HF_CAMERA_ROTATION_0};
        stream = [[IFImageStream alloc] initWithBorrowedData:input error:error];
        if (!stream) break;
        HFMultipleFaceData faces = {0};
        if (![session trackStream:stream borrowedResult:&faces error:error]) break;
        for (HInt32 i = 0; i < faces.detectedNum; ++i) {
            HFaceRect rect = faces.rects[i];
            NSLog(@"face %d: x=%d y=%d width=%d height=%d", i,
                  rect.x, rect.y, rect.width, rect.height);
        }
        *faceCount = faces.detectedNum;
        success = YES;
    } while (NO);
    [stream closeWithError:NULL];
    [bitmap closeWithError:NULL];
    [session closeWithError:NULL];
    [IFRuntime terminateWithError:NULL];
    return success;
}
Swift
import Foundation
import InspireFaceSwift

func detectFile(modelPath: String, imagePath: String) throws -> Int {
    try InspireFaceRuntime.launch(path: modelPath)
    defer { try? InspireFaceRuntime.terminate() }
    let session = try FaceSession(configuration: SessionConfiguration(
        detectionMode: .alwaysDetect, maximumFaces: 10, pixelLevel: 320))
    defer { try? session.close() }
    let bitmap = try ImageBitmap(contentsOfFile: imagePath, channels: 3)
    defer { try? bitmap.close() }
    return try bitmap.withUnsafeMutablePixels { bytes, pixels in
        try ImageStream.withBorrowedBytes(
            bytes, width: pixels.width, height: pixels.height, format: .bgr
        ) { stream in
            try session.withUnsafeFaces(in: stream) { faces in
                for (index, rect) in faces.rectangles.enumerated() {
                    print("face \(index): x=\(rect.x) y=\(rect.y) " +
                          "width=\(rect.width) height=\(rect.height)")
                }
                return faces.count
            }
        }
    }
}

The file decoder produces BGR pixels with channels: 3. This example borrows the bitmap's storage and consumes all face results before another tracking call. It avoids creating a second pixel copy just to construct the stream.

Model paths and errors

Bundle the model as a resource file and resolve its real path. If it is downloaded, finish the write before launch and keep it in app-owned storage. The model file is separate from the frameworks; adding the libraries does not install a model.

Objective-C methods return NO or nil on failure and optionally populate an NSError. Swift imports these failures as throws. SDK errors use IFErrorDomain, with the native HResult in NSError.code. Check the return value; an old error variable is not a substitute for checking whether the current call succeeded.

Objective-C
NSError *error = nil;
HInt32 count = 0;
if (!DetectFile(modelPath, imagePath, &count, &error)) {
    NSLog(@"%@ (%ld): %@", error.domain, (long)error.code, error.localizedDescription);
} else {
    NSLog(@"Detected %d faces", count);
}
Swift
do {
    let count = try detectFile(modelPath: modelPath, imagePath: imagePath)
    print("Detected \(count) faces")
} catch {
    let failure = error as NSError
    print("\(failure.domain) (\(failure.code)): \(failure.localizedDescription)")
}

Pixel buffers and borrowed bytes

The CVPixelBuffer initializer retains and locks the buffer until the stream closes or its storage is replaced. It does not copy pixels or remove row padding.

Pixel formatDirect input requirement
BGRA / RGBAOne plane, exactly width × 4 bytes per row.
8-bit grayOne plane, exactly width bytes per row.
NV12, full or video rangeEven dimensions; Y and UV rows each use width bytes; UV starts immediately after width × height Y bytes.

Padded rows, separated NV12 planes and unsupported formats return HERR_INVALID_IMAGE_STREAM_PARAM. The iOS camera example includes an explicit row copy for padded BGRA. The same helper works with macOS pixel buffers.

Objective-C
#import <InspireFace/InspireFaceApple.h>

BOOL CountPixelBuffer(IFSession *session, CVPixelBufferRef pixelBuffer,
                      HFRotation rotation, HInt32 *faceCount, NSError **error) {
    *faceCount = 0;
    IFImageStream *stream = [[IFImageStream alloc] initWithPixelBuffer:pixelBuffer
                                                               rotation:rotation
                                                                  error:error];
    if (!stream) return NO;
    HFMultipleFaceData faces = {0};
    BOOL success = [session trackStream:stream borrowedResult:&faces error:error];
    if (success) *faceCount = faces.detectedNum;
    [stream closeWithError:NULL];
    return success;
}
Swift
import CoreVideo
import InspireFaceSwift

func countPixelBuffer(session: FaceSession, pixelBuffer: CVPixelBuffer,
                      rotation: ImageRotation) throws -> Int {
    let stream = try ImageStream(pixelBuffer: pixelBuffer, rotation: rotation)
    defer { try? stream.close() }
    return try session.withUnsafeFaces(in: stream) { faces in
        faces.count
    }
}

initWithBorrowedData: / ImageStream(borrowing:) keeps a pointer, not its allocation owner. Retain the original storage until the stream closes, and do not mutate it during processing. Swift's ImageStream.withBorrowedBytes closes the stream before leaving its closure; keep tracking and downstream work inside that closure.

Result ownership and cleanup

Result or resourceValidity
Borrowed faces and tokensUntil the session next tracks, resets or closes.
Borrowed embeddingUntil the next feature extraction or session close.
Pipeline result pointersUntil the corresponding result cache is updated or the session closes.
Snapshot dataUntil that snapshot closes; it is independent of subsequent session tracking.
nativeHandleBorrowed from the wrapper. Never release it separately through the C API.

Snapshot cost

A snapshot is easier to keep safely across frames, but copying its results adds latency. For ordered processing of a single camera stream, consume the session's borrowed results before the next frame. Use a snapshot when results need to outlive that processing window.

ARC releases owned native resources when their wrappers deallocate. Call close explicitly when timing matters, such as releasing a camera buffer. A second close reports an invalid-handle error; it is not an idempotent operation. Close capture objects before their parent session, and close all sessions before terminating the process runtime.

Queues and frame order

All SDK calls are synchronous. Use one serial worker per session, including tracking, pipeline processing and feature extraction. A Swift unsafe-access closure limits the intended lifetime of a view; it does not make a session safe for concurrent calls. Direct C calls through nativeHandle can invalidate borrowed pointers too.

For camera input, complete track → pipeline / extraction → copy UI values → close stream before starting the next frame. Send only owned values, such as copied rectangles and scores, to the main queue. Serialize changes to the global runtime and FeatureHub; do not reload models while other workers are processing.

CoreML runtime modes

Use the CoreML build and an Apple model pack, then select a mode before creating sessions. The setting does not enable CoreML in a CPU-only build or convert its models.

Objective-C / C modeSwiftCoreML compute units
HF_APPLE_COREML_INFERENCE_MODE_CPU.cpuCPU only.
HF_APPLE_COREML_INFERENCE_MODE_GPU.gpuCPU and GPU.
HF_APPLE_COREML_INFERENCE_MODE_ANE.neuralEngineAll available units: CoreML may select Neural Engine, GPU or CPU.
Objective-C
#import <InspireFace/InspireFaceApple.h>

BOOL ConfigureCoreML(NSError **error) {
    return [IFRuntime setCoreMLInferenceMode:HF_APPLE_COREML_INFERENCE_MODE_ANE
                                      error:error];
}
Swift
import InspireFaceSwift

func configureCoreML() throws {
    try InspireFaceRuntime.setCoreMLInferenceMode(.neuralEngine)
}

The .neuralEngine name does not force every operation onto that hardware. Availability and model support affect CoreML's choice. Initialize the mode on the same worker as the runtime setup; recreate sessions when changing a configuration that affects their models. See the iOS and macOS build chapters for the corresponding packages.

Continue with a feature

The feature guides provide Objective-C and Swift tabs for tracking, recognition, landmarks, liveness, optional analysis, FeatureHub and capture. Keep the same stream and current face token through all operations for a frame.

Edit this page
Last Updated:: 9/28/26, 8:17 PM
Contributors: Jingyu
Prev
Android
Next
iOS