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 & Capabilities tab on Xcode. But, when I go to the Apple Developer portal under Certificates, Identifiers & 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?
Post not yet marked as solved
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?
Post not yet marked as solved
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?
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.
Post not yet marked as solved
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.
Post not yet marked as solved
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?
Post not yet marked as solved
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?
Post not yet marked as solved
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?
Post not yet marked as solved
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?
Post not yet marked as solved
I have a screen with two List side by side, inside a NavigationView. The layout is rendered correctly, and I can independently scroll both lists. The problem is that, when I scroll the first list, it goes behind the navigation bar without triggering the effect of applying a background color to it. Here's a gif showing what's going on:
And this is the code I'm using for this view:
struct ContentView: View {
var body: some View {
NavigationView {
HStack(spacing: 0) {
List {
Section(header: Text("Header left")) {
ForEach(0..<600) { integer in
Text("\(integer)")
}
}
}
.listStyle(InsetGroupedListStyle())
.frame(minWidth: 0, maxWidth: .infinity)
List {
Section(header: Text("Header right")) {
ForEach(0..<400) { integer in
Text("\(integer)")
}
}
}
.listStyle(InsetGroupedListStyle())
.frame(minWidth: 0, maxWidth: .infinity)
}
.navigationTitle("Example")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Would this be a SwiftUI bug? If not, how can I make the first list correctly interact with the navigation bar when scrolling?
Post not yet marked as solved
WWDC21 Session Focus on iPad keyboard navigation says that we can use UIFocusHaloEffect to change the appearance of focused items.
On iPadOS, we can use this effect by assigning a UIFocusHaloEffect to the focusEffect property like so:
self.focusEffect = UIFocusHaloEffect()
What wasn't very clear is where should we put this code when working with UICollectionViewCell. I am doing it in the collectionView(_:canFocusItemAt:) method:
func collectionView(_ collectionView: UICollectionView, canFocusItemAt indexPath: IndexPath) -> Bool {
guard #available(iOS 15.0, *) else { return false }
guard let cell = collectionView.cellForItem(at: indexPath) as? FeedCollectionViewCell else { return false }
if cell.focusEffect == nil {
cell.focusEffect = UIFocusHaloEffect(roundedRect: cell.artworkImageView.frame,
cornerRadius: cell.cornerRadius,
curve: .continuous)
}
return true
}
Is this the best way to implement it?
Post not yet marked as solved
Before beta 4 this worked as expected. After updating to beta 4, all my UICommands inside UIMenu on NSMenuToolbarItem.itemMenu are now disabled, and I can't figure out how to enable them.
Here's my itemForItemIdentifier method:
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
		let item = NSMenuToolbarItem(itemIdentifier: itemIdentifier)
		item.itemMenu = UIMenu(title: "", options: .displayInline, children: [UICommand(title: "Test", action: #selector(onTestTap))])
		item.image = UIImage(systemName: "ellipsis.circle")
		return item
}
Am I doing something wrong or is this a bug on macOS Big Sur beta 4?
Post not yet marked as solved
On a Catalyst app, the CLLocationManagerDelegate method didUpdateLocations is never called.
I have requested permission using requestLocation.
After granting it, the locationManagerDidChangeAuthorization method is called, with a positive authorizationStatus.
There I call requestLocation on the CLLocationManager object, but neither didUpdateLocations nor didFailWithError delegate methods are called.
The same code works as expected on iOS.
Post not yet marked as solved
If the app starts on regular mode, changes to compact, and then changes back to regular, everything works fine. The problem happens when the app starts on compact mode. When trying to switch to regular, the following exception happens and the app crashes:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unexpected view controller change in Secondary column for expanding <UISplitViewController: 0x10550a630>'
I have a sample project on Github - https://github.com/marcosatanaka/sidebar-ios14 that we can use to simulate this. Just follow the steps to reproduce:
Launch the app
Open another app on the side in a way that the first app changes to compact mode
Relaunch the app
Slide the second app off the screen so that the first changes to regular mode
Is this a bug on the API, or I'm using it incorrectly? Thanks.
Post not yet marked as solved
I know we need two authorizations in order to access the user's playlists:#1 - Privacy: Asks the user for permission to access the music library on the device.We ask for it using SKCloudServiceController.requestAuthorization(_:)#2 - Music User Token: Returns a user token that you use to access personalized Apple Music content.We ask for it using SKCloudServiceController().requestUserToken(forDeveloperToken:completionHandler:)According to the Introducing MusicKit session from WWDC 2017:"because fetching the music user token is a somewhat expensive operation, we recommend you cache the music user token once you've fetched it"and"Since you'll be caching this music user token, you should also be aware of when you should invalidate this cache and fetch the music user token again, and this is typically whenever you get a forbidden status code from any of the Apple Music API endpoints; that is the (403) HTTP status code."That's exactly what I'm doing on my app. If the request to get the user's playlists (GET https://api.music.apple.com/v1/me/library/playlists) returns 403, I clear #2 and ask for it again (after checking if #1 is still authorized).But when I do that, I get the following log on my console, and the app crashes:[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
[] nw_connection_receive_internal_block_invoke [C1] Receive reply failed with error "Operation canceled"
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
SSAccountStore: Unable to get the local account. error = Error Domain=SSErrorDomain Code=100 "Não pôde conectar com a iTunes Store" UserInfo={NSLocalizedDescription=Não pôde conectar com a iTunes Store}
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=9 "(null)""
SSAccountStore: Failed to fetch the backing accounts. error = Error Domain=com.apple.accounts Code=9 "(null)"
SSAccountStore: Unable to get the local account. error = Error Domain=SSErrorDomain Code=100 "Não pôde conectar com a iTunes Store" UserInfo={NSLocalizedDescription=Não pôde conectar com a iTunes Store}
Message from debugger: Terminated due to signal 9When that happens, for some reason the authorization #1 is revoked (which we can see by going on to Settings > Privacy > Media & Apple Music). And then I can only obtain authorization #2 after granting #1 and asking for #2 after that.Am I doing something wrong with this process? Why fetching the music user token results in an error and an application crash?I'm on iOS 13 beta 6.