Post

Replies

Boosts

Views

Activity

CLServiceSession: how to check the diagnostics (authorisation status and accuracy authorisation) without prompting the user about location services (delay the prompt)?
Hello, I'm currently refactoring my app to use the new Core Location APIs introduced in iOS 17 (CLLocationUpdate) and iOS 18 (CLServiceSession). I'm not quite sure how best to reproduce the current flow I've in my app right now: At app launch: If location services are authorized when in use + full accuracy: get the user current location then stop. If the services are not yet determined or denied, do nothing. Later in the app, when a user taps on a button to get its current location: Not determined: prompt and get the user current location if authorised when in use with full accuracy, then stop. Denied: present an alert (open Settings). Authorised when in use Full accuracy: get the user current location then stop. Not full accuracy: present an alert (open Settings). My issue is that I can't find a way to determine the authorisation status without prompting the user. As soon as I create a CLServiceSession to inspect the diagnostics (CLServiceSession.Diagnostic), the user is prompted. So I can't use this at app launch as I want to delay the prompt until the user first interacts with the feature actually requiring location services. Do I still need to use CLLocationManager().authorizationStatus and CLLocationManager().accuracyAuthorization at app launch? Or am I missing something in the new APIs that allow me to check a session status without prompting? Thank you!
1
0
82
2d
SwiftUI: safeAreaInset/safeAreaBar modifier used on a NavigationStack should automatically update the content inset (margins) of Views in the NavigationStack
[Submitted as FB23732628] Hello, In my app, I want a content to be always visible at the bottom of the UI such as a button (onboarding) or a mini player (Apple Music or Apple Podcasts). It should be visible even if I navigate to a destination view (using a NavigationLink or updating the NavigationStack path). And I don't use a TabView so I can't use the tabViewBottomAccessory. If I use the safeAreaInset/safeAreaBar modifier on the NavigationStack in SwiftUI, the content insets (margins) is not automatically updated for the Views within the stack. Expected behaviour: if I use the safeAreaInset/safeAreaBar, the Views in the NavigationStack should have their content inset (margins) updated like if the safeAreaInset/safeAreaBar is applied on the NavigationStack content directly. Steps to reproduce: check the attached project, scroll at the bottom of the first List, notice the content is hidden below the button. Navigate to the detail view, scroll at the bottom and notice the content is hidden below the button. Regards Axel import SwiftUI struct NavigationStackSafeAreaInset: View { var body: some View { NavigationStack { List { ForEach(0...20, id: \.self) { int in NavigationLink { List { ForEach(0...20, id: \.self) { int in Text(int.formatted()) } } } label: { Text(int.formatted()) } } } } .safeAreaInset(edge: .bottom) { Button { } label: { Text("New") .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) .controlSize(.large) .buttonBorderShape(.capsule) .padding() } } } #Preview { NavigationStackSafeAreaInset() }
0
0
210
Jul ’26
How to get the correct animation when inserting/removing a row in a SwiftUI List from a swipeAction?
Hello, In my app, I have a List with two sections. The first section contains favourited items. The second section contains all the items. I use a swipeAction to favorite / undo favorite an item. An item can be in the first section and in the second section. But when I use the swipeAction to perform the action, the row animation is conflicting with the List animation for insertion / removal (I think). It’s not synchronised and it leads to an ugly UX. GeometryGroup on the Section does not help. One solution is to delay the action so the swipe has enough time to go back to its original position but it’s hacky and depends too much on manual timing, etc. If I favorite / undo from a tap on the row (no swipe action), the animation is correct (obviously, as the row doesn’t need to animate to its original position). I experimented with a ScrollView + swipeActionsContainer() + swipeActions on iOS 27, and it works very nicely. But this solution only works for iOS 27 and my app targets iOS 18. So I would love to have a native implementation for iOS 18+ if possible. Am I missing something to get the correct animation with a List? You can check the attached code: https://gist.github.com/alpennec/f9de25cda29b515eb45af6b368a89ed8 Video: https://www.dropbox.com/scl/fi/sqitivihm4pbu8htxicap/ListSectionsSwipeActions.mov?rlkey=08wl708g82rmyy6nkf75725bv&st=0qb7rhdd&dl=0 I also filed a feedback with a video: FB23661327 Regards, Axel
1
2
415
Jul ’26
AppIntents and String catalog: how can we support both singular and plural forms for TypeDisplayRepresentation (used by DeleteIntent in the Shortcuts app for example)
Hello, I’m implementing the AppIntents framework in my app. I want to translate the TypeDisplayRepresentation that is used in the Shortcuts app UI like in a DeleteIntent (see my feedback about this: FB23451186 for more context). In the “Accelerating app interactions with App Intents” sample code we can see that this is done using a .stringsdict file, as follows for the “Trail” key (singular and plural): <key>Trail</key> <dict> <key>NSStringLocalizedFormatKey</key> <string>%#@VARIABLE@</string> <key>VARIABLE</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>one</key> <string>Trail</string> <key>other</key> <string>Trails</string> </dict> </dict> I want to use a String catalog instead of a .stringsdict file because all my strings are in a String catalog. I tried to migrate the AppIntents.stringsdict file manually but it failed with an error: “An error occurred when migrating AppIntentsSampleApp/Resources/AppIntents.stringsdict: This stringsdict cannot be migrated: Missing required key 'NSStringFormatValueTypeKey' inside 'Trail' -> 'VARIABLE’” So I manually added a NSStringFormatValueTypeKey like this in the .stringsdict file: <key>Trail</key> <dict> <key>NSStringLocalizedFormatKey</key> <string>%#@VARIABLE@</string> <key>VARIABLE</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> <string>lld</string> <key>one</key> <string>Trail</string> <key>other</key> <string>Trails</string> </dict> </dict> And then I’ve been able to migrate the .stringsdict file into a String catalog. The string catalog looks like this after migration: "Trail" : { "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { "state" : "translated", "value" : "%#@VARIABLE@" }, "substitutions" : { "VARIABLE" : { "formatSpecifier" : "lld", "variations" : { "plural" : { "one" : { "stringUnit" : { "state" : "translated", "value" : "Trail (Catalog)" } }, "other" : { "stringUnit" : { "state" : "translated", "value" : "Trails (Catalog)" } } } } } } } } This works, which is nice. But I tried to reproduce the same result by having a %#@VARIABLE@ in my LocalizedStringResource defaultValue like this: TypeDisplayRepresentation( name: LocalizedStringResource( "Flower", defaultValue: "%#@VARIABLE@", table: "AppIntents" ), numericFormat: LocalizedStringResource( "\(placeholder: .int) flower", table: "AppIntents" ) ) But the String catalog doesn’t support that apparently, I can’t get a “substitution” object in my catalog, so I have to manually do it using the source code which is not ideal and painful. Is there a way to support this kind of substitution with no actual plural token in the string as we can see for the %#@VARIABLE@ for Trail? Thank you, Regards, Axel
1
0
550
Jun ’26
AppIntents: how to present a searchable modal picker for an entity relation in an automatic "Find" intent (from EnumerableEntityQuery or EntityPropertyQuery)
Hello, My (fictional) app has multiple app entities like a BookEntity and an AuthorEntity. There is a relationship between them: a book has an author. Because I implement the EntityPropertyQuery for the BookEntityQuery, it creates a “Find Book where...” intent. In this intent, I can filter the data by an author (AuthorEntity). But I can’t find a way to allow the user to select any author using the searchable modal usually presented to “choose” a parameter value from an intent for example. Right now, it shows: a menu with the suggestedEntities() authors if the AuthorEntityQuery implements this function. With no way to search even if the AuthorEntityQuery conforms to the EntityStringQuery. a menu with allEntities() authors if the AuthorEntityQuery conforms to EnumerableEntityQuery and does not implement the suggestedEntities(). With no way to search even if the AuthorEntityQuery conforms to the EntityStringQuery. nothing if suggestedEntities() is not implemented and allEntities() is also not implemented even if the AuthorEntityQuery conforms to the EntityStringQuery. So this means if I implement suggestedEntities(), my users have no way to choose any author not in the suggestions. It’s too limited. if I implement allEntities() but not suggestedEntities(), this could potentially be a lot of entities and it’s not always relevant because then the Shortcuts app with an AuthorEntity parameter will be created for allEntities(), and the UI with always show the full list of allEntities() when I have to pick an author (unless I build a specific DynamicOptionsProvider but this would mean I lose the suggestedEntities() for example. if I just conforms to EntityStringQuery, I can’t select any item at all for this filter (no menu to choose). You can check the attached sample code provided. I checked a bit other apps, for example the Photos app allows you to find a photo based on an album but it lists ALL the albums (which is a lot) with no way to search using string. I also check the Sofa app, it shows the list of SofaListEntity (which implements suggestedEntities() and conforms to EntityStringQuery and EntityQuery). It actually shows all the lists (confirmed by the developer) with no way to search. See attachements from the Sofa developer. Is there a way to support a search for a filter using a relationship conforming to the EntityStringQuery? Is there a way to specify a provider for a @Property of an entity like we can for a @Parameter? For example, I could provide a custom DynamicOptionsProvider for the @Property(title: “Author”) var author which would be independent from the AuthorEntityQuery used elsewhere (parameter intents + Shortcuts). Maybe you can suggest another way to implement this? Maybe I should not rely on a relationship but instead flatten the relationship in the BookEntity to add an “authorName” or “authorID”? I filed this feedback with a sample code: FB23453134 Thanks, Regards, Axel
0
1
330
Jun ’26
DeleteIntent: the singular typeDisplayRepresentation of the AppEntity is used instead of the entities parameter title (plural)
Hello, I'm using a DeleteIntent in my app, but I can't get it to display "Delete {Books}" in the Shortcut apps. It always displays "Delete {Book}". It apparently uses the BookEntity typeDisplayRepresentation instead of using the intent entities parameter title ("Books") in the parameterSummary. For a "normal" AppIntent, the Shortcuts app uses the entities parameter title ("Books") in the parameterSummary. I filed a feedback: FB23451186 Regards, Axel
0
0
283
Jun ’26
CSSearchableItem init(appEntity:) crashes on iOS 18.0+
Hello, In my app, I want to create a CSSearchableItem using the initialiser that accepts an appEntity so I can update the item expirationDate when indexing. This initialiser is marked as iOS 18.0+ but as soon as I launch my app, it crashes. I filed a feedback: FB23270394 Can you help? Thank you Axel dyld[62169]: Symbol not found: _$s10AppIntents13IndexedEntityPAAE15hideInSpotlightSbvg Referenced from: <150E43FA-D9F4-3DF3-88C1-86E3DA3B272B> /Users/axel/Library/Developer/CoreSimulator/Devices/2C645A0F-45E5-429E-82EE-0C71D83407E3/data/Containers/Bundle/Application/18F00389-5CE8-49A2-883A-CDA38DDB03C4/Skipper.app/Skipper.debug.dylib Expected in: <F5744EDB-79CF-333C-A49A-8E9C5C3ACD10> /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AppIntents.framework/AppIntents Symbol not found: _$s10AppIntents13IndexedEntityPAAE15hideInSpotlightSbvg Referenced from: <150E43FA-D9F4-3DF3-88C1-86E3DA3B272B> /Users/axel/Library/Developer/CoreSimulator/Devices/2C645A0F-45E5-429E-82EE-0C71D83407E3/data/Containers/Bundle/Application/18F00389-5CE8-49A2-883A-CDA38DDB03C4/Skipper.app/Skipper.debug.dylib Expected in: <F5744EDB-79CF-333C-A49A-8E9C5C3ACD10> /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AppIntents.framework/AppIntents dyld config: DYLD_ROOT_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot DYLD_LIBRARY_PATH=/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator DYLD_INSERT_LIBRARIES=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libLogRedirect.dylib:/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libMainThreadChecker.dylib:/usr/lib/libRPAC.dylib:/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libViewDebuggerSupport.dylib DYLD_FRAMEWORK_PATH=/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator:/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator/PackageFrameworks DYLD_FALLBACK_FRAMEWORK_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks DYLD_FALLBACK_LIBRARY_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib Debug session ended with code 9: killed
1
0
417
Jun ’26
Spotlight: searching with Spotlight on iOS 17+ only works for the title or displayName, not any other indexed attribute from the CSSearchableItem.
Hello, I’m indexing content in my app using Core Spotlight. On iOS, I notice that I can only search using the title or displayName even if I index more content in Spotlight using CSSearchableItem or IndexedEntity. On macOS, I can search for any content or attributes of the CSSearchableItem or IndexedEntity. See attached screenshots (the item id on iOS is 708 and the item id on macOS is 741). On both platforms, the content can be fetched using a CSSearchQuery. I filed a feedback with an attached project: FB23317556 Regards Axel
0
2
327
Jun ’26
macOS 27: indexing using CSSearchableItem does not work. But using an IntentEntity works.
Hello, I’m using Core Spotlight in my app. I notice that if I use CSSearchableIndex to index the content, it cannot be found in Spotlight on macOS 27. if I use instead an IndexedEntity (from the AppIntents framework), the content can be found on macOS 27. The content seems to correctly be saved because I can fetch the content using a CSSearchQuery in both cases. I filed a feedback with a project attached: FB23317414 Regards, Axel
0
1
352
Jun ’26
How to detect if a migration is required?
Hello, With Core Data, we can use the isConfiguration(withName:compatibleWithStoreMetadata:) method on an NSManagedObjectModel alongside metadata(for:) on NSPersistentStoreCoordinator to check if the on-disk store is up to date or not. Is this the way to do it too with SwiftData or do we have an easier way to check if the on-disk store will need to migrate? I want to inform my users in the UI when the app launches (or from widgets or app intents). Regards, Axel
0
0
969
Jun ’26
Working with visits and significant location changes following Core Location updates in iOS 17 and iOS 18
Hello, I'm working on an application that requires the use of significant location changes and visits, in addition to region monitoring and standard continuous location delivery (foreground and background). iOS 17 and iOS 18 introduced changes to how we can monitor distinct regions of interest (with CLMonitor) as well as receive location updates (with CLLocationUpdate). But I couldn't find any information regarding how to work with Significant location changes. Do we still need to create a location manager and call startMonitoringSignificantLocationChanges()? Where are the updates received in this case, in the locationManager(_:didUpdateLocations:) or in the liveUpdates async sequence? Visits. Same question here, for visit monitoring to work, do we still have to create a location manager then call startMonitoringVisits()? Where are the visits being notified? Still in locationManager(_:didVisit:) or in the liveUpdates asynchronous sequence? I just want to be sure I understand correctly how to use the updates, and if some features of Core Location still need to use a location manager and the delegate to receive the events. Maybe additional CLCondition will be added to cover both of these technologies as it seems highly related to monitoring conditions (significant location change, and visit). Thank you, Axel
1
0
774
Jun ’26
How to present a View above everything in SwiftUI?
Hello, I'm trying to present an app overlay (like an HUD) that should appear on top of everything (the app UI could be the root content view or a modal presented from the content view or a modal over a modal presented from the content view, etc.). If I use a ZStack for example, the issue is that the view is not visible if the ZStack is presenting a modal for example. In UIKit, I think we can use instantiate another UIWindow to show content above the top window of the app (what a native alert does if I'm not wrong). What would be the equivalent in SwiftUI? How could I create this? Thanks, Axel
2
0
273
Jun ’26
StoreKit 2: is there a way for an app to be informed in real time if an auto-renewable subscription is cancelled by the user?
Hello, In my iOS app, I have a customer center where the user can see some details about its current subscription. I display things like the billing period, the price, the introductory offer state, the renewal date if it's not cancelled or the expiration date if it's cancelled, etc. From this screen, the user can open the subscription management sheet. I want to detect if the user cancels the subscription from this sheet or from the App Store (when the app is running) so I can refresh the information displayed on my customer center. I checked the asynchronous sequences provided by StoreKit 2 like Transaction.updates or Product.SubscriptionInfo.Status.updates and tested with a Sandbox account on my physical device with the app debugged using Xcode. But I noticed these sequences don't emit when I cancel the subscription in Sandbox. Is this the expected behavior? Is there a way to observe in real time if a user cancels the subscription? I can still manually check when the sheet is dismissed but it's not ideal because I want to know even if the user cancel from outside of the app with the app running. Thank you, Axel
2
1
758
Feb ’26
Product.SubscriptionInfo subscriptionPeriod does not provide the same result between the Sandbox/App Store environment and the StoreKit Testing in Xcode for a "1 week" subscription. "1 week" vs "7 days"
Hello, I noticed the Product.SubscriptionInfo subscriptionPeriod (of type Product.SubscriptionPeriod) is different for the same product between StoreKit Testing in Xcode and the sandbox/App Store (production) environment. For a “1 week” auto-renewable subscription, we get the following: StoreKit Testing in Xcode: 1 week gives a subscriptionPeriod with value of 1 and a unit of Product.SubscriptionPeriod.Unit.week Sandbox/App Store: 1 week gives a subscriptionPeriod with value of 7 and a unit of Product.SubscriptionPeriod.Unit.day This created issues in my app because I used the localizedDescription of a Product.SubscriptionPeriod to display a text similar to “$4.99 per week”. This is what I obtain with the StoreKit Testing in Xcode, but in the Sandbox/App Store environment, it displays “$4.99 per day” (because the subscriptionPeriod is “7 Days” and the unit is then .day). Obviously, this is not what I wanted to display. Other periods like “1 month”, “2 months”, “3 months”, “6 months, and “1 year”, the period provided by both StoreKit Testing and Sandbox/App Store correspond to the period unit specified in App Store Connect. In addition, I want to report that for a weekly subscription/offer or a 2 weeks offer, Product.SubscriptionInfo.subscriptionPeriod or Product.SubscriptionOffer.period == .weekly or .everyTwoWeeks is always false. We observe the following: With Sandbox or App Store live production: 1 week, Product.SubscriptionInfo.subscriptionPeriod == .weekly is false (because it’s “7 days”) 1 week, Product.SubscriptionOffer.period == .weekly is false (because it’s “7 days”) 2 weeks (offer), Product.SubscriptionInfo.subscriptionPeriod == .everyTwoWeeks is false (because it’s “14 days”) 2 weeks (offer), Product.SubscriptionOffer.period == .everyTwoWeeks is false (because it’s “14 days”) But with an Xcode StoreKit configuration file: 1 week, Product.SubscriptionInfo.subscriptionPeriod == .weekly is true (because it’s “1 week”) 1 week, Product.SubscriptionOffer.period == .weekly is true (because it’s “1 week”) 2 weeks, Product.SubscriptionInfo.subscriptionPeriod == . everyTwoWeeks is true (because it’s “2 weeks”) 2 weeks, Product.SubscriptionOffer.period == . everyTwoWeeks is true (because it’s “2 weeks”) So in sandbox and production, .weekly and .everyTwoWeeks is never possible. If someone from Apple could check the feedback FB19605865 🙂 Thank you Regards, Axel, @alpennec Code: do { let productIDs: [String] = ["revenueSocks_weekly_trial"] let products: [StoreKit.Product] = try await Product.products (for: productIDs) let weeklySubscription: StoreKit.Product = products.first! let displayPrice: String = weeklySubscription.displayPrice // For a weekly subscription in App Store Connect // With an Xcode StoreKit configuration file: subscriptionPeriod unit is Week (week), value is 1 → "1 Week" // With the Sandbox + App Store: subscriptionPeriod unit is Day (.day), value is 7 → "7 Days" let unitString: String = weeklySubscription.subscription!.subscriptionPeriod.unit.localizedDescription print("\(displayPrice) per \(unitString.localizedLowercase)") // StoreKit configuration file → "$4.99 per week" // Sandbox + App Store → "$4.99 per day" } catch { print(error) }
0
0
186
Nov ’25
CLServiceSession: how to check the diagnostics (authorisation status and accuracy authorisation) without prompting the user about location services (delay the prompt)?
Hello, I'm currently refactoring my app to use the new Core Location APIs introduced in iOS 17 (CLLocationUpdate) and iOS 18 (CLServiceSession). I'm not quite sure how best to reproduce the current flow I've in my app right now: At app launch: If location services are authorized when in use + full accuracy: get the user current location then stop. If the services are not yet determined or denied, do nothing. Later in the app, when a user taps on a button to get its current location: Not determined: prompt and get the user current location if authorised when in use with full accuracy, then stop. Denied: present an alert (open Settings). Authorised when in use Full accuracy: get the user current location then stop. Not full accuracy: present an alert (open Settings). My issue is that I can't find a way to determine the authorisation status without prompting the user. As soon as I create a CLServiceSession to inspect the diagnostics (CLServiceSession.Diagnostic), the user is prompted. So I can't use this at app launch as I want to delay the prompt until the user first interacts with the feature actually requiring location services. Do I still need to use CLLocationManager().authorizationStatus and CLLocationManager().accuracyAuthorization at app launch? Or am I missing something in the new APIs that allow me to check a session status without prompting? Thank you!
Replies
1
Boosts
0
Views
82
Activity
2d
SwiftUI: safeAreaInset/safeAreaBar modifier used on a NavigationStack should automatically update the content inset (margins) of Views in the NavigationStack
[Submitted as FB23732628] Hello, In my app, I want a content to be always visible at the bottom of the UI such as a button (onboarding) or a mini player (Apple Music or Apple Podcasts). It should be visible even if I navigate to a destination view (using a NavigationLink or updating the NavigationStack path). And I don't use a TabView so I can't use the tabViewBottomAccessory. If I use the safeAreaInset/safeAreaBar modifier on the NavigationStack in SwiftUI, the content insets (margins) is not automatically updated for the Views within the stack. Expected behaviour: if I use the safeAreaInset/safeAreaBar, the Views in the NavigationStack should have their content inset (margins) updated like if the safeAreaInset/safeAreaBar is applied on the NavigationStack content directly. Steps to reproduce: check the attached project, scroll at the bottom of the first List, notice the content is hidden below the button. Navigate to the detail view, scroll at the bottom and notice the content is hidden below the button. Regards Axel import SwiftUI struct NavigationStackSafeAreaInset: View { var body: some View { NavigationStack { List { ForEach(0...20, id: \.self) { int in NavigationLink { List { ForEach(0...20, id: \.self) { int in Text(int.formatted()) } } } label: { Text(int.formatted()) } } } } .safeAreaInset(edge: .bottom) { Button { } label: { Text("New") .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) .controlSize(.large) .buttonBorderShape(.capsule) .padding() } } } #Preview { NavigationStackSafeAreaInset() }
Replies
0
Boosts
0
Views
210
Activity
Jul ’26
How to get the correct animation when inserting/removing a row in a SwiftUI List from a swipeAction?
Hello, In my app, I have a List with two sections. The first section contains favourited items. The second section contains all the items. I use a swipeAction to favorite / undo favorite an item. An item can be in the first section and in the second section. But when I use the swipeAction to perform the action, the row animation is conflicting with the List animation for insertion / removal (I think). It’s not synchronised and it leads to an ugly UX. GeometryGroup on the Section does not help. One solution is to delay the action so the swipe has enough time to go back to its original position but it’s hacky and depends too much on manual timing, etc. If I favorite / undo from a tap on the row (no swipe action), the animation is correct (obviously, as the row doesn’t need to animate to its original position). I experimented with a ScrollView + swipeActionsContainer() + swipeActions on iOS 27, and it works very nicely. But this solution only works for iOS 27 and my app targets iOS 18. So I would love to have a native implementation for iOS 18+ if possible. Am I missing something to get the correct animation with a List? You can check the attached code: https://gist.github.com/alpennec/f9de25cda29b515eb45af6b368a89ed8 Video: https://www.dropbox.com/scl/fi/sqitivihm4pbu8htxicap/ListSectionsSwipeActions.mov?rlkey=08wl708g82rmyy6nkf75725bv&st=0qb7rhdd&dl=0 I also filed a feedback with a video: FB23661327 Regards, Axel
Replies
1
Boosts
2
Views
415
Activity
Jul ’26
Shortcuts and App Intents does not work on simulators running iOS 26 or iOS 27
Hello, Shortcuts and App Intents don't work on simulators running iOS 26 or iOS 27. It's working fine on simulators running iOS 18. It makes testing and adopting new technologies difficult. Please check this feedback which contains a video showcasing the issue with a sample code provided by Apple: FB23342158 Regards, Axel
Replies
3
Boosts
2
Views
527
Activity
Jul ’26
AppIntents and String catalog: how can we support both singular and plural forms for TypeDisplayRepresentation (used by DeleteIntent in the Shortcuts app for example)
Hello, I’m implementing the AppIntents framework in my app. I want to translate the TypeDisplayRepresentation that is used in the Shortcuts app UI like in a DeleteIntent (see my feedback about this: FB23451186 for more context). In the “Accelerating app interactions with App Intents” sample code we can see that this is done using a .stringsdict file, as follows for the “Trail” key (singular and plural): <key>Trail</key> <dict> <key>NSStringLocalizedFormatKey</key> <string>%#@VARIABLE@</string> <key>VARIABLE</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>one</key> <string>Trail</string> <key>other</key> <string>Trails</string> </dict> </dict> I want to use a String catalog instead of a .stringsdict file because all my strings are in a String catalog. I tried to migrate the AppIntents.stringsdict file manually but it failed with an error: “An error occurred when migrating AppIntentsSampleApp/Resources/AppIntents.stringsdict: This stringsdict cannot be migrated: Missing required key 'NSStringFormatValueTypeKey' inside 'Trail' -> 'VARIABLE’” So I manually added a NSStringFormatValueTypeKey like this in the .stringsdict file: <key>Trail</key> <dict> <key>NSStringLocalizedFormatKey</key> <string>%#@VARIABLE@</string> <key>VARIABLE</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> <string>lld</string> <key>one</key> <string>Trail</string> <key>other</key> <string>Trails</string> </dict> </dict> And then I’ve been able to migrate the .stringsdict file into a String catalog. The string catalog looks like this after migration: "Trail" : { "extractionState" : "stale", "localizations" : { "en" : { "stringUnit" : { "state" : "translated", "value" : "%#@VARIABLE@" }, "substitutions" : { "VARIABLE" : { "formatSpecifier" : "lld", "variations" : { "plural" : { "one" : { "stringUnit" : { "state" : "translated", "value" : "Trail (Catalog)" } }, "other" : { "stringUnit" : { "state" : "translated", "value" : "Trails (Catalog)" } } } } } } } } This works, which is nice. But I tried to reproduce the same result by having a %#@VARIABLE@ in my LocalizedStringResource defaultValue like this: TypeDisplayRepresentation( name: LocalizedStringResource( "Flower", defaultValue: "%#@VARIABLE@", table: "AppIntents" ), numericFormat: LocalizedStringResource( "\(placeholder: .int) flower", table: "AppIntents" ) ) But the String catalog doesn’t support that apparently, I can’t get a “substitution” object in my catalog, so I have to manually do it using the source code which is not ideal and painful. Is there a way to support this kind of substitution with no actual plural token in the string as we can see for the %#@VARIABLE@ for Trail? Thank you, Regards, Axel
Replies
1
Boosts
0
Views
550
Activity
Jun ’26
AppIntents: how to present a searchable modal picker for an entity relation in an automatic "Find" intent (from EnumerableEntityQuery or EntityPropertyQuery)
Hello, My (fictional) app has multiple app entities like a BookEntity and an AuthorEntity. There is a relationship between them: a book has an author. Because I implement the EntityPropertyQuery for the BookEntityQuery, it creates a “Find Book where...” intent. In this intent, I can filter the data by an author (AuthorEntity). But I can’t find a way to allow the user to select any author using the searchable modal usually presented to “choose” a parameter value from an intent for example. Right now, it shows: a menu with the suggestedEntities() authors if the AuthorEntityQuery implements this function. With no way to search even if the AuthorEntityQuery conforms to the EntityStringQuery. a menu with allEntities() authors if the AuthorEntityQuery conforms to EnumerableEntityQuery and does not implement the suggestedEntities(). With no way to search even if the AuthorEntityQuery conforms to the EntityStringQuery. nothing if suggestedEntities() is not implemented and allEntities() is also not implemented even if the AuthorEntityQuery conforms to the EntityStringQuery. So this means if I implement suggestedEntities(), my users have no way to choose any author not in the suggestions. It’s too limited. if I implement allEntities() but not suggestedEntities(), this could potentially be a lot of entities and it’s not always relevant because then the Shortcuts app with an AuthorEntity parameter will be created for allEntities(), and the UI with always show the full list of allEntities() when I have to pick an author (unless I build a specific DynamicOptionsProvider but this would mean I lose the suggestedEntities() for example. if I just conforms to EntityStringQuery, I can’t select any item at all for this filter (no menu to choose). You can check the attached sample code provided. I checked a bit other apps, for example the Photos app allows you to find a photo based on an album but it lists ALL the albums (which is a lot) with no way to search using string. I also check the Sofa app, it shows the list of SofaListEntity (which implements suggestedEntities() and conforms to EntityStringQuery and EntityQuery). It actually shows all the lists (confirmed by the developer) with no way to search. See attachements from the Sofa developer. Is there a way to support a search for a filter using a relationship conforming to the EntityStringQuery? Is there a way to specify a provider for a @Property of an entity like we can for a @Parameter? For example, I could provide a custom DynamicOptionsProvider for the @Property(title: “Author”) var author which would be independent from the AuthorEntityQuery used elsewhere (parameter intents + Shortcuts). Maybe you can suggest another way to implement this? Maybe I should not rely on a relationship but instead flatten the relationship in the BookEntity to add an “authorName” or “authorID”? I filed this feedback with a sample code: FB23453134 Thanks, Regards, Axel
Replies
0
Boosts
1
Views
330
Activity
Jun ’26
DeleteIntent: the singular typeDisplayRepresentation of the AppEntity is used instead of the entities parameter title (plural)
Hello, I'm using a DeleteIntent in my app, but I can't get it to display "Delete {Books}" in the Shortcut apps. It always displays "Delete {Book}". It apparently uses the BookEntity typeDisplayRepresentation instead of using the intent entities parameter title ("Books") in the parameterSummary. For a "normal" AppIntent, the Shortcuts app uses the entities parameter title ("Books") in the parameterSummary. I filed a feedback: FB23451186 Regards, Axel
Replies
0
Boosts
0
Views
283
Activity
Jun ’26
CSSearchableItem init(appEntity:) crashes on iOS 18.0+
Hello, In my app, I want to create a CSSearchableItem using the initialiser that accepts an appEntity so I can update the item expirationDate when indexing. This initialiser is marked as iOS 18.0+ but as soon as I launch my app, it crashes. I filed a feedback: FB23270394 Can you help? Thank you Axel dyld[62169]: Symbol not found: _$s10AppIntents13IndexedEntityPAAE15hideInSpotlightSbvg Referenced from: <150E43FA-D9F4-3DF3-88C1-86E3DA3B272B> /Users/axel/Library/Developer/CoreSimulator/Devices/2C645A0F-45E5-429E-82EE-0C71D83407E3/data/Containers/Bundle/Application/18F00389-5CE8-49A2-883A-CDA38DDB03C4/Skipper.app/Skipper.debug.dylib Expected in: <F5744EDB-79CF-333C-A49A-8E9C5C3ACD10> /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AppIntents.framework/AppIntents Symbol not found: _$s10AppIntents13IndexedEntityPAAE15hideInSpotlightSbvg Referenced from: <150E43FA-D9F4-3DF3-88C1-86E3DA3B272B> /Users/axel/Library/Developer/CoreSimulator/Devices/2C645A0F-45E5-429E-82EE-0C71D83407E3/data/Containers/Bundle/Application/18F00389-5CE8-49A2-883A-CDA38DDB03C4/Skipper.app/Skipper.debug.dylib Expected in: <F5744EDB-79CF-333C-A49A-8E9C5C3ACD10> /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/AppIntents.framework/AppIntents dyld config: DYLD_ROOT_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot DYLD_LIBRARY_PATH=/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator DYLD_INSERT_LIBRARIES=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libLogRedirect.dylib:/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libMainThreadChecker.dylib:/usr/lib/libRPAC.dylib:/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libViewDebuggerSupport.dylib DYLD_FRAMEWORK_PATH=/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator:/Users/axel/Library/Developer/Xcode/DerivedData/Skipper-gayhthkwqznqqkeoqazrmncvolcq/Build/Products/Debug-iphonesimulator/PackageFrameworks DYLD_FALLBACK_FRAMEWORK_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks DYLD_FALLBACK_LIBRARY_PATH=/Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib Debug session ended with code 9: killed
Replies
1
Boosts
0
Views
417
Activity
Jun ’26
Spotlight: searching with Spotlight on iOS 17+ only works for the title or displayName, not any other indexed attribute from the CSSearchableItem.
Hello, I’m indexing content in my app using Core Spotlight. On iOS, I notice that I can only search using the title or displayName even if I index more content in Spotlight using CSSearchableItem or IndexedEntity. On macOS, I can search for any content or attributes of the CSSearchableItem or IndexedEntity. See attached screenshots (the item id on iOS is 708 and the item id on macOS is 741). On both platforms, the content can be fetched using a CSSearchQuery. I filed a feedback with an attached project: FB23317556 Regards Axel
Replies
0
Boosts
2
Views
327
Activity
Jun ’26
macOS 27: indexing using CSSearchableItem does not work. But using an IntentEntity works.
Hello, I’m using Core Spotlight in my app. I notice that if I use CSSearchableIndex to index the content, it cannot be found in Spotlight on macOS 27. if I use instead an IndexedEntity (from the AppIntents framework), the content can be found on macOS 27. The content seems to correctly be saved because I can fetch the content using a CSSearchQuery in both cases. I filed a feedback with a project attached: FB23317414 Regards, Axel
Replies
0
Boosts
1
Views
352
Activity
Jun ’26
How to detect if a migration is required?
Hello, With Core Data, we can use the isConfiguration(withName:compatibleWithStoreMetadata:) method on an NSManagedObjectModel alongside metadata(for:) on NSPersistentStoreCoordinator to check if the on-disk store is up to date or not. Is this the way to do it too with SwiftData or do we have an easier way to check if the on-disk store will need to migrate? I want to inform my users in the UI when the app launches (or from widgets or app intents). Regards, Axel
Replies
0
Boosts
0
Views
969
Activity
Jun ’26
Working with visits and significant location changes following Core Location updates in iOS 17 and iOS 18
Hello, I'm working on an application that requires the use of significant location changes and visits, in addition to region monitoring and standard continuous location delivery (foreground and background). iOS 17 and iOS 18 introduced changes to how we can monitor distinct regions of interest (with CLMonitor) as well as receive location updates (with CLLocationUpdate). But I couldn't find any information regarding how to work with Significant location changes. Do we still need to create a location manager and call startMonitoringSignificantLocationChanges()? Where are the updates received in this case, in the locationManager(_:didUpdateLocations:) or in the liveUpdates async sequence? Visits. Same question here, for visit monitoring to work, do we still have to create a location manager then call startMonitoringVisits()? Where are the visits being notified? Still in locationManager(_:didVisit:) or in the liveUpdates asynchronous sequence? I just want to be sure I understand correctly how to use the updates, and if some features of Core Location still need to use a location manager and the delegate to receive the events. Maybe additional CLCondition will be added to cover both of these technologies as it seems highly related to monitoring conditions (significant location change, and visit). Thank you, Axel
Replies
1
Boosts
0
Views
774
Activity
Jun ’26
How to present a View above everything in SwiftUI?
Hello, I'm trying to present an app overlay (like an HUD) that should appear on top of everything (the app UI could be the root content view or a modal presented from the content view or a modal over a modal presented from the content view, etc.). If I use a ZStack for example, the issue is that the view is not visible if the ZStack is presenting a modal for example. In UIKit, I think we can use instantiate another UIWindow to show content above the top window of the app (what a native alert does if I'm not wrong). What would be the equivalent in SwiftUI? How could I create this? Thanks, Axel
Replies
2
Boosts
0
Views
273
Activity
Jun ’26
StoreKit 2: is there a way for an app to be informed in real time if an auto-renewable subscription is cancelled by the user?
Hello, In my iOS app, I have a customer center where the user can see some details about its current subscription. I display things like the billing period, the price, the introductory offer state, the renewal date if it's not cancelled or the expiration date if it's cancelled, etc. From this screen, the user can open the subscription management sheet. I want to detect if the user cancels the subscription from this sheet or from the App Store (when the app is running) so I can refresh the information displayed on my customer center. I checked the asynchronous sequences provided by StoreKit 2 like Transaction.updates or Product.SubscriptionInfo.Status.updates and tested with a Sandbox account on my physical device with the app debugged using Xcode. But I noticed these sequences don't emit when I cancel the subscription in Sandbox. Is this the expected behavior? Is there a way to observe in real time if a user cancels the subscription? I can still manually check when the sheet is dismissed but it's not ideal because I want to know even if the user cancel from outside of the app with the app running. Thank you, Axel
Replies
2
Boosts
1
Views
758
Activity
Feb ’26
Product.SubscriptionInfo subscriptionPeriod does not provide the same result between the Sandbox/App Store environment and the StoreKit Testing in Xcode for a "1 week" subscription. "1 week" vs "7 days"
Hello, I noticed the Product.SubscriptionInfo subscriptionPeriod (of type Product.SubscriptionPeriod) is different for the same product between StoreKit Testing in Xcode and the sandbox/App Store (production) environment. For a “1 week” auto-renewable subscription, we get the following: StoreKit Testing in Xcode: 1 week gives a subscriptionPeriod with value of 1 and a unit of Product.SubscriptionPeriod.Unit.week Sandbox/App Store: 1 week gives a subscriptionPeriod with value of 7 and a unit of Product.SubscriptionPeriod.Unit.day This created issues in my app because I used the localizedDescription of a Product.SubscriptionPeriod to display a text similar to “$4.99 per week”. This is what I obtain with the StoreKit Testing in Xcode, but in the Sandbox/App Store environment, it displays “$4.99 per day” (because the subscriptionPeriod is “7 Days” and the unit is then .day). Obviously, this is not what I wanted to display. Other periods like “1 month”, “2 months”, “3 months”, “6 months, and “1 year”, the period provided by both StoreKit Testing and Sandbox/App Store correspond to the period unit specified in App Store Connect. In addition, I want to report that for a weekly subscription/offer or a 2 weeks offer, Product.SubscriptionInfo.subscriptionPeriod or Product.SubscriptionOffer.period == .weekly or .everyTwoWeeks is always false. We observe the following: With Sandbox or App Store live production: 1 week, Product.SubscriptionInfo.subscriptionPeriod == .weekly is false (because it’s “7 days”) 1 week, Product.SubscriptionOffer.period == .weekly is false (because it’s “7 days”) 2 weeks (offer), Product.SubscriptionInfo.subscriptionPeriod == .everyTwoWeeks is false (because it’s “14 days”) 2 weeks (offer), Product.SubscriptionOffer.period == .everyTwoWeeks is false (because it’s “14 days”) But with an Xcode StoreKit configuration file: 1 week, Product.SubscriptionInfo.subscriptionPeriod == .weekly is true (because it’s “1 week”) 1 week, Product.SubscriptionOffer.period == .weekly is true (because it’s “1 week”) 2 weeks, Product.SubscriptionInfo.subscriptionPeriod == . everyTwoWeeks is true (because it’s “2 weeks”) 2 weeks, Product.SubscriptionOffer.period == . everyTwoWeeks is true (because it’s “2 weeks”) So in sandbox and production, .weekly and .everyTwoWeeks is never possible. If someone from Apple could check the feedback FB19605865 🙂 Thank you Regards, Axel, @alpennec Code: do { let productIDs: [String] = ["revenueSocks_weekly_trial"] let products: [StoreKit.Product] = try await Product.products (for: productIDs) let weeklySubscription: StoreKit.Product = products.first! let displayPrice: String = weeklySubscription.displayPrice // For a weekly subscription in App Store Connect // With an Xcode StoreKit configuration file: subscriptionPeriod unit is Week (week), value is 1 → "1 Week" // With the Sandbox + App Store: subscriptionPeriod unit is Day (.day), value is 7 → "7 Days" let unitString: String = weeklySubscription.subscription!.subscriptionPeriod.unit.localizedDescription print("\(displayPrice) per \(unitString.localizedLowercase)") // StoreKit configuration file → "$4.99 per week" // Sandbox + App Store → "$4.99 per day" } catch { print(error) }
Replies
0
Boosts
0
Views
186
Activity
Nov ’25