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.
Post
Replies
Boosts
Views
Activity
TL;DROn iOS 13 and Xcode 11, how can I configure an Intent to run in the background and just return the result, so it can be used as the input for other actions in the Shortcuts app?Details of what I'm trying to achieveMy app has a list of songs that I want to expose via Shortcuts (actually, metadata about the song, not the song itself). The idea is to give advanced users a way to integrate this database of music with other apps or actions they want. For example, one may find useful to get a list of upcoming music for the next month, and use it to create Calendar events for each song. Having access to this list on the Shortcuts app can enable them to do this.I have created an Intent called "List All Unread Music Releases" and defined its response as a list of objects that contains information about each song. The problem is, when I go to the Shortcuts app, create a new shortcut using this Intent, and run it, it opens my app instead of running in the background.Steps I've done to create and configure IntentsHere's a high level definition of what I did to configure Intents in the project. The next section will have the actual source code and screenshots.Created a new SiriKit Intent Definition File.Created a new Intent.
Defined it's Title, Description, Parameters, and disabled the "Intent is eligible for Siri Suggestions" checkbox.Defined the response property as an Array (because it's going to be a list of songs), and configured the Output to be this array property.Created a new Intents Extension, with the checkbox "Include UI Extension" disabled. The idea here is to process the user request in the background and return a list with the results - no UI required.In the Intents Extension target, defined the IntentsSupported array inside Info.plist with the name of the intent created in step 2.Made the IntentHandler class implement the protocol generated for the intent created in step 2.Code samples and screenshotsMy SiriKit Intent Definition File and the GetUnreadReleases Intent:https://i.stack.imgur.com/es0PD.pngThe GetUnreadReleases Intent response:https://i.stack.imgur.com/lLSCU.pngThe Intents Extension IntentHandler class:import Intents
class IntentHandler: INExtension, GetUnreadReleasesIntentHandling {
func handle(intent: GetUnreadReleasesIntent, completion: @escaping (GetUnreadReleasesIntentResponse) -> Void) {
let response = GetUnreadReleasesIntentResponse(code: .success, userActivity: nil)
let release1 = IntentRelease(identifier: "1", display: "***** 1")
release1.name = "Name test 1"
release1.artist = "Artist test 1"
response.releases = [release1]
completion(response)
}
func resolveMediaType(for intent: GetUnreadReleasesIntent, with completion: @escaping (IntentMediaTypeResolutionResult) -> Void) {
if intent.mediaType == .unknown {
completion(.needsValue())
} else {
completion(.success(with: intent.mediaType))
}
}
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}The Intents Extension Info.plist file:https://i.stack.imgur.com/O84u4.pngConclusionSo, I would like this intent to run in the background, assemble the list of songs based on the user defined parameters, and return this list to be used as an input to other actions in the Shortcuts app.It looks like previous versions of the Intents editor (Xcode < 11 / iOS < 13.0) had a checkbox "Supports background execution" that did just that, but I can't find it anymore on Xcode 11.
I'm using the new double column UISplitViewController and a UICollectionView with the new .sidebar appearance as the primary view controller.
To understand how this new API works, I created a sample project and hosted it on Github - https://github.com/marcosatanaka/sidebar-ios14, so you can download and run it to reproduce the problem I'm facing. It was based on the sample code from Implementing Modern Collection Views - https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/implementing_modern_collection_views, specifically, on the OutlineViewController class of the project.
Everything is working fine, the primary and secondary views are shown and I can switch between the views on the sidebar by tapping on them. The problem happens when I open a second app with Split View and adjust the size of the second app by dragging the app divider, so my app stays on the Regular mode, and the second app on Compact mode.
This somehow breaks the layout of the sidebar (and no errors are printed out to the console). Here's a screenshot - https://github.com/marcosatanaka/sidebar-ios14/blob/master/Screenshots/1.jpeg that shows what happens.
If I restart the app, turn the iPad to portrait mode (which changes the layout to Compact), and then turn it to landscape (which changes the layout back to Regular), this is what happens - https://github.com/marcosatanaka/sidebar-ios14/blob/master/Screenshots/2.jpeg to the sidebar. And also, the following auto layout error is printed on the console:
Console - https://developer.apple.com/forums/content/attachment/e1949dd2-6943-40e4-8336-cea33aab26ba
I noticed that if I do not specify a .flexibleWidth for the autoresizingMask of the collection view, this problem stops. But then the style of the selected items on the sidebar no longer works as expected, as we can see on this screenshot - https://github.com/marcosatanaka/sidebar-ios14/blob/master/Screenshots/3.jpeg.
So, is this a bug with the new .sidebar appearance of the collection view, or did I do something wrong when configuring my views?
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.
I'm testing the new UISwitch.Style to use a native checkbox when running a Catalyst app on macOS.
When the UISwitch is on a view by itself, the conversion from switch to checkbox works fine. But if the checkbox is inside the accessoryView of a UITableViewCell, the conversion doesn't work, neither the checkbox or the switch are rendered.
I created a small sample project to demonstrate what's happening: https://github.com/marcosatanaka/catalyst-switch-test
Is this a Catalyst bug or we should configure switches differently when they're inside table view cells?
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?
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?
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?
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?
This happened before iOS 14, but much less frequently. Since the release of iOS 14, many users have reported to me that songs they add to a playlist through my app take a long time to appear (and sometimes never appear). The web service responds 204 No Content as expected, - https://developer.apple.com/documentation/applemusicapi/libraryplaylistrequesttrack so I'm suspecting that there may be a bug in the backend that handles this service, or in the Music client apps that are not syncing the latest changes to playlists.
I managed to reproduce this here too. All I had to to was to call this endpoint a few times with different tracks and open the Music app to check it out. The tracks sometimes appear as expected. But sometimes they appear on my Mac and don't appear on my iPhone. Sometimes they appear on the iPhone, but not on the iPad. And I even saw one time they appearing on the client apps, but not in the web interface (music.apple.com).
My question is: do I need to do something different on my end after calling this endpoint, or this is a problem with the backend service and/or client applications?
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.
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?
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?
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.
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?