Post

Replies

Boosts

Views

Activity

MusicKit Custom Data Request
Hi, I am trying to use MusicDataRequest from MusicKit to get the user's library artists (https://api.music.apple.com/v1/me/library/artists). This works well, until I am trying to use pagination with it. The data returned by this endpoint contains a "next" property, which reads /v1/me/library/artists?offset=25. Replacing the URL as such resulting in https://api.music.apple.com/v1/me/library/artists?offset=25 no longer works, as the request returns an error: MusicDataRequest.Error( status: 400, code: 40008, title: "Invalid Path Value", detailText: "Unknown library resource type 'artists?offset=25'", ... ) It seems like the request cannot handle query parameters and considers them as part of the request's path. Is there any way to use query parameters with MusicDataRequest? Thanks for any response.
3
0
1.5k
Nov ’21
CLBeaconIdentityConstraint wildcards
Hi, I am trying to understand how the wildcarding works with CLBeaconIdentityConstraint. The documentation states the following: Constraints always specify a UUID value, but the major and minor values are optional. However, CLBeaconIdentityConstraint comes with the following initializers: init(uuid: UUID) init(uuid: UUID, major: CLBeaconMajorValue) init(uuid: UUID, major: CLBeaconMajorValue, minor: CLBeaconMinorValue) This tells me that you cannot specify a wildcard for both major and minor independently, but rather only for minor or for both major and minor. I do work with beacons that have a weird major mixed in with other data. The idea I want to achieve is to wildcard major, while still being able to supply a minor value. I don't always need this option, but sometimes I don't need/want to know the major but filter out some minor values. Since this class is coming from Objective-C, it works with NSNumber internally (and in Swift they are optional getters), however through the initialisers specified above, I cannot nil the major value. Even in Objective-C the initializers are not exposing the NSNumber object. Is there any approach that does not involve runtime ObjC "hacks" to nil the major NSNumber backing object? Does it make sense to try and nil the major while keeping the minor? Will Core Location still supply beacons just fine? Thanks
0
0
530
Oct ’21
Playing Songs and Albums with MusicKit (Bug?)
Hi, I am trying to use MusicKit for playing a song or an album. I am using the following code for it: Tested on iPhone 11 Pro, iOS 15.0.1 @MainActor private func play<I: PlayableMusicItem>(_ item: I) async throws { let systemPlayer = SystemMusicPlayer.shared if !systemPlayer.isPreparedToPlay { try await systemPlayer.prepareToPlay() } let queue = systemPlayer.queue try await queue.insert(item, position: .afterCurrentEntry) try await systemPlayer.play() } Before I was using the "oldschool" way using the MusicPlayer framework as follows: @MainActor private func playOldschool(identifier: String) { let systemPlayer = MPMusicPlayerController.systemMusicPlayer if !systemPlayer.isPreparedToPlay { systemPlayer.prepareToPlay() } systemPlayer.setQueue(with: [identifier]) systemPlayer.play() } Both have been tested under the same conditions (permissions, same MusicSubscription), however the one using MusicKit does not seem to work well as try await systemPlayer.prepareToPlay() fails. If I remove the prepareForPlay code, it fails on play() with the same message and error as prepareForPlay. The logs show this: [SDKPlayback] prepareToPlay failed [no target descriptor] Error Domain=MPMusicPlayerControllerErrorDomain Code=1 "(null)" I could not find anything for that error domain and code 1, however prepareToPlay fails even in playOldschool, if I use the async variant of the function. At the moment I am staying with playOldschool, because that actually plays music. I wonder if I should file a radar for this or if there is any additional requirement for MusicKit that I haven't fulfilled causing it to fail. Any help is appreciated!
2
0
1.4k
Oct ’21
Understanding .musicSubscriptionOffer view modifier
Hi, I am trying to implement the new view modifier to show a subscription view for AppleMusic. In the #wwdc-10294 (Meet MusicKit for Swift) talk, the use case is very clear and it makes sense. We have an album and if the user wants to play it without an active subscription, we show toggle the binding that makes the view appear. However, using a single boolean removes flexibility so I am trying to figure out the following: I have two buttons: "Play" and "Add", which will either play the album as in the talk or add it to the user library using the Apple MusicAPI. In both cases if there is no subscription, I'd like to show the offer. This means I will have two different MusicSubscriptionOffer.Options configuration, one where the messageIdentifier is .playMusic and the other one .addMusic. This also means that I need to use two viewModifiers .musicSubscriptionOffer resulting in two different bindings (otherwise I assume both view controllers will show when the binding changes?). Worst case is if I show a list of songs and want to have options for .playMusic and .addMusic for each song, then I need a dynamic amount of bindings for the view modifier. Would I need to handle this like list bindings? Ideally I'd like an API that allows me to pass in an enum and provide options based on the enum cases like other SwiftUI API (like .sheet). This would allow for dynamic options and only requiring one single .musicSubscriptionOffer. Is there any solid solution for this at the moment? Any insights would be helpful, thanks!
1
0
687
Oct ’21
What happens if you apply a NSDiffableDataSourceSnapshot without animation?
Hi, My UICollectionViewCell has a subview UIImageView, which has a mask CALayer that I control and that I add animations to. Recently, I noticed that the animation wasn't working and I was wondering why. I finally figured out that it depends on whether I apply my NSDIffableDataSourceSnapshot animated or not. The animation would only work as expected, if the snapshot is applied animated. This raised a question: What happens if the snapshot is applied without animation? And why is it affecting CABasicAnimation on a CALayer? I haven't found a solution for it yet, so I wanted to ask here in case anybody knows what's up. imageView.layer.mask = animationLayer animationLayer.removeAllAnimations() let animation = CABasicAnimation(keyPath: "locations") /// ... animationLayer.add(animation, forKey: "shimmer") This code runs when the cell is gathered from the collection view for an index path. dataSource.apply(snapshot, animatingDifferences: false) Is there any way to apply a snapshot without animation while keeping animations within the cell working correctly? Thanks
0
0
710
Jul ’21
MusicKit additional properties for Songs and Albums
Hi, I know MusicKit is in beta, but after having talked to an engineer at a WWDC lab, it seems to be feature complete for now. I really enjoy the framework and it helps wrap the Apple Music API nicely. However, the types it provides are missing some properties that are relevant to any music item (song, album, music video) such as the releaseDate, contentRating, durationInMillis and url. This is the JSON response from a /tracks relationship of an album: "previews": [ { "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/e6/84/62/e6846266-2779-4527-902b-0a3b6f73be75/mzaf_18277320986443617976.plus.aac.p.m4a" } ], "artwork": { "width": 3000, "height": 3000, "url": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/c4/7a/01/c47a01c2-2b04-a327-12bd-c726ae076c7f/886447823545.jpg/{w}x{h}bb.jpeg", "bgColor": "1c1c1c", "textColor1": "fafafa", "textColor2": "e1e1e1", "textColor3": "cdcdcd", "textColor4": "b9b9b9" }, "artistName": "Kollegah", "url": "https://music.apple.com/de/album/alpha/1477896577?i=1477896820", "discNumber": 1, "genreNames": [ "Hip-Hop/Rap", "Musik" ], "durationInMillis": 141827, "releaseDate": "2014-05-09", "name": "Alpha", "isrc": "DEDG61400001", "hasLyrics": true, "albumName": "King", "playParams": { "id": "1477896820", "kind": "song" }, "trackNumber": 1, "composerName": "Kai Engelmann, Phillip Herwig, Alexis Papadimitriou, Daniel Coros, Yunus Cimen & Sadik Kalyon", "contentRating": "explicit" } As you can see, the releaseDate, durationInMillis, url, contentRating, etc. are missing from the struct Song : MusicItem in the MusicKit. I was wondering if we can extend MusicKit as developers in a way to include the releaseDate and other types or are we making a choice between using custom models and custom requests vs. using MusicKit? Thanks
2
0
1.2k
Jun ’21
Combining Actors with blazing fast lists
Hi, I really enjoyed both sessions as they helped me improve loading images in a collection view. I am currently experimenting with both codes and I'd like to combine them. As far as I understand from the "Make blazing fast lists and collection views" session there are key considerations: In the cell registration get the current asset for your model If it is a placeholder, download the asset and afterwards reconfigure the cell. This is due to cells potentially being reused already. If it is not a placeholder, we can just assign it to the cell's image view From the other talk about "protecting mutable state with Swift actors", I found out about protecting the image cache by using actors and that one should be aware of changed state after re-entry from an await. Now I am trying to combine the two talks, which is a bit difficult if I want to make sure that I use it correctly, so here are my ideas: I want an ImageLoader actor, that protects its cache state By using an actor, both reading from the cache and storing the cache become async operations (since if the cache is currently used, we need to "await" our turn to read from it) By doing this, in our cell registration, we can no longer fetch the asset synchronously and check if it is a placeholder or not. This means that even if we already have a cached image, the re-entry might be later and the cell might already be reused and therefore we can't just set the imageView image. Moreover we cannot call reconfigure of the cell registration (via the data source snapshot) anymore, since this would put us in an infinite loop. Additionally, preparing the image before displaying it also is an async operation. And since those images are larger in memory, I'd want to avoid caching images - I'd rather prepare them in the cell registration handler, which would make it async as well. Here is my code: cell.artworkView.image = UIImage(named: "DefaultArtwork") async { let asset: AlbumAsset = await self.assetStore.asset(forURL: artworkURL) switch asset { case .placeholder: await self.assetStore.downloadAsset(forURL: artworkURL) self.reconfigureAlbum(albumID) case .image(let image): let thumbnailImage = await image.byPreparingThumbnail(ofSize: .init(width: 100, height: 100)) DispatchQueue.main.async { cell.artworkView.image = thumbnailImage // Problem } } } Any help is appreciated as to how I can improve the situation so I can use actors, while still following the rules for updating a cell. I'd need something like a synchronous way of getting images, while having an asynchronous way of downloading and preparing images, and maintaining mutable state (cache). Thanks for any help.
1
0
1.1k
Jun ’21
Localization in Xcode
Hi, I‘m excited for the new localization features in Xcode 13. I learned something new about how it is expected to use Localization Strings. Before watching the videos I‘d always use a unique key for localizations, such as "navigationbar_leadingButtons_back" = "Back" and used them in my code, which made it a bit tricky to read them, instead of how it is shown in this WWDC by just using the english text "Back" and use "Back" as a key. However, if I have a longer sentence, let‘s suppose a description of a feature that has several lines. "This feature provides the ability to do xyz" If this is used as a Localization Key, then changing the text (because of changes of the feature or another reason) creates a new key, which breaks most of the translations that have already been done, since the key is gone right? If I export Localizations again now, then already translated strings for the old key are dropped, aren‘t they? I wonder why it is not advised to use developer friendly keys, that don‘t change and only change the text if needed? Additionally neither strings, nor developer-friendly strings as keys support compile time existence checks as far as I understand. Of course there are fallbacks to other languages, but it doesn‘t tell you unless you try out the app in that language. That‘s why I‘m still using developer-friendly keys with underscores in order to generate Swift Code from them to be used in my app, which gives some compile time check opportunities, as you can‘t access the localization if there is no key for it. How would the problem of renaming a key, by changing text in your app be handled in Xcode‘s Localization generator? And what are good reasons besides legibility for developers only for using complete texts as keys? E.g Compare: "This purchase gives you (fuelCount) fuel for your car" to Localization.Store.Products.Fuel.purchaseText.text(with: "\(fuelCount)") And this code represents "store_products_fuel_purchaseText" = "This purchase gives you {0} fuel for your car"; The key would never need to change, if we want to change the text as it is not the same key. Thanks for any info in advance :)
3
0
3.9k
Jun ’21