I am having trouble accessing the lastPlayedData for any given album or track using MusicKit. The value is always nil, both on numerous albums and tracks I tested.
Afaik this is not a property that has to be fetched separately like tracks for example.
I am running this on my physical iPhone 12 18.1.1 with Xcode 16.1. The albums and tracks have definitely been played multiple times before. The app has permission to the library using MusicAuthorization.request()
This post mentions the same problem but offers no solution.
Thanks for any help
Post
Replies
Boosts
Views
Activity
Can I use the TestFight app icon to link to my app inside TestFlight?
All I found is this forum post that does not give a precise answer.
Should I contact https://www.apple.com/legal/contact/trademark-information.html for that matter?
Thank you
I use Universal Product Codes (UPC) in my app to reliably identify albums after having used albumIDs for a time. AlbumIDs can change over time for no obvious reasons (see here for songIDs) so I switched to UPCs since I believed they cannot change. Well apparently they can.
A few days ago I populated a JSON with UPCs including 196871067713. Today trying to perform a MusicCatalogResourchRequest for the UPC does not return anything. When using that UPC and putting it into an Apple Music link like https://music.apple.com/de/album/folge-89-im-geistergarten/1683337782?l=en-GB redirects to https://music.apple.com/de/album/folge-89-im-geistergarten/1683337782?l=en-GB so I assume the UPC has changed from 196871067713 to 1683337782.
Apple Music can handle that and redirects to the new upc both in the app and as a website.
But a MusicCatalogResourceRequest cannot do that. I filed a suggestion for that (FB15167146) but I need a solution quicker. Can I somehow detect where the URL is redirecting to? Is there a way MusicCatalogResourceRequest can do this? Performing a MusicCatalogSearchRequest can be an option but seems unreliable when using the title as search term. Other ideas?
Thank you
I want to switch from using print statements to using OSLog because of the filtering options and so on. I am using MusicKit. To mute all the log noise mostly coming from CoreData I pass these arguments on launch:
-com.apple.CoreData.SQLDebug 0
-com.apple.CoreData.MigrationDebug 0
-com.apple.CoreData.ConcurrencyDebug 0
-com.apple.CoreData.CloudKitDebug 0
-com.apple.CoreData.Logging.stderr 0
This works for all the Core Data related warnings but I also need such an argument for MusicKit. Setting the environment variable OS_ACTIVITY_MODE to disable hides all the noise but also hides the log statements I sent via Logger().debug() for example.
In particular these log messages appear in great quantities.
Attempted to register account monitor for types client is not authorized to access: {(
"com.apple.account.iTunesStore"
)}
<ICMonitoredAccountStore: 0x303c5c9f0> Failed to register for account monitoring. err=Error Domain=com.apple.accounts Code=7 "(null)"
My application works fine and these log messages mean absolutely nothing to me. These two threads mention a similar problem but can't offer a solution.
https://forums.developer.apple.com/forums/thread/720835
https://forums.developer.apple.com/forums/thread/743795
Thank you
When changing a property of a SwiftData Model from a ModelActor the memory needed slightly increases. Once you do that more often, you can see that the usage is linearly increasing. I modified the Swiftdata template as little as possible. This is the least code I need to reproduce the problem:
Changes In the @main struct :
ContentView(modelContainer: sharedModelContainer)
ContentView:
struct ContentView: View {
@Query private var items: [Item]
let dataHanndler: DataHandler
@State var timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false, block: { t in })
var body: some View {
NavigationSplitView {
List {
ForEach(items) { item in
NavigationLink {
Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
} label: {
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
ToolbarItem {
Button {
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { t in
Task {
await dataHanndler.updateRandom()
// Obviously this makes little sense but I need to update a lot of entities in my actual app. This is the simplest way to demonstrate that. updateRandom() could also be a function of a view but that doesn't make a difference
}
}
} label: {
Label("Do a lot of writing", systemImage: "gauge.with.dots.needle.100percent")
}
}
ToolbarItem {
Button {
timer.invalidate()
} label: {
Label("Invalidate", systemImage: "stop.circle")
}
}
}
} detail: {
Text("Select an item")
}
}
private func addItem() {
Task {
await dataHanndler.insert(timestamp: Date.now)
}
}
init(modelContainer: ModelContainer) {
self.dataHanndler = DataHandler(modelContainer: modelContainer)
}
}
ModelActor:
@ModelActor
actor DataHandler {
public func update<T>(_ persistentIdentifier: PersistentIdentifier, keypath: ReferenceWritableKeyPath<Item, T>, to value: T) throws {
let model = modelContext.model(for: persistentIdentifier) as! Item
model[keyPath: keypath] = value
}
public func insert(timestamp: Date) {
let item = Item(timestamp: timestamp)
modelContext.insert(item)
}
public func updateRandom() {
let count = try! modelContext.fetchCount(FetchDescriptor<Item>())
var descriptor = FetchDescriptor<Item>()
descriptor.fetchOffset = Int.random(in: 0..<count)
descriptor.fetchLimit = 1
let model = try! modelContext.fetch(descriptor)
model.first!.timestamp = Date.now
}
}
I filed a bug report FB14876920 but I am looking for other ideas to solve this before it will be fixed in a future update. The modelContext I use is created and managed by the @ModelActor macro.
Happy to hear ideas
Apparently the @Query property wrapper from SwiftData does not update when data is loaded from CloudKit. The data can be programmatically be accessed but nothing appears in the view.
Steps to reproduce:
Create new Xcode project using the SwiftData storage option.
Provide a default value for the Item Model. That is required so data can be automatically synced by SwiftData.
Enable iCloud -> CloudKit capabilities and choose a container
Enable Background Modes -> Remote notification capability
Add a toolbar button that prints the number of items from @Query like this:
ToolbarItem {
Button {
print(items.count)
} label: {
Label("Count", systemImage: "1.circle")
}
}
Install app on a physical device that can sync to iCloud.
Add some items using the + in the toolbar
Delete app and wait for around a minute
Reinstall app with a debugger attached
Press the 1.circle button in the toolbar. It will print either 0 or the number of items you previously added. When it does not print 0 the data should be visible but it is not. Once you quit and relaunch the app or press the + button again, all of the items appear.
Has anyone else experienced this before? Anything I can do so the data appears / the view reloads once the items are available? I need to update my view once the data has been loaded from iCloud.
I already filed a bug report with id FB14619787.
I'm currently in the process of migrating to Swift 6. A lot of my code triggers the warning from the title. Passing argument of non-sendable type 'ContentView' outside of main actor-isolated context may introduce data races. I depend on the .task/.refreshable modifiers and buttons that trigger asynchronous work that cannot be done on the Main Actor since it takes way to long.
The below code demonstrates the problem. Some comments explain my problems further. I read a lot of articles and documentations but couldn't find an answer to such a seemingly simple error
struct ContentView: View { // Marking Senable as suggested by the warning causes different warning for @State
@State private var authorizationStatus: MusicAuthorization.Status = .notDetermined // Sole purpose to trigger the errors
var body: some View {
VStack {
Text("Hello, world!")
Button("Some button") {
Task {
await doingSomeAsyncWork()
// WARNING: Passing argument of non-sendable type 'ContentView' outside of main actor-isolated context may introduce data races
}
}
}
.task { // Or refreshable I believe both behave the same
await doingSomeAsyncWork()
// WARNING: Passing argument of non-sendable type 'ContentView' outside of main actor-isolated context may introduce data races
}
}
// Marking @MainActor is not an option since some of these functions might be running for more than 10 seconds
// Tried marking func as nonisolated but that obviously had no effect
func doingSomeAsyncWork() async {
authorizationStatus = await MusicAuthorization.request() // Just to have a easy asynchronous function. Without some async code in here, the errors disappear
}
}
Thank you
Using the hardware volume buttons on the iPhone, you have 16 steps you can adjust your volume to. I want to implement a volume control slider in my app. I am updating the value of the slider using AVAudioSession.sharedInstance().outputVolume. The problem is that this returns values rounded to the nearest 0 or 5. This makes the slider jump around. .formatted() is not causing this problem.
You can recreate the problem using code below.
@main
struct VolumeTestApp: App {
init() {
try? AVAudioSession.sharedInstance().setActive(true)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var volume = Double()
@State private var difference = Double()
var body: some View {
VStack {
Text("The volume changed by \(difference.formatted())")
Slider(value: $volume, in: 0...1)
}
.onReceive(AVAudioSession.sharedInstance().publisher(for: \.outputVolume), perform: { value in
volume = Double(value)
})
.onChange(of: volume) { oldValue, newValue in // Only used to make the problem more obvious
if oldValue > newValue {
difference = oldValue - newValue
} else {
difference = newValue - oldValue
}
}
}
}
Here is a video of the problem in action:
https://share.icloud.com/photos/00fmp7Vq1AkRetxcIP5EXeAZA
What am I doing wrong or what can I do to avoid this?
Thank you
I built an app that makes playing audio plays easier using MusicKit. Now I am about to release the app to the app store. Following questions occured while doing so:
Am I accessing/showing third party content in my app when I am music (in this case radio plays) from MusicKit? I am getting all of that data directly from Apple. Is Apple a third party in this case?
The publisher has an app that can playback all of the content that can be accessed in my app. This app has an age rating of 4+ years. Can I just copy that? I've heard that referring to other apps doesn't convince the App Review Team if they disagree. None of the titles are marked explicit in Apple Music.
Under the hood MusicKit is using HTTPS to get the data from Apple's servers. I have no code that has anything to do with encryption or HTTPS. Does my app still uses Non Exempt Encryption because MusicKit does so?
Can I access music through MusicKit that is otherwise not available in this region or does MusicKit take care of this for me? In other words do I have to restrict the availability of my app to certain regions so I don't bypass any geo blockings by accident?
Thank you
For a kind of podcast player I need to periodically update a swiftData object to keep track of the listening progress. (Happy to hear if there are better ways) I need to do this in many places in my app so I wanted to extract the modelContext into a Singleton so I can write a global function that starts the timer.
In doing so I stumbled upon a problem: The memory used by my app is steadily increasing and the device is turning hot.
@Observable
class Helper {
static let shared = Helper()
var modelContext: ModelContext?
}
@main
struct SingletontestApp: App {
let modelContainer: ModelContainer
init() {
do {
modelContainer = try ModelContainer(
for: Item.self, Item.self
)
} catch {
fatalError("Could not initialize ModelContainer")
}
Helper.shared.modelContext = modelContainer.mainContext
}
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(modelContainer)
}
}
struct ContentView: View {
@Query private var items: [Item]
var body: some View {
NavigationSplitView {
List {
ForEach(items) { item in
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
}
}
.toolbar {
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
ToolbarItem {
Button(action: updateItemPeriodically) {
Label("Change random", systemImage: "dice")
}
}
}
} detail: {
Text("Select an item")
}
}
func addItem() {
withAnimation {
let newItem = Item(timestamp: Date())
Helper.shared.modelContext!.insert(newItem)
}
}
@MainActor
func updateItemPeriodically() { // Doesn't matter if run as global or local func
let descriptor = FetchDescriptor<Item>(sortBy: [SortDescriptor(\.timestamp)])
let results = (try? Helper.shared.modelContext?.fetch(descriptor)) ?? []
let element = results.randomElement()
let timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { timer in // Smaller time intervals worsen the problem
element?.timestamp = Date.now
}
}
}
Calling save() manually or automatically in the timer does not have any effect. I am not sure about my general way of keeping track of listening process so if you think there is a better way, feel free to correct me.
Thanks for your help
I am trying to bring my iOS App to native macOS. I am using exactly the same TimelineProvider and widgets (the ones not supported on macOS surrounded by #if(os)). Running the whole app or just the WidgetExtension on iOS works perfectly fine. Running the mac app works perfectly fine apart from missing Widgets.
When running the WidgetExtension on My Mac, the WidgetKit Simulator opens and only presents Failed to load widget. The operation couldn't be completed. (WidgetKit_Simulator.WidgetDocument.Error error 4.) The code compiles fine without any warnings, only a file path is printed into the console. file:///Users/myName/Library/Developer/Xcode/DerivedData/MyAppName-dfsiuexplidieybwvbkqofchxirp/Build/Products/Debug/MyApp.app/Contents/PlugIns/MyAppNameWidgetExtensionExtension.appex/
Shortly after I get a log entry Logging Error: Failed to initialize logging system. Log messages may be missing. If this issue persists, try setting IDEPreferLogStreaming=YES in the active scheme actions environment variables.
I am not sure which further Informationen I can give to solve my problem. Destinations on main App and Widget Extension is both set to Mac (no suffix). The mac is running 14.4.1 and Xcode 15.3.
I am really thankful for any assistance you can give me to fix this problem. Thanks
Hi, is there a way to display the animated cover art in an app? Not every album has a cover art but for the ones that have one I would like to display them instead of the artwork.
Thank you :)
Hello everyone,
I followed this (https://www.hackingwithswift.com/quick-start/swiftdata/how-to-sync-swiftdata-with-icloud) guide from Paul Hudson on how to sync swiftdata with iCloud. I tried it on my device directly and it worked exactly as I would expect. Now I tried the same version of the app on another device installed through TestFlight external tester group. It no longer works.
When deleting the app, the alert reads "Deleting this app will also delete its data, but any documents or data will be stored in iCloud will not be deleted" so the app should have said something in iCloud. When looking in Settings -> Your Name -> iCloud -> Manage Account Storage, on the working device I can see around 300 KB saved in iCloud, on the other device my app is not listed. Both have a fast and working internet connection, almost fully charged, low data mode turned off, running 17.4.1, Background modes enabled, Mobile data enabled, more than enough unused iCloud storage and plenty of time to sync.
I was streaming the logs from the Cloudkit dashboard but nothing appeared there. The data saved neither syncs to another device of the same apple id nor reappears after app removal.
The model Container is initialized without any configuration, the only relationship is optional and every value has a default value. There is A LOT of log noise when launching the app and I am unable to get any meaningful information from that. I can only get the log from the device where it is working as expected.
I have triple checked that it is exactly the same app version and no debug conditions anywhere. I have absolutely no idea what is causing this.
Thanks for any help :)