Posts

Post not yet marked as solved
0 Replies
326 Views
My app uses Core Data to store user data. It doesn't have login or profile mechanisms, because user data is tied to the user's Apple ID and synced via iCloud using CloudKit. I've recently added the User Management capability, and checked Runs as Current User to allow each Apple TV user to have access to its own data. Everything works as expected: I press and hold the TV button to select a different user in Control Center; The system shows a switching user UI; And the app is relaunched using the new user's Apple ID and data from iCloud. The problem is that switching users apparently causes the local Core Data managed database to be reset, removing all data from the previous user. This is inconvenient because every time we switch users, the newly selected user has to wait for CloudKit to download all its data back into the app. And it takes a while, especially for users that have more than a few hundred items in the database. Ideally, tvOS should maintain the user data on-device, and only switch to a different database according to the active user. This way data would not need to be downloaded from scratch every time a user is switched. Is there a setting I can configure or a checkbox I can check to enable this behavior, or is this something not possible yet on tvOS?
Posted Last updated
.
Post not yet marked as solved
2 Replies
461 Views
After updating to iOS 17 and Xcode 15 I noticed that menus on my app get automatically dismissed while CloudKit is syncing data right after opening the app. I know it's CloudKit because this issue doesn't happen when I launch the app in Airplane Mode. It looks like CloudKit causes something to change (even when there are no data changes since the last usage), which causes the UI to refresh. This refresh causes the menus to be dismissed. This is frustrating because users have to tap a button two or three times before being able to interact with the menu showed by the button. I'm attaching a screen recording that shows the issue: https://youtube.com/shorts/Wl9gP2HLktE I open the app and tap the "+" icon, which shows the menu. The menu is quickly dismissed. I tap the "+" icon again, and the menu is shown for a millisecond, and is dismissed again. I tap the "+" button once again. This time the menu is shown and stays there because CloudKit has finished its initial sync process. Note that this didn't happened on iOS 16 / Xcode 14, so something must have changed to cause this issue. Is there something I need to update on my code to fix this issue, or is it a bug in the OS or frameworks that will be fixed in a future update?
Posted Last updated
.
Post marked as solved
2 Replies
1.9k Views
I have a macOS Share Extension invoked when users tap the Share button in Safari. I'm trying to get the page's URL from the -[NSExtensionItem attachments] attribute, but it comes as an NSSecureCoding object, and I'm unable to read the URL from it. In the loadView method, I'm filtering and loading the attachments of type public.url: override func loadView() { super.loadView() guard let inputItem = extensionContext?.inputItems.first as? NSExtensionItem else { print("Didn't received input item from action.") return } var itemProvider: NSItemProvider? itemProvider = inputItem.attachments?.filter({ $0.registeredTypeIdentifiers.contains("public.url") }).first ?? inputItem.attachments?.filter({ $0.registeredTypeIdentifiers.contains("public.plain-text") }).first guard let itemProvider = itemProvider else { print("Didn't received attachments from input item.") return } if itemProvider.canLoadObject(ofClass: URL.self) { itemProvider.loadItem(forTypeIdentifier: "public.url", completionHandler: onLoadVideoURL) } else if itemProvider.canLoadObject(ofClass: String.self) { itemProvider.loadItem(forTypeIdentifier: "public.plain-text", completionHandler: onLoadVideoURL) } else { print("This action only supports URL and String.") } } The itemProvider.loadItem method runs for the type identifier public.url, calling the completion handler bellow: @objc private func onLoadVideoURL(dict: NSSecureCoding?, error: Error?) { print("URL: \(dict.debugDescription)") // ... } But the content that it prints to the console is: URL: Optional(<68747470 733a2f2f 73746163 6b6f7665 72666c6f 772e636f 6d2f7175 65737469 6f6e732f 35323231 39373030 2f686f77 2d746f2d 63617374 2d6e7373 65637572 65636f64 696e672d 746f2d6d 6b6d6170 6974656d 2d696e2d 61637469 6f6e2d65 7874656e 73696f6e>) The same code works as expected on iOS, printing the shared URL to the console. Do I have to somehow convert this NSSecureCoding to URL or another object? Or should I do this in a completely different way on macOS? The goal is to access the page's URL from the Share Extension activated when the user selects it in the Share Menu.
Posted Last updated
.
Post not yet marked as solved
1 Replies
738 Views
My app allows users to store URLs for future reference. It also has widgets that display these saved items. I want to make these widgets interactive by opening the linked content in Safari without having to open the main app. The issue is that UIApplication.shared.open is not available in app extensions. And this is a problem since widgets are app extensions. Are there alternative methods to accomplish this scenario, or is it currently unsupported?
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.2k Views
In an AppIntent we can declare an IntentDescription with a categoryName to group similar intents: struct OpenArtist: AppIntent { static var description: IntentDescription = IntentDescription("Opens a specific artist.", categoryName: "artistsSection") // Additional properties } But how can we assign the same category to the "Find AppEntity" intent generated when we declare an EntityPropertyQuery? I want to group it along with the other intents that handle the same entity, but since it is generated by the system, I don't know how to assign a category to it.
Posted Last updated
.
Post not yet marked as solved
0 Replies
898 Views
My AppEntity has a Bool property, and I would like to query by this property using EntityPropertyQuery. I'm creating an EntityQueryProperty for it with an EqualToComparator as the following (partial code for brevity): // My AppEntity struct AlbumAppEntity: AppEntity, Identifiable { @Property(title: "Hidden") var isHidden: Bool // Other properties } // My EntityPropertyQuery static var properties = QueryProperties { Property(\AlbumAppEntity.$isHidden) { EqualToComparator { isHidden in if isHidden { return NSPredicate(format: "isHidden == YES") } else { return NSCompoundPredicate(type: .or, subpredicates: [NSPredicate(format: "isHidden = nil"), NSPredicate(format: "isHidden == NO")]) } } } } But the problem is that Shortcuts does not recognize it as a boolean parameter in the shortcuts editor. It recognizes it as a numeric field, which returns the error AppIntents.EntityPropertyQueryError error 2 when run: I also tried different NSPredicate, but the result is always the same: Property(\AlbumAppEntity.$isHidden) { EqualToComparator { NSPredicate(format: "isHidden == %d", $0) } } Property(\AlbumAppEntity.$isHidden) { EqualToComparator { NSPredicate(format: "isHidden == %@", NSNumber(value: $0)) } } How can I query using boolean properties in a way that Shortcuts recognizes it and provides appropriate fields in the shortcuts editor?
Posted Last updated
.
Post marked as solved
1 Replies
1.2k Views
TL;DR How to create an NSSortDescriptor using a PartialKeyPath instead of a KeyPath? Or How to convert a PartialKeyPath to a KeyPath? Details I'm using the new query properties from AppIntents to filter my app's data in Shortcuts, but I'm unable to map the sorting attribute it gives me to the sorting attribute Core Data expects in the predicate. Here's my EntityPropertyQuery implementation: extension ArtistQuery: EntityPropertyQuery { static var sortingOptions = SortingOptions { SortableBy(\ArtistEntity.$name) } static var properties = QueryProperties { Property(\ArtistEntity.$name) { EqualToComparator { NSPredicate(format: "name = %@", $0) } ContainsComparator { NSPredicate(format: "name CONTAINS %@", $0) } } } func entities(matching comparators: [NSPredicate], mode: ComparatorMode, sortedBy: [Sort<ArtistEntity>], limit: Int?) async throws -> [ArtistEntity] { Database.shared.findArtists(matching: comparators, matchAll: mode == .and, sorts: sortedBy.map { NSSortDescriptor(keyPath: $0.by, ascending: $0.order == .ascending) }) } } And my findArtists method is implemented as follows: static func findArtists(matching comparators: [NSPredicate], matchAll: Bool, sorts: [NSSortDescriptor]) -> [EArtist] { ... } As we can see in the entities(matching:) function, I'm using the by attribute from the sortedBy parameter to create the NSSortDescriptor, but it doesn't work because the NSSortDescriptor init expects a KeyPath, not a PartialKeyPath: Cannot convert value of type 'PartialKeyPath<ArtistEntity>' to expected argument type 'KeyPath<Root, Value>' So, can I create an NSSortDescriptor using a PartialKeyPath instead of a KeyPath? Or maybe converting a PartialKeyPath to a KeyPath?
Posted Last updated
.
Post marked as solved
5 Replies
11k Views
I'm trying to build my iOS app to macOS Catalyst. Everything works fine when running locally on my machine via Xcode, but an error occurs when I archive and try to upload to the notarisation service: Cannot create a Mac Catalyst Developer ID provisioning profile for "br.com.marcosatanaka.music-harbor". The App Groups capability is not available for Mac Catalyst Developer ID provisioning profiles. Disable this feature and try again. I have the App Groups capability enabled on my app's target Signing &amp; Capabilities tab on Xcode. But, when I go to the Apple Developer portal under Certificates, Identifiers &amp; Profiles > Profiles and select the Mac Catalyst provisioning profile (automatically generated by Xcode), the App Groups capability is not present on the Enabled Capabilities section. I can work around this issue by removing the com.apple.security.application-groups entitlement when building for Mac Catalyst, but that causes me a runtime error when Core Data tries to access the store located on the shared container. I also need it to be on a shared container because I want to access the database from both the main app and also the new widget extension. How can I add the App Groups capability to my Mac Catalyst provisioning profile?
Posted Last updated
.
Post not yet marked as solved
3 Replies
3.3k Views
Using SwiftUI's new Table container, how can I add a context menu that appears when Control-clicking a row? I can add the contextMenu modifier to the content of the TableColumn, but then I will have to add it to each individual column. And it only works above the specific text, not on the entire row: I tried adding the modifier to the TableColumn itself, but it shows a compile error: Value of type 'TableColumn<RowValue, Never, Text, Text>' has no member 'contextMenu' Here's what I have in terms of source code, with the contextMenu modifier in the content of the TableColumn: struct ContentView: View { @Environment(\.managedObjectContext) private var viewContext @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Item.name, ascending: true)]) private var items: FetchedResults<Item> @State private var sortOrder = [KeyPathComparator(\Item.name)] @State private var selection = Set<Item.ID>() var body: some View { NavigationView { Table(items, selection: $selection, sortOrder: $items.sortDescriptors) { TableColumn("Column 1") { Text("Item at \($0.name!)") .contextMenu { Button(action: {}) { Text("Action 1") } Divider() Button(action: {}) { Text("Action 2") } Button(action: {}) { Text("Action 3") } } } TableColumn("Column 2") { Text($0.id.debugDescription) } } .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } if selection.isEmpty { Text("Select an item") } else if selection.count == 1 { Text("Selected \(items.first(where: { $0.id == selection.first! })!.id.debugDescription)") } else { Text("Selected \(selection.count)") } } } } So, how can I add a context menu to the entire row inside the Table?
Posted Last updated
.
Post not yet marked as solved
0 Replies
1k Views
iPadOS uses a different selection color when an external keyboard is connected. But the problem is that it doesn't change the text color to white, making it difficult to read: A simple List with NavigationLink produces this behavior by default: var body: some View { List { ForEach(searchResults) { item in NavigationLink(destination: ContentDetailView(item: item)) { ListItemView(item: item) } } } } I tried to improve text legibility by changing all Text colors to white when the cell is selected. But this doesn't work because the text becomes even more unreadable when no external keyboard is connected. Is there a way to change the selection color when an external keyboard is connected? Or maybe detect when an external keyboard is connected to manually change the text color for this specific case?
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.7k Views
Using the Implementing a Store In Your App Using the StoreKit API sample code, I've successfully integrated my new APP with StoreKit 2. There is one problem though: when I call the method Transaction.latest(for:) to get the user’s latest transaction, it always returns nil. Here's the code snippet: guard let result = await Transaction.latest(for: myProductId) else { return false } Is this a bug with StoreKit 2, or am I doing something wrong? This happens on a physical device, running from Xcode. Thanks in advance.
Posted Last updated
.
Post not yet marked as solved
1 Replies
832 Views
I'm sharing a Core Data store with my action extension, which adds data to it. My app has a SwiftUI view that presents this data, fetched with a FetchRequest: private struct VideosScrollView: View { @Environment(\.managedObjectContext) private var viewContext private var fetchRequest: FetchRequest<Video> init(sortOrder: String, tagIds: String, showWatched: Bool) { fetchRequest = Video.getFetchRequest(sortingBy: "addDate", with: sortOrder, showWatched: showWatched, tagIds: tagIds) } var body: some View { ScrollView { if fetchRequest.wrappedValue.isEmpty { ContentEmptyView() } else { ForEach(fetchRequest.wrappedValue) { item in VideoCellView(video: item) } } } } } After adding data from the action extension and going back to the app, the view is not updated. Only after CloudKit finished a sync is that the view notices something changed and updates itself. How can I force my SwiftUI view to update when data changes in the action extension?
Posted Last updated
.
Post not yet marked as solved
0 Replies
658 Views
My app has an action extension that allow users to collect and save links throughout the system. It also has a widget to show these links in the Home Screen. When adding links from the main app, I call WidgetCenter.shared.reloadAllTimelines() to reload all widgets, and everything works as expected. But when I add links from the action extension, widgets are not reloaded, even after calling WidgetCenter.shared.reloadAllTimelines(). Only when I go to the main app is that widgets do reload. How can I refresh my widgets for changes made via the Action Extension from the share sheet?
Posted Last updated
.
Post not yet marked as solved
9 Replies
1.8k Views
On a macOS app generated with Catalyst, the method SKCloudServiceController.requestUserToken(forDeveloperToken:completionHandler:) returns a SKErrorDomain. The error is: Error Domain=SKErrorDomain Code=0 "Ocorreu um erro desconhecido" UserInfo={NSLocalizedDescription=Ocorreu um erro desconhecido} Has something changed regarding this method on macOS or is this a bug?
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.3k Views
I noticed that sometimes, when opening my Mac Catalyst app, the window is not resized to the size I left it the last time. Should I restore it manually when launching the app, or is the system responsible for it? And if it so, why it doesn't work sometimes?
Posted Last updated
.