Post

Replies

Boosts

Views

Activity

SPM: Create XCFramework and reusing it - simple example "error: no such module" when importing
Context: I am trying to create a XCFramework that I can reuse it in my Swift app. My example is based on SPM (Swift Package Manager) but I had the same import error no such module when I tried to import my XCFramework in XCode. Here is the code for XCFramework: Package.swift // swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "MySDK", platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)], products: [ .library(name: "MySDK", type: .dynamic, targets: ["MySDK"]), ], targets: [ .target(name: "MySDK") ] ) Sources/MySDK/my_sdk.swift public func myHelloStr() -> String { return "Bonjour le monde!" } To generate the XCFramework: $ xcodebuild build -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES $ xcodebuild -create-xcframework -framework DerivedData/Build/Products/Debug/PackageFrameworks/MySDK.framework -output MyFramework.xcframework I can see MyFramework.xcframework folder with - `Info.plist` - `macos-x86_64/MySDK.framework/MySDK` - `macos-x86_64/MySDK.framework/Resources/Info.plist` - `macos-x86_64/MySDK.framework/Versions/A/MySDK` - `macos-x86_64/MySDK.framework/Versions/A/Resources/Info.plist` - `macos-x86_64/MySDK.framework/Versions/Current/MySDK` - `macos-x86_64/MySDK.framework/Versions/Current/Resources/Info.plist` Then I create a new SPM project MyApp with Package.swift // swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "TestApp", platforms: [.macOS(.v14), .iOS(.v13), .watchOS(.v6)], products: [ .executable(name: "MyApp", targets: ["MyApp"]) ], targets: [ .executableTarget(name: "MyApp", dependencies: [ .target(name: "MyFramework") ] ), .binaryTarget( name: "MyFramework", path: "../test_sdk/MyFramework.xcframework" ) ] ) And Sources/MyApp/main.swift: import MySDK print("Hello World: \(myHelloStr())") $ swift run Building for debugging... error: emit-module command failed with exit code 1 (use -v to see invocation) /Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK' import MySDK ^ /Users/olivier/dev/test_app/Sources/MyApp/main.swift:1:8: error: no such module 'MySDK' import MySDK ^ error: fatalError If I generate my XCFramework using xcodebuild archive instead of xcodebuild build such as described in this doc https://developer.apple.com/documentation/xcode/creating-a-multi-platform-binary-framework-bundle: $ xcodebuild archive -scheme MySDK -destination "platform=macOS" -derivedDataPath DerivedData -archivePath "archives/MyFramework" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES (...) ** ARCHIVE SUCCEEDED ** $ xcodebuild -create-xcframework -archive archives/MyFramework.xcarchive -framework MySDK.framework -output MyFramework.xcframework error: the path does not point to a valid framework: /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Library/Frameworks/MySDK.framework ... it's not normal because I have these paths in /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products: /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/Users/olivier/Objects/MySDK.o /Users/olivier/dev/test_sdk/archives/MyFramework.xcarchive/Products/usr/local/lib/MySDK.framework/... XCode version $ xcodebuild -version Xcode 15.2 Build version 15C500b
2
0
1.2k
Jan ’24
How to run `xctest` bundle - or how to add `entitlement` to test?
I am writing a SPM based project for MacOS. In this project? I need to access MacOS Keychain. I am write a swift test built by SPM testTarget(). I can see it generates a bundle ./.build/x86_64-apple-macosx/debug/MyProjectTests.xctest with an executable: % file ./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest/Contents/MacOS/MyProjectPackageTests ./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest/Contents/MacOS/MyProjectPackageTests: Mach-O 64-bit bundle x86_64 This bundle file cannot be executed. How can I execute its tests? I tried with xcodebuild test-without-building -xctestrun ./.build/x86_64-apple-macosx/debug/MyProjectPackageTests.xctest -destination 'platform=macOS' without any chance. Obviously the next question is can I 'simply' add entitlement to this bundle with codesign to fix my enttilement error. My error when running the test is A required entitlement isn't present.
1
0
902
Jan ’24
SwiftData does not retrieve my inverse one-to-many Relationship
Here is my models: import SwiftData @Model final public class FirstModel { let name: String @Relationship(deleteRule: .cascade, inverse: \SecondModel.parent) var children = [SecondModel]() init(name: String) { self.name = name } } @Model final public class SecondModel { let parent: FirstModel let name: String @Relationship(deleteRule: .cascade, inverse: \ThirdModel.parent) var children = [ThirdModel]() init(name: String, parent: FirstModel) { self.name = name self.parent = parent } } @Model final public class ThirdModel { let parent: SecondModel let name: String init(name: String, parent: SecondModel) { self.name = name self.parent = parent } } Then I create my model entries: let schema = Schema([ FirstModel.self, SecondModel.self, ThirdModel.self ]) let container = try ModelContainer(for: schema) let context = ModelContext(container) let firstModel = FirstModel(name: "my first model") let secondModel = SecondModel(name: "my second model", parent: firstModel) let thirdModel = ThirdModel(name: "my third model", parent: secondModel) context.insert(firstModel) context.insert(secondModel) context.insert(thirdModel) try context.save() I want to retrieve the children from my models: print("-- Fetch Third Model") let thirdFetchDescriptor: FetchDescriptor<ThirdModel> = FetchDescriptor<ThirdModel>(predicate: #Predicate { $0.name == "my third model" }) let thirdModels = try context.fetch(thirdFetchDescriptor) for entry in thirdModels { print(">>> \(entry) - \(entry.parent) - \(entry.parent.parent)") } print("-- Fetch First Model") let firstFetchDescriptor: FetchDescriptor<FirstModel> = FetchDescriptor<FirstModel>(predicate: #Predicate { $0.name == "my first model" }) let firstModels = try context.fetch(firstFetchDescriptor) for entry in firstModels { print(">>> \(entry) - \(entry.children)") for child in entry.children { print("\t>>> \(child) - \(child.children)") } } ... But it does not seem to work: -- Fetch Third Model >>> cardapart_sdk_app_ui.ThirdModel - cardapart_sdk_app_ui.SecondModel - cardapart_sdk_app_ui.FirstModel -- Fetch First Model >>> cardapart_sdk_app_ui.FirstModel - [] What I would expect to see: -- Fetch First Model >>> cardapart_sdk_app_ui.FirstModel - [cardapart_sdk_app_ui.SecondModel] >>> cardapart_sdk_app_ui.SecondModel - [cardapart_sdk_app_ui.ThirdModel] I am not sure what I am doing wrong or missing...
1
0
653
May ’24
Make my SwiftData code concurrency proof (sendable model, singleton)
Here is my current code: @Model final public class ServerModel { @Attribute(.unique) var serverUrl: URL init(serverUrl: URL) { self.serverUrl = serverUrl } } @ModelActor public actor MyDatabaseService { public static var shared = MyDatabaseService() public init() { self.modelContainer = try! ModelContainer(for: ServerModel.self) let context = ModelContext(modelContainer) self.modelExecutor = DefaultSerialModelExecutor(modelContext: context) } public func listServers() throws -> [ServerModel] { let descriptor = FetchDescriptor<ServerModel>() return try modelContext.fetch(descriptor) } } When try to call try await MyDatabaseService.shared.listServers() There are two problems: ServerModel is not Sendable "Reference to static property 'shared' is not concurrency-safe because it involves shared mutable state; this is an error in Swift 6" For the first one, I can solve it by doing: public struct Server { let serverUrl: URL; } @Model final public class ServerModel { @Attribute(.unique) var serverUrl: URL init(serverUrl: URL) { self.serverUrl = serverUrl } func getSendable() -> Server { return Server(serverUrl: self.serverUrl) } } @ModelActor public actor MyDatabaseService { (...) public func listServers() throws -> [Server] { let descriptor = FetchDescriptor<ServerModel>() return try modelContext.fetch(descriptor).map { $0.getSendable() } } } I am wondering if there is a smarter solution to this first issue. SwiftData already require to define the model with basic/codable types, so if there was a magic way to get a sendable from the model. I try to make my model 'Codable' but 'Codable' is not compatible with 'Sendable'. For my second issue, the singleton issue. I do not really know how to fix it.
1
0
510
May ’24
SwiftData: Application crash when trying to save (and fetch) a Model with unique attribute a second time
The context is to create a model instance in SwitfData and return it. This model as a unique attribute (defined by @Attribute(.unique)). The application runs fine the first time but on the second run, it fails with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP). What the reason behind this crash? Here is my sample application to duplicate the issue. The issue is reproducible on MacOS and iOS: import SwiftUI import SwiftData @available(iOS 17, *) @available(macOS 11, *) @Model public final class MyModel : CustomStringConvertible { @Attribute(.unique) var uuid: UUID init(uuid: UUID) throws { self.uuid = uuid } public var description: String { return self.uuid.uuidString } } @available(iOS 17, *) @available(macOS 11, *) @ModelActor public actor LocalDatabaseService { public static let shared = LocalDatabaseService() let schema = Schema([MyModel.self]) public init() { self.modelContainer = try! ModelContainer(for: self.schema) let context = ModelContext(modelContainer) self.modelExecutor = DefaultSerialModelExecutor(modelContext: context) } public func createMyModel(uuid: UUID) throws -> MyModel { let myModel = try MyModel(uuid: uuid) let modelContext = self.modelContext modelContext.insert(myModel) try modelContext.save() return myModel } } struct ContentView: View { var body: some View { Task { let id = UUID(uuidString: "9C66CA5B-D91C-480F-B02C-2D14EEB49902")! let myModel = try await LocalDatabaseService.shared.createMyModel(uuid: id) print("myModel:\(myModel)") print("DONE") } return VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() } } #Preview { return ContentView() } Note: a workaround is to returned the fetched model instance return try self.getMyModel(uuid: uuid): func getMyModel(uuid: UUID) throws -> MyModel { let fetchDescriptor = FetchDescriptor<MyModel>(predicate: #Predicate { $0.uuid == uuid }) let serverList = try modelContext.fetch(fetchDescriptor) if !serverList.isEmpty { if let first = serverList.first { return first } } fatalError("Could not find MyModel with uuid \(uuid)") } ... but it does not explain the crash.
1
0
471
May ’24
Access Bluetooth in system daemon - Unauthorized
Hello, as the title says, I am trying to access Bluetooth in a system daemon. I am running on MacOS Sonoma 14.5. When initializing Bluetooth, my daemon received Unauthorized state. I have tried to add my daemon in the system settings (System Preferences > Security & Privacy > Privacy > Bluetooth) "Allow applications to access Bluetooth" by adding the program executable path defined by the entry Program of my system daemon as suggested here: https://developer.apple.com/forums/thread/662459. But I am still having the issue. Writing a system daemon with Bluetooth is not my final goal. The bigger picture is the smartcard reader driver with Bluetooth access which as the same issue and the solution is probably related. I do not remember how but my smartcard reader driver use to work with Bluetooth but it does now with the same Unauthorized error. As far as I can see daemon and smartcard drivers does not have support for entitlement. Here are the logs for my sample system daemon: my_daemon [0x6000011b0000] activating connection: mach=true listener=false peer=false name=com.apple.server.bluetooth.le.att.xpc bluetoothd [0x7f804828e8a0] activating connection: mach=false listener=false peer=true name=com.apple.server.bluetooth.le.att.xpc.peer[76672].0x7f804828e8a0 bluetoothd Received XPC message "CBMsgIdCheckIn" from session "" bluetoothd Received XPC check-in from session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" fAccessLevel 0 fProgrammaticPairing 0 fLimitedForMediaAccess 0 bluetoothd Access level is less than kXPCAccessLevelSystem for session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67". Restricted state operation not allowed bluetoothd Sending 'session attached' event for session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" bluetoothd Attached session for "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" with session: 0x7f804802d1b0, session handle: 0xef8d0000 bluetoothd Registering peripheral session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" with backgrounding: off, persistence: off (CBSR) restoreID: (null) bluetoothd Error getting Application State for <private>: <private>, 3 bluetoothd Error getting Application State for <private>: <private>, 3 bluetoothd Session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" tccRequired : 1 bluetoothd ReadyForTCC. TCC required:1 fLimitedForMediaAccess:0 fDeviceAccessForMediaExtension:0 bluetoothd Session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" : needsRestrictedStateOperation = 0, overrideRestrictedState = 0 , denylistMode = 0, receivesControllerBTClockEvents=0 my_daemon Received CBMsgIdReadyForTCC my_daemon Running performTccCheck CBManager tccAvail 1, tccRequired 1 my_daemon TCC required my_daemon [0x6000011b8000] activating connection: mach=true listener=false peer=false name=com.apple.tccd my_daemon [0x6000011b8000] failed to do a bootstrap look-up: xpc_error=[3: No such process] my_daemon [0x6000011b8000] invalidated after a failed init my_daemon send_message_with_reply(): user tccd unavailable, sending 0x600000ab4000 to system tccd my_daemon [0x6000011b4000] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system tccd [0x7fd4d1f7ed80] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[76672].0x7fd4d1f7ed80 tccd REQUEST: tccd_uid=0, sender_pid=76672, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=76672.1 tccd AUTHREQ_CTX: msgID=76672.1, function=<private>, service=kTCCServiceBluetoothAlways, preflight=no, query=1, client_dict=(null), daemon_dict=<private> tccd AUTHREQ_ATTRIBUTION: msgID=76672.1, attribution={requesting={TCCDProcess: identifier=my_daemon-5555494498236e3b5e2e395b93c13af176769937, pid=76672, auid=0, euid=0, binary_path=/Users/olivier/daemon/my_daemon}, }, tccd AUTHREQ_SUBJECT: msgID=76672.1, subject=/Users/olivier/daemon/my_daemon, tccd Refusing TCCAccessRequest for service kTCCServiceBluetoothAlways from client Sub:{/Users/olivier/daemon/my_daemon}Resp:{TCCDProcess: identifier=my_daemon-5555494498236e3b5e2e395b93c13af176769937, pid=76672, auid=0, euid=0, binary_path=/Users/olivier/daemon/my_daemon} in background session tccd AUTHREQ_RESULT: msgID=76672.1, authValue=0, authReason=5, authVersion=1, error=(null), tccd REPLY: (0) function=TCCAccessRequest, msgID=76672.1 my_daemon [0x6000011b4000] invalidated after the last release of the connection object bluetoothd Received XPC message "CBMsgIdTCCDone" from session "my_daemon-5555494498236e3b5e2e395b93c13af176769937-peripheral-76672-67" tccd [0x7fd4d1f7ed80] invalidated after getting a no-senders notification - client is gone bluetoothd [0x7f80482820f0] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system tccd [0x7fd4d32585f0] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[169].0x7fd4d32585f0 tccd REQUEST: tccd_uid=0, sender_pid=169, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=169.48 tccd [0x7fd4d313d880] activating connection: mach=true listener=false peer=false name=com.apple.tccd tccd [0x7fd4d313d880] failed to do a bootstrap look-up: xpc_error=[3: No such process] bluetoothd [0x7f80482820f0] invalidated after the last release of the connection object bluetoothd Bluetooth user permission alwaysAuth: denied tccd [0x7fd4d313d880] invalidated after a failed init tccd FORWARD: to=com.apple.tccd/0, request: { require_purpose=<xpc_null> service="kTCCServiceBluetoothAlways" function="TCCAccessRequest" preflight=true target_token={pid:76672, auid:-1, euid:0} TCCD_MSG_ID="169.48" background_session=false } tccd REPLY: from=com.apple.tccd, reply: { XPCErrorDescription="Connection invalid" } tccd forwardMessage error: Connection invalid. tccd [0x7fd4d3152bf0] activating connection: mach=false listener=false peer=true name=com.apple.tccd.system.peer[169].0x7fd4d3152bf0 bluetoothd [0x7f80482820f0] activating connection: mach=true listener=false peer=false name=com.apple.tccd.system tccd REQUEST: tccd_uid=0, sender_pid=169, sender_uid=0, sender_auid=-1, function=TCCAccessRequest, msgID=169.49 tccd [0x7fd4d32585f0] invalidated after getting a no-senders notification - client is gone tccd [0x7fd4d1f4c810] activating connection: mach=true listener=false peer=false name=com.apple.tccd tccd [0x7fd4d1f4c810] failed to do a bootstrap look-up: xpc_error=[3: No such process] tccd [0x7fd4d1f4c810] invalidated after a failed init tccd FORWARD: to=com.apple.tccd/0, request: { require_purpose=<xpc_null> service="kTCCServiceBluetoothAlways" function="TCCAccessRequest" preflight=true target_token={pid:76672, auid:-1, euid:0} TCCD_MSG_ID="169.49" background_session=false } tccd REPLY: from=com.apple.tccd, reply: { XPCErrorDescription="Connection invalid" } tccd forwardMessage error: Connection invalid.
2
0
727
Jun ’24