Posts under App & System Services topic

Post

Replies

Boosts

Views

Activity

Issue in background notification iOS 18
Issue: I am making an application that stores data locally from notifications fired from the server. Everything works fine in the foreground but the background is having problems with not being triggered when notifications are fired. So we tried firing 2 notifications at the same time, including default and silent types. But the problem continues to arise on ios 18, when firing multiple times like that, the trigger is not handling all notifications, leading to data loss. I tried on ios 15 and it worked fine. Environment: Device or Simulator: Iphone 11 pro max (iOS 18.3.2 Steps to Reproduce: Open app, allow received notification. Move app to background mode or terminate app. Sent 2 notifications: a. Default notification payload: { "aps": { "content-available": 1 }, ”notification”: {…}, “alert”: {..}, “data": "some_value" } b. Silent notification payload: { "aps": { "content-available": 1 }, ”data": "some_value" } What I've Tried: Trigger notification in function: application(_:didReceiveRemoteNotification:fetchCompletionHandler:) Handle write data to local storage in above function, put it in background thread also. Thanks in advance!
2
0
122
2w
StoreKit Products Load After Rebuild But Not on Fresh Install (iOS/SwiftUI)
Problem: I'm implementing StoreKit 2 in my SwiftUI app. Products load successfully when I rebuild in Xcode, but on a fresh install, Product.products(for:) returns an empty array. The paywall shows "Unable to load pricing." Setup: Using StoreKit Configuration File ( .storekit ) for testing Product IDs match exactly between config and code: com..premium.lifetime (non-consumable) com..premium.monthly (auto-renewable subscription) com.****.premium.yearly (auto-renewable subscription) StoreKitManager is a @MainActor singleton with @Published properties What I've Tried: Initial delay before loading - Added 1-second delay in init before calling loadProducts() Product ID verification - Confirmed IDs match exactly between StoreKitConfig.storekit and code Retry logic with exponential backoff - Implemented 3 retry attempts with 0.5s/1s/1.5s delays Multiple calls to updatePurchasedProducts() - Called twice after initial load Verified StoreKit configuration - File is properly added to project, has valid product definitions Code Structure: swift @MainActor final class StoreKitManager: ObservableObject { static let shared = StoreKitManager() @Published private(set) var products: [Product] = [] private init() { updateListenerTask = listenForTransactions() Task { try? await Task.sleep(nanoseconds: 1_000_000_000) await loadProducts() // Returns empty on fresh install await updatePurchasedProducts() } } } Observations: ✅ Works perfectly after Xcode rebuild ❌ Fails on fresh app install (simulator & device) ❌ Product.products(for:) returns empty array (no error thrown) ✅ StoreKit configuration file is valid and properly configured Question: Why does StoreKit need a rebuild to recognize products? Is there a proper initialization sequence I'm missing for fresh installs? Environment: Xcode [Version 26.0 beta 7] iOS [IOS +17.0] Testing with StoreKit Configuration File
0
0
65
2w
Issue with Top-Up Flow on iPhone 14 Pro Max (iOS 18.6.2) in TestFlight
Hi Apple Team and Developers, I’ve been testing the Top-up flow in our app via the TestFlight environment. Across multiple devices (around 10 tested), everything works fine with no issues. However, on one specific device — iPhone 14 Pro Max running iOS 18.6.2 — I’ve noticed an intermittent issue: When performing a Top-up, the Apple UI first shows a successful purchase confirmation. Immediately afterward, another UI prompt appears asking the player to re-enter their Apple ID password. At the same time, Apple returns a ghost string that we cannot use to verify the user’s package bundle ID. This creates potential confusion for users, as they see both a success confirmation and an unexpected password prompt. I’m unsure if this behavior is expected or if there’s a recommended way to handle or prevent this issue. Has anyone else encountered something similar, or does Apple have a suggested fix/workaround for this? For reference, here’s a short video of the issue in action: \🔗 https://drive.google.com/file/d/1Ml-QpEu4ocoxn-W3wEMsFMbXy2QdwbHB/view?usp=sharing Any guidance would be greatly appreciated. Thank you for your support!
0
0
84
2w
Apple Watch Ultra exercise app and activity rings won’t connect after charging
Since upgrading to iOS 26 beta on my Apple Watch Ultra and iPhone 16 Pro Max, my exercise app and activity rings have sporadically not connected after charging. Several recent mornings, when I’ve put my watch on, the activity rings are grayed out and when I click on them, they will show no activity, even though I have been active. Similarly, when I attempt to select the activity app, it will open, but when I select an activity, it will not start the workout. I’ve tried starting and restarting the watch and phone. I’ve checked permissions, and both the watch and phone are running the latest iOS. The only fix seems to be unpairing and repairing the watch and phone which is an absolute pain. Any assistance on how to permanently fix this would be greatly appreciated.
3
0
117
2w
printf %a/%A misrounding (C99 compliance violation) when guard digit is 8
Note This issue has already been reported via Feedback Assistant as FB20512074, but the status is Investigation Complete – Unable to Diagnose with Current Information. Since this bug does not produce a crash log and is therefore difficult to capture through Feedback, I am also posting it here on the Developer Forum to provide additional details and to open discussion. ⸻ Description When formatting floating-point numbers with %a or %A, macOS libc sometimes rounds incorrectly when the guard digit equals 8. This leads to non-conformance with C99’s round-to-nearest, ties-to-even rule. ⸻ Steps to Reproduce #include <stdio.h> int main(void) { // precision 0 printf("%.0a\n", 1.5); printf("%.0a\n", 1.53); printf("%.0a\n", 1.55); printf("%.0a\n", 1.56); // precision 1 printf("%.1a\n", 0x1.380p+0); printf("%.1a\n", 0x1.381p+0); printf("%.1a\n", 0x1.382p+0); printf("%.1a\n", 0x1.383p+0); return 0; } Expected Results (per C99/C11) %.0a with inputs (1.5, 1.53, 1.55, 1.56): 0x2p+0 0x2p+0 0x2p+0 0x2p+0 %.1a with inputs (0x1.380p+0, 0x1.381p+0, 0x1.382p+0, 0x1.383p+0): 0x1.4p+0 0x1.4p+0 0x1.4p+0 0x1.4p+0 Actual Results (macOS observed) %.0a with inputs (1.5, 1.53, 1.55, 1.56): 0x1p+0 0x2p+0 0x1p+0 0x2p+0 %.1a with inputs (0x1.380p+0, 0x1.381p+0, 0x1.382p+0, 0x1.383p+0): 0x1.3p+0 0x1.4p+0 0x1.3p+0 0x1.4p+0 This shows that values slightly above half are sometimes treated as ties and rounded down incorrectly. ⸻ Root Cause Analysis Inside Libc/gdtoa/FreeBSD/_hdtoa.c, rounding is decided in dorounding(): if ((s0[ndigits] > 8) || (s0[ndigits] == 8 && (s0[ndigits + 1] & 1))) adjust = roundup(s0, ndigits); This logic has two mistakes: Half detection Correct: When the guard nibble is 8, all lower discarded digits must be checked. Current: Only the LSB of the next nibble is checked (& 1). Consequence: Cases like ...8C... (e.g. 1.55 ≈ 0x1.8C…) are strictly greater than half, but are treated as exact halves and rounded down. Tie-to-even parity check Correct: For a true half (all lower digits zero), rounding should use the parity of the last kept digit. Current: The code incorrectly uses the parity of the next discarded nibble instead. Consequence: True ties are not rounded to even reliably. ⸻ Proposed Fix (behavioral) if (s0[ndigits] > 8) { adjust = roundup(...); // strictly > half } else if (s0[ndigits] == 8) { if (any_nonzero_tail(s0 + ndigits + 1)) { adjust = roundup(...); // > half } else { // exact tie: round-to-even if (s0[ndigits - 1] & 1) adjust = roundup(...); } } ⸻ Impact This bug is not limited to %.0a; it occurs for any precision when the guard nibble is 8. It causes exact halves to round incorrectly and greater-than-half values to be rounded down. The effect is alternating outputs (zigzag) instead of consistent monotonic rounding. This is a C99 compliance violation.
1
0
137
2w
Regression: Associated domain on NFC tag or through control does not open app
Foreword: I filed a feedback a week ago and so far no one replied or at least acknowledged my feedback. That's why I'm writing here now to get some more attention (hopefully, thanks). I recorded a video to show you what exactly is happening. I am not sure where the issue belongs to exactly but it is related to associated domains, the camera (QR codes), the NFC module, App Intents and Control Center controls. https://youtu.be/sT2bZLs_6rA FB20418059 (I added some tags that are somehow related to the associated domain issue)
1
0
194
2w
Recorded video looks blurry, color-washed, low bitrate, compressed using ScreenCaptureKit
Hello everyone, I am trying to implement ScreenCaptureKit into my project, I am using MacOs 26 for the target version and followed this official project from apple regarding the screencapture kit. https://developer.apple.com/documentation/ScreenCaptureKit/capturing-screen-content-in-macos I used the official exact code and implemented in my app, but the results are not good. The video look blurry, unclear, lost colors and its like 720p honestly. The 1st video frame t is result when I integrate it in my app. After that, I used another app ( which was built in electron, they were using screencapturekit as well ) and there results were a lot better. The 2nd video frame is when I recorded using their application. It appears as close to as system display I tried multiple things, but no impressive results. For my purpose, I want to the final recorded video to be as good as the display quality of the system. I also applied .hdr local display and coronolicial, but no help with that as well. Changed codecs to .mov, .hevc, but still no help Why is not the recoded video as high quality as the display
3
0
310
1w
Failed to parse signedTransactionInfo in the notification payload. status=VERIFICATION_FAILURE
We are currently using App Store Server Notifications V2 in a production environment, but occasionally encounter the error "Failed to parse signedTransactionInfo in the notification payload. status=VERIFICATION_FAILURE." What could be the cause of this error? Also, is there a way to resolve this error? After the notification from Apple was received on the server side, it was passed to the Apple library and an error occurred in the Apple library when decryption was performed.
1
0
149
3w
Calendar's date func is not behaving as I'd expect...
When I run this in a playground: var meDate = Calendar.current.date(from: DateComponents(year: 2024, hour: 7, weekday: 3, weekdayOrdinal: 2))! print(meDate) I see: 2024-01-09 15:00:00 +0000 This seems correct to me. jan 9th is the second Tuesday in 2024 I'm in the pacific TZ, 07:00 PDT matches 15:00GMT But then I do this: meDate = Calendar.current.date(bySetting: .weekday, value: 4, of: meDate)! print(meDate) and I see: 2024-01-10 08:00:00 +0000 I would have expected my hour value (7PST/15GMT) to have been preserved. Is there a way I can update weekday, but not lose my hour?
2
0
333
3w
OS Location via Bluetooth GPS receiver
Hello, We are a software and hardware development company for the forestry and environmental sectors. We have been based in Quebec (Canada) for over 30 years now. Our Canadian market covers Quebec, Ontario, and the Maritime provinces in the east. We are currently expanding across Canada and into the northern United States. We are on Android platforms with several map and data entry applications. To ensure the success of our expansion, we aim to become part of the Apple family, which is why we are contacting you today. We have developed our own GNSS receiver to increase the location accuracy of our users. This device is called GSFGPS. It uses Bluetooth BLE to communicate with mobile devices and a high-precision GPS that transmits its position using the NMEA protocol. We would like this device to be compatible with an iPhone/iPad. We have developed a mock location application in MAUI (multi-platform). Based on our interpretation of your documentation, we understand that the concept of mock location does not exist at Apple. How can we ensure that our Bluetooth GNSS device is compatible with your iPhone/iPad devices and that they can use the position of the Bluetooth device rather than the internal GPS of your devices? We are a reseller for Juniper Systems, and we know that they have an app on the App Store that has the same features as our product. https://junipersys.com/index.php/support/article/14709 We look forward to your follow-up and recommendations.
2
0
109
1w
External GPS receiver
Hello, We are a software and hardware development company for the forestry and environmental sectors. We have been based in Quebec (Canada) for over 30 years now. Our Canadian market covers Quebec, Ontario, and the Maritime provinces in the east. We are currently expanding across Canada and into the northern United States. We are on Android platforms with several map and data entry applications. To ensure the success of our expansion, we aim to become part of the Apple family, which is why we are contacting you today. We have developed our own GNSS receiver to increase the location accuracy of our users. It uses Bluetooth BLE to communicate with mobile devices and a high-precision GPS that transmits its position using the NMEA protocol. We would like this device to be compatible with an iPhone/iPad. We have developed a mock location application in MAUI (multi-platform). Based on our interpretation of your documentation, we understand that the concept of mock location does not exist at Apple. How can we ensure that our Bluetooth GNSS device is compatible with your iPhone/iPad devices and that they can use the position of the Bluetooth device rather than the internal GPS of your devices? We are a reseller for Juniper Systems, and we know that they have an app on the App Store that has the same features as our product. https://junipersys.com/index.php/support/article/14709 We look forward to your follow-up and recommendations.
1
0
79
2w
unifiedContacts identifier vs contactRelations identifier
The documentation specifies that when Contacts framework returns unified contacts that each fetched unified contact object (CNContact) has its own unique identifier that’s different from any individual contact’s identifier in the set of linked contacts and that when refetching a unified contact, that this identifier should be used. There is also an analogous identifier within the list of contactRelations, but each of these don't seem to corespondent to the unified contacts. For example, is a new contact (Sheryl Zakroff) is created in the simulator Contacts and their spouse is set to Hank Zakroff. However, the GUID created for the contactRelations identifier does not correlate to the original Hank Zakroff GUID and cannot be searched. Is this a bug or what is the indent of the contactRelations identifier? Here's a debug output of walking the unifiedContacts: Name: Hank Zakroff 2E73EE73-C03F-4D5F-B1E8-44E85A70F170 - Other : (555) 766-4823 - Other : (707) 555-1854 Name: David Taylor E94CD15C-7964-4A9B-8AC4-10D7CFB791FD - Other : 555-610-6679 Name: Sheryl Zakroff DE783BC8-7917-4138-93F6-3AF0FD4CE083 - Other : (707) 555-1854 - Spouse: <CNContactRelation: 0x60000000dd60: name=Hank M. Zakroff> - 534B467D-CA00-46D3-897C-16EEA782C9CF - Looking for ["534B467D-CA00-46D3-897C-16EEA782C9CF"] []
1
0
192
1w
"Cannot connect to App Store" when trying to purchase subscription using Xcode built app
I'm developing an app and I think I've implemented what I need to in the swift code. However, when I click the Purchase button in my app, I see "Cannot connect to App Store" when the App Store app opens. Attached are images showing how I've configured the Sandbox user. What am I doing wrong? I expect to be able to do a fake purchase to test subscription activation in the app, but it doesn't work.
1
0
156
3w
PushKit (VoIP) delivery issue — user’s device fails to receive VoIP pushes; logging in on that device suppresses VoIP pushes for all devices of that user
We are facing an issue where VoIP notifications are not delivered to a user's device. If we login with the user credentials on another device the VoIP notifications are being received, if he logs in on his device VoIP notifications are not being received anymore on all devices. So When the user logs in on the affected device, all devices on that account stop receiving VoIP pushes (including the affected one). Logging out on the affected device restores delivery to other devices. What could cause this issue? It's only happening for this user so the configuration and mobile app PushKit code is working as intended.
0
0
74
3w
Waiting for an Async Result in a Synchronous Function
This comes up over and over, here on the forums and elsewhere, so I thought I’d post my take on it. If you have questions or comments, start a new thread here on the forums. Put it in the App & System Services > Processes & Concurrency subtopic and tag it with Concurrency. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Waiting for an Async Result in a Synchronous Function On Apple platforms there is no good way for a synchronous function to wait on the result of an asynchronous function. Lemme say that again, with emphasis… On Apple platforms there is no good way for a synchronous function to wait on the result of an asynchronous function. This post dives into the details of this reality. Prime Offender Imagine you have an asynchronous function and you want to call it from a synchronous function: func someAsynchronous(input: Int, completionHandler: @escaping @Sendable (_ output: Int) -> Void) { … processes `input` asynchronously … … when its done, calls the completion handler with the result … } func mySynchronous(input: Int) -> Int { … calls `someAsynchronous(…)` … … waits for it to finish … … results the result … } There’s no good way to achieve this goal on Apple platforms. Every approach you might try has fundamental problems. A common approach is to do this working using a Dispatch semaphore: func mySynchronous(input: Int) -> Int { fatalError("DO NOT WRITE CODE LIKE THIS") let sem = DispatchSemaphore(value: 0) var result: Int? = nil someAsynchronous(input: input) { output in result = output sem.signal() } sem.wait() return result! } Note This code produces a warning in the Swift 5 language mode which turns into an error in the Swift 6 language mode. You can suppress that warning with, say, a Mutex. I didn’t do that here because I’m focused on a more fundamental issue here. This code works, up to a point. But it has unavoidable problems, ones that don’t show up in a basic test but can show up in the real world. The two biggest ones are: Priority inversion Thread pools I’ll cover each in turn. Priority Inversion Apple platforms have a mechanism that helps to prevent priority inversion by boosting the priority of a thread if it holds a resource that’s needed by a higher-priority thread. The code above defeats that mechanism because there’s no way for the system to know that the threads running the work started by someAsynchronous(…) are being waited on by the thread blocked in mySynchronous(…). So if that blocked thread has a high-priority, the system can’t boost the priority of the threads doing the work. This problem usually manifests in your app failing to meet real-time goals. An obvious example of this is scrolling. If you call mySynchronous(…) from the main thread, it might end up waiting longer than it should, resulting in noticeable hitches in the scrolling. Threads Pools A synchronous function, like mySynchronous(…) in the example above, can be called by any thread. If the thread is part of a thread pool, it consumes a valuable resource — that is, a thread from the pool — for a long period of time. The raises the possibility of thread exhaustion, that is, where the pool runs out of threads. There are two common thread pools on Apple platforms: Dispatch Swift concurrency These respond to this issue in different ways, both of which can cause you problems. Dispatch can choose to over-commit, that is, start a new worker thread to get work done while you’re hogging its existing worker threads. This causes two problems: It can lead to thread explosion, where Dispatch starts dozens and dozens of threads, which all end up blocked. This is a huge waste of resources, notably memory. Dispatch has an hard limit to how many worker threads it will create. If you cause it to over-commit too much, you’ll eventually hit that limit, putting you in the thread exhaustion state. In contrast, Swift concurrency’s thread pool doesn’t over-commit. It typically has one thread per CPU core. If you block one of those threads in code like mySynchronous(…), you limit its ability to get work done. If you do it too much, you end up in the thread exhaustion state. WARNING Thread exhaustion may seem like just a performance problem, but that’s not the case. It’s possible for thread exhaustion to lead to a deadlock, which blocks all thread pool work in your process forever. There’s a trade-off here. Swift concurrency doesn’t over-commit, so it can’t suffer from thread explosion but is more likely deadlock, and vice versa for Dispatch. Bargaining Code like the mySynchronous(…) function shown above is fundamentally problematic. I hope that the above has got you past the denial stage of this analysis. Now let’s discuss your bargaining options (-: Most folks don’t set out to write code like mySynchronous(…). Rather, they’re working on an existing codebase and they get to a point where they have to synchronously wait for an asynchronous result. At that point they have the choice of writing code like this or doing a major refactor. For example, imagine you’re calling mySynchronous(…) from the main thread in order to update a view. You could go down the problematic path, or you could refactor your code so that: The current value is always available to the main thread. The asynchronous code updates that value in an observable way. The main thread code responds to that notification by updating the view from the current value. This refactoring may or may not be feasible given your product’s current architecture and timeline. And if that’s the case, you might end up deploying code like mySynchronous(…). All engineering is about trade-offs. However, don’t fool yourself into thinking that this code is correct. Rather, make a note to revisit this choice in the future. Async to Async Finally, I want to clarify that the above is about synchronous functions. If you have a Swift async function, there is a good path forward. For example: func mySwiftAsync(input: Int) async -> Int { let result = await withCheckedContinuation { continuation in someAsynchronous(input: input) { output in continuation.resume(returning: output) } } return result } This looks like it’s blocking the current thread waiting for the result, but that’s not what happens under the covers. Rather, the Swift concurrency worker thread that calls mySwiftAsync(…) will return to the thread pool at the await. Later, when someAsynchronous(…) calls the completion handler and you resume the continuation, Swift will grab a worker thread from the pool to continue running mySwiftAsync(…). This is absolutely normal and doesn’t cause the sorts of problems you see with mySynchronous(…). IMPORTANT To keep things simple I didn’t implement cancellation in mySwiftAsync(…). In a real product it’s important to support cancellation in code like this. See the withTaskCancellationHandler(operation:onCancel:isolation:) function for the details.
0
0
617
3w
Recursively walk a directory using File Coordination
What’s the recommended way to recursively walk through a directory tree using File Coordination? From what I understand, coordinating a read of a directory only performs a “shallow” lock; this would mean that I’d need to implement the recursive walk myself rather than use FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:) plus a single NSFileCoordinator.coordinate(with:queue:byAccessor:) call. I’m trying to extract information from all files of a particular type, so I think using NSFileCoordinator.ReadingOptions.immediatelyAvailableMetadataOnly on each file before acquiring a full read lock on it (if it’s the right file type) would make sense. Am I on the right track?
5
0
112
2w
Testing Live Caller ID Lookup Feature before App Store Release
Hi, We are working to integrate the Live Caller ID Lookup feature into our app. After submitting the request form via the link: https://developer.apple.com/contact/request/live-caller-id-lookup/, we received this reply from Apple: Apple’s OHTTP relay has been configured to talk to your OHTTP gateway. Now Live Caller ID Lookup should work for your application extension when distributed through App Store. However, before officially releasing our app on the App Store, we’d like to make sure the Live Caller ID Lookup feature is working as expected. To test this, we uploaded the app to TestFlight, and it successfully passed App Review. However, the test failed — we observed that the system tries to fetch the config from http://www.example.com/config instead of our actual configuration URL. Questions: Is this expected behavior when using TestFlight? Does the Live Caller ID Lookup feature only become active after full public release on the App Store? Is there any recommended way to test this feature before public release? Thank you!
0
0
107
3w
[CoreBluetooth] peripheral.name cached and not updating after peripheral changes
We are working with Bluetooth peripherals using CoreBluetooth, and I've noticed that the CBPeripheral.name property seems to be cached. Has anyone else encountered this behavior? Is this caching expected behavior in CoreBluetooth? Is there a recommended way to force refresh or invalidate the cached name? Most importantly: Is there a reliable method to get the most accurate and up-to-date name of a peripheral?
2
0
81
2w
Direction data not available with U2 chip (iPhone 15 Pro and iPhone 16 Pro) when using Murata SR040/SR150 accessory
Hello, I am developing with the Nearby Interaction framework using third-party UWB accessories (Murata SR040/SR150). I observed a difference between U1-based and U2-based iPhones: iPhone 12 Pro (U1 chip) NINearbyObject.direction returns valid 3D vector (x, y, z). Distance and direction both work as expected. iPhone 15 Pro and iPhone 16 Pro (U2 chip) NINearbyObject.direction is always nil. Only distance is returned (around 0.35–0.40 m in my test). Effectively behaves as "distance-only mode". Environment: Hardware: iPhone 12 Pro, iPhone 15 Pro iOS version: 18.5 Accessory: Murata UWB SR040 / SR150 App: Using NINearbyAccessoryConfiguration with BLE-based discovery Info.plist includes NSNearbyInteractionUsageDescription Camera assistance was tested both ON and OFF Expectation: I expected the U2 chip to behave consistently with U1, i.e. provide direction vectors when possible. Instead, on iPhone 15 Pro, direction is always unavailable (nil) while distance is returned correctly. Questions: Is this an intentional limitation for U2 chip + third-party accessories? Is there a new requirement (e.g. certification, firmware update, capability flags) to enable direction on U2 devices? Could this be related to NIDeviceCapability or the new Extended Distance Measurement (EDM) mode in U2? Thanks in advance for any clarification.
0
0
47
3w
App Intent Parameter (AppEntity) not registering
I'm currently testing this on a physical device (12 Pro Max, iOS 26). Through shortcuts, I know for a fact that I am able to successfully trigger the perform code to do what's needed. In addition, if I just tell siri the phrase without my unit parameter, and it asks me which unit, I am able to, once again, successfully call my perform. The problem is any of my phrases that I include my unit, it either just opens my application, or says "I can't understand" Here is my sample code: My Entity: import Foundation import AppIntents struct Unit: Codable, Identifiable { let nickname: String let ipAddress: String let id: String } struct UnitEntity: AppEntity { static var typeDisplayRepresentation: TypeDisplayRepresentation { TypeDisplayRepresentation( name: LocalizedStringResource("Unit", table: "AppIntents") ) } static let defaultQuery = UnitEntityQuery() // Unique Identifer var id: Unit.ID // @Property allows this data to be available to Shortcuts, Siri, Etc. @Property var name: String // By not including @Property, this data is NOT used for queries. var ipAddress: String var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: "\(name)" ) } init(Unit: Unit) { self.id = Unit.id self.ipAddress = Unit.ipAddress self.name = Unit.nickname } } My Query: struct UnitEntityQuery: EntityQuery { func entities(for identifiers: [UnitEntity.ID]) async throws -> [UnitEntity] { print("[UnitEntityQuery] Query for IDs \(identifiers)") return UnitManager.shared.getUnitUnits() .map { UnitEntity(Unit: $0) } } func suggestedEntities() async throws -> [UnitEntity] { print("[UnitEntityQuery] Request for suggested entities.") return UnitManager.shared.getUnitUnits() .map { UnitEntity(Unit: $0) } } } UnitsManager: class UnitManager { static let shared = UnitManager() private init() {} var allUnits: [UnitEntity] { getUnitUnits().map { UnitEntity(Unit: $0) } } func getUnitUnits() -> [Unit] { guard let jsonString = UserDefaults.standard.string(forKey: "UnitUnits"), let data = jsonString.data(using: .utf8) else { return [] } do { return try JSONDecoder().decode([Unit].self, from: data) } catch { print("Error decoding units: \(error)") return [] } } func contactUnit(unit: UnitEntity) async -> Bool { // Do things here... } } My AppIntent: import AppIntents struct TurnOnUnit: AppIntent { static let title: LocalizedStringResource = "Turn on Unit" static let description = IntentDescription("Turn on an Unit") static var parameterSummary: some ParameterSummary { Summary("Turn on \(\.$UnitUnit)") } @Parameter(title: "Unit Unit", description: "The Unit Unit to turn on") var UnitUnit: UnitEntity func perform() async throws -> some IntentResult & ProvidesDialog { //... My code here } } And my ShortcutProvider: import Foundation import AppIntents struct UnitShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: TurnOnUnit(), phrases: [ "Start an Unit with \(.applicationName)", "Using \(.applicationName), turn on my \(\.$UnitUnit)", "Turn on my \(\.$UnitUnit) with \(.applicationName)", "Start my \(\.$UnitUnit) with \(.applicationName)", "Start \(\.$UnitUnit) with \(.applicationName)", "Start \(\.$UnitUnit) in \(.applicationName)", "Start \(\.$UnitUnit) using \(.applicationName)", "Trigger \(\.$UnitUnit) using \(.applicationName)", "Activate \(\.$UnitUnit) using \(.applicationName)", "Volcano \(\.$UnitUnit) using \(.applicationName)", ], shortTitle: "Turn on unit", systemImageName: "bolt.fill" ) } }
1
0
53
3w