apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README | LICENSE

commit e61386529422a6413a852f0233a196a88f4ded51
parent 86f5548e9e00c2b7ad3c1d6837bff8bc41bd0f24
Author: triesap <tyson@radroots.org>
Date:   Fri, 28 Aug 2026 05:15:04 +0000

fix(transfer): route simulator loopback locally

Diffstat:
MSources/RadrootsKit/RadrootsAppleBackgroundTransfer.swift | 57++++++++++++++++++++++++++++++---------------------------
MTests/RadrootsKitTests/RadrootsAppleBackgroundTransferTests.swift | 12+++---------
2 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/Sources/RadrootsKit/RadrootsAppleBackgroundTransfer.swift b/Sources/RadrootsKit/RadrootsAppleBackgroundTransfer.swift @@ -53,10 +53,37 @@ public struct RadrootsAppleBackgroundTransferAdapters: Sendable { downloadStagingRoot: downloadStagingRoot, now: now ) + #if targetEnvironment(simulator) + let simulatorSession = RadrootsAppleBackgroundURLSession( + identifier: normalizedSessionIdentifier, store: store, fileResolver: fileResolver, + downloadStagingRoot: downloadStagingRoot, + now: now, usesForegroundSession: true + ) + #endif return Self( - now: now, enqueue: { request in try await session.enqueue(request) }, - cancel: { identifier in await session.cancel(identifier) }, - activeTransferIdentifiers: { await session.activeTransferIdentifiers() }, + now: now, + enqueue: { request in + #if targetEnvironment(simulator) + if request.networkPolicy == .simulatorLoopbackHTTP { + try await simulatorSession.enqueue(request) + return + } + #endif + try await session.enqueue(request) + }, + cancel: { identifier in + #if targetEnvironment(simulator) + await simulatorSession.cancel(identifier) + #endif + await session.cancel(identifier) + }, + activeTransferIdentifiers: { + var identifiers = await session.activeTransferIdentifiers() + #if targetEnvironment(simulator) + identifiers.formUnion(await simulatorSession.activeTransferIdentifiers()) + #endif + return identifiers + }, handleBackgroundEvents: { identifier, completionHandler in await session.handleBackgroundEvents( identifier: identifier, completionHandler: completionHandler) @@ -66,30 +93,6 @@ public struct RadrootsAppleBackgroundTransferAdapters: Sendable { return .unavailable #endif } - - #if os(iOS) && targetEnvironment(simulator) - static func simulatorForegroundIntegration( - sessionIdentifier: String, store: any RadrootsBackgroundTransferStore, - fileResolver: any RadrootsBackgroundTransferFileResolver, - downloadStagingRoot: URL, now: @escaping @Sendable () -> Date = Date.init - ) throws -> Self { - let normalizedSessionIdentifier = - try RadrootsBackgroundTransferValidation.normalizedIdentifier(sessionIdentifier) - let session = RadrootsAppleBackgroundURLSession( - identifier: normalizedSessionIdentifier, store: store, fileResolver: fileResolver, - downloadStagingRoot: downloadStagingRoot, now: now, usesForegroundSession: true - ) - return Self( - now: now, enqueue: { request in try await session.enqueue(request) }, - cancel: { identifier in await session.cancel(identifier) }, - activeTransferIdentifiers: { await session.activeTransferIdentifiers() }, - handleBackgroundEvents: { identifier, completionHandler in - await session.handleBackgroundEvents( - identifier: identifier, completionHandler: completionHandler) - } - ) - } - #endif } public actor RadrootsAppleBackgroundTransfer: RadrootsBackgroundTransfer { diff --git a/Tests/RadrootsKitTests/RadrootsAppleBackgroundTransferTests.swift b/Tests/RadrootsKitTests/RadrootsAppleBackgroundTransferTests.swift @@ -618,17 +618,11 @@ import Testing else { return } let roots = try appleTransferRoots() defer { try? FileManager.default.removeItem(at: roots.dataRoot.deletingLastPathComponent()) } - let store = RadrootsInMemoryBackgroundTransferStore() let resolver = RadrootsAppleBackgroundTransferFileResolver(roots: roots) - let stagingRoot = roots.temporaryRoot.appendingPathComponent( - "live-urlsession", isDirectory: true) - let adapters = try RadrootsAppleBackgroundTransferAdapters.simulatorForegroundIntegration( - sessionIdentifier: "org.radroots.tests.background-transfer.\(UUID().uuidString.lowercased())", - store: store, - fileResolver: resolver, - downloadStagingRoot: stagingRoot + let transfer = try RadrootsAppleBackgroundTransfer( + roots: roots, + sessionIdentifier: "org.radroots.tests.background-transfer.\(UUID().uuidString.lowercased())" ) - let transfer = RadrootsAppleBackgroundTransfer(store: store, adapters: adapters) let destination = RadrootsFileReference( scope: .cache, relativePath: "live-urlsession/package.swift") let request = try RadrootsBackgroundTransferRequest(