SPB Git

spb/focale Public

Swift 100%
1.7 KB · 48 lines swift
Raw Blame History
1//2//  PhotoLibraryWriter.swift3//  Focale4//5//  Author: Simon-Pierre Boucher6//  Contact: contact@spboucher.ai7//8//  Writes captures into the system photo library via PHAssetCreationRequest.9//  No parallel library, no private sandbox (CLAUDE.md §4). The user can10//  uninstall tomorrow and lose nothing.11//1213import Foundation14import Photos1516actor PhotoLibraryWriter {1718    /// PhotoKit runs change blocks on its own queue; this box carries the19    /// created identifier out of the @Sendable block without giving the20    /// block any actor isolation (a Swift 6 runtime crash otherwise).21    private final class IdentifierBox: @unchecked Sendable {22        var value: String?23    }2425    /// Saves a capture and returns the new asset's localIdentifier —26    /// the key the whole index is built on.27    func save(_ photo: CapturedPhoto) async throws -> String {28        let box = IdentifierBox()29        let change: @Sendable () -> Void = {30            let request = PHAssetCreationRequest.forAsset()31            if let processed = photo.processedData {32                request.addResource(with: .photo, data: processed, options: nil)33                if let raw = photo.rawData {34                    let options = PHAssetResourceCreationOptions()35                    request.addResource(with: .alternatePhoto, data: raw, options: options)36                }37            } else if let raw = photo.rawData {38                request.addResource(with: .photo, data: raw, options: nil)39            }40            box.value = request.placeholderForCreatedAsset?.localIdentifier41        }42        try await PHPhotoLibrary.shared().performChanges(change)4344        guard let localIdentifier = box.value else { throw CaptureError.captureFailed }45        return localIdentifier46    }47}48