Post

Replies

Boosts

Views

Activity

Reply to SwiftData regression in iOS 18 RC, contexts don't sync
Thank you for your reply. I can't explain why you saw the unit test pass. I see passes in the simulator in Xcode 16 RC using iOS 17.4 and 17.5. It fails for me only in iOS 18 RC on the simulator. The full demo project is attached to the FB linked above if that is helpful. If I can provide any other diagnostics please let me know. We developed the app in iOS 17.0 and these unit tests passed all year in all point releases of iOS 17. We were also all green for later iOS 18 betas prior to the RC. I can't say for certain that there is no other impact to our app from this bug. We saw a change in concurrency behavior in iOS 18 RC compared to the betas (and compared to iOS 17.X) which revealed a race condition in our code. We had reliably "won" the race prior to the RC, but reliably lost in the RC. We had to refactor a chunk of code to get that to work, and we may have also fixed any issues coming from the ModelContext behavior above at the same time. The only app impact that seems like I can point specifically at this bug is in a view that took a ModelObject as an argument, rather than running its own @Query. We have two models @Model Parent { var children: [Child] } @Model Child {} The view below would continue to show the ContentUnavailableView even after our background process had updated the parent instance, and it's content was visible on other screens which were populated successfully with @Query variable. MyView { let parent: Parent // <- passed as argument, not query var body { if let children = parent.children, children.isEmpty == false { trendsContent } else { ContentUnavailableView(...) } } } The issue you linked where Query vars do not update when ModelActors update is one we saw during all early betas of iOS 18 (and iOS 17.0 betas as well), but have not been impacted by in any released iOS version.
Sep ’24
Reply to SwiftData regression in iOS 18 RC, contexts don't sync
It turned out that we could get this fixed pretty quickly in our app, but there was more to fix in our unit tests. A pattern we had adopted in unit tests was testing async operations performed by our ModelActors: Create a ModelContext in a unit test. Create a ModelObject instance in that unit test Context Send that ModelObject to a ModelActor to get updated Back in the unit test, confirm that the ModelObject was updated. It's that step 4 that was broken by this change in iOS 18 RC.
Sep ’24
Reply to Managing Duplicate Objects in Core Data (or SwiftData) with CloudKit Sync When Devices were Offline during object creation
You will need to handle this yourself in your code to remove the duplicate record. You can search for Core Data “deduplication” in your favorite search engine. I posted this thread asking for advice for how to solve this in Swift Data but at the time it was not possible. With the new iOS 18 history processing it may be possible, but I haven’t looked into it yet. That session mentions identifying changes that originate in other processes like widgets, but does not explicitly mention Cloud-originated changes. If anyone has tried this I’d like to hear if it works to identify CloudKit changes. If you are using Core Data there are good tools to process data changes that originate on another device. Apple’s best article on the topic is here and it should give you all of the code you need to solve this for a Core Data application. The short version is that in your example scenario you will see that both records are created, and both records will be synced to CloudKit, and both records will be sent to both devices. You can set up rules that will process incoming data that originated from a CloudKit sync, and identify if they are appropriate to preprocess in some way (such as by removing duplicates according to whatever business logic is appropriate for your app).
Aug ’24
Reply to ModelActors not persisting relationships in iOS 18 beta
Unfortunately this bug is not fixed in Xcode 16 beta 5 / iOS 18.0 (22A5326g) beta. Correct me if I'm wrong, but doesn't this break the only "correct" way to do background work that appends new ModelObjects to an existing to-many relationship? Our app downloads data and creates new Items that populate an existing to-many relationship in a Location ModelObject. Our understanding is that the only idiomatic way to do this in the background with Swift Data is with a ModelActor, so this is how our app functions. It would be great for a DTS Engineer to confirm that what I describe above is the correct approach, and that the bug described in this post is expected to be fixed before iOS 18 RC. Otherwise our app requires some more significant rework to get ready for iOS 18, and it's not clear that there is another Swift-Data-intended way to accomplish this task.
Aug ’24
Reply to Changes to SwiftData SubModels do not update the UI
Perhaps try defining a relationship in your models. https://developer.apple.com/documentation/swiftdata/defining-data-relationships-with-enumerations-and-model-classes/ Your current usage of these models is non-standard. I understand that this is a toy example, but it isn't normally done to create a Model inside another Model without defining a relationship between them. You would normally do something like this: import Foundation import SwiftData @Model final class Item { var firstArray: [String] var itemDetail: ItemDetail init(firstArray: [String], itemDetail: ItemDetail) { self.firstArray = firstArray self.itemDetail = itemDetail } } @Model class ItemDetail { var secondArray: [String] // VVV This is the new line that creates the relationship. @Relationship(inverse: \Item.itemDetail) var item: Item init(secondArray: [String]) { self.secondArray = secondArray } }
Aug ’24
Reply to ModelActors not persisting relationships in iOS 18 beta
Hi @sendtobo I'm not seeing any change in behavior when I try your code. I added the following function to my example ModelActor: func createEmployeeThenAdd(CompanyWithID companyID: PersistentIdentifier?) { guard let companyID, let company: Company = self[companyID, as: Company.self] else { logger.error("Could not get a company") return } let newEmployee = Employee(company: nil) modelContext.insert(newEmployee) newEmployee.company = company logger.notice("Created employee \(newEmployee.name) in Company \(newEmployee.company?.name ?? "NIL")") try! modelContext.save() } When I run it from iOS 17, everything works normally. When I run it from iOS 18 beta 4, I see in the console the expected result with a relationship: Created employee 14E7161E in Company E3AD3F67 But the UI doesn't update (as you noted). However when I tap the "Add in View" button which runs on the main actor, I see the view update with both inserts (failed insert via ModelActor, successful via UI/main actor). Employee 14E7161E in company NIL Employee 81AA7153 in company E3AD3F67 I note in your example that you are adding companies.first. This means you are not getting the company to add in the same way as my example. I'm passing in the PersistentIdentifier and pulling the model object from the container with that reference, so my function doesn't have access to all companies. How are you getting the list of all companies to add one to the relationship in your example?
Jul ’24
Reply to Bug in Calendar.date(from:) in iOS 18? It is now underspecified with year, weekOfYear, and yearForWeekOfYear?
I agree that the test is odd. In our app we are generating a sequence of all of the start dates for weeks within a year by iterating over weekOfYear. Somehow we ended up with both year and yearForWeekOfYear specified (probably because year alone didn't give us the results we wanted). Dropping the year does indeed generate the same sequence of results as including it in both iOS 17 and 18 beta so it looks like we just make that change and are good. It seems to me that Calendar.date(from:) should return nil for cases where year and yearForWeekOfYear are specified, rather than January 1 of the specified year. Cheers!
Jul ’24
Reply to Crash in Swift Data on iOS 17.5, Resolved in iOS 18.0 Developer Beta
The code you posted is generic to all Observation objects, including Models in SwiftData, so it is not going to be helpful. Your steps to reproduce are also not helping us to help you because of course we don't have your app's code. The most likely root cause of your crash is related to the fact that Views in iOS 18 are now implicitly annotated with @MainActor. If you are running code that requires it to be on the main actor, it will work silently in iOS 18, but will fail in earlier versions of iOS. Also, be aware that Apple will not approve any apps that use Xcode 16 until it reaches release candidate. You have to use Xcode 15 and target iOS 17 until then to be approvable. Good luck to you
Jul ’24
Reply to WeatherKit Historical Data Availability
I am also having persistent problems with historical data from WeatherKit. There are certain locations, on certain dates, where the service throws an unhandled error. I used a Technical Support Incident to try to get help and was told there is no workaround. I've had FB open with them since November 2023 for these issues and seen no movement on the topic. I have also posted about it on these forums here.. It's particularly frustrating because If you request a date range that is fully missing, the API throws an error of an internal / private type (can't specifically catch it). If you request a date range that has partial missing data, the API silently fails to return the missing data (no errors thrown, just some dates don't get returned). At this point I think WeatherKit is not suitable for use as a source of historical data. It doesn't seem to be a well tested aspect of the service, presumably because the historical data doesn't get a lot of use by developers. We are working on an alternate data vendor for our app for historical data. We may continue to use WeatherKit for current / recent weather, as that always works for us so far, but historical weather is unreliable. I've got a GitHub gist with stand alone code to replicate the problem if anyone wants to play with what the errors look like. Maybe if more people express an interest in historical data and file Feedbacks the issue might get more visibility.
Mar ’24
Reply to WeatherKit always fails with 404 for specific lat/long/dates with forecastDaily
I want to update this with feedback that I received from Apple Developer Technical Support. "There is no workaround DTS can provide for the bug reports mentioned (FB13608710,FB13551253,FB13188858); they are all still under investigation." So if you are seeing intermittent failures to download historical data using WeatherKit, or permanent failures at specific locations and dates, Apple is aware of it and it's not something you are doing wrong on your end. This includes failures where a request does not throw an error, but it silently fails to retrieve data from the middle of the range. I have implemented a stand-alone SwiftUI view that demonstrates these failures to request historical data at this gist. You of course need to have a Xcode project with a WeatherKit Capability. Hopefully this can be resolved by Apple, but we will be pursuing an alternate weather data vendor, as historical data availability is a tent pole of our app. Note that we have not seen problems with WeatherKit providing recent or forecast data, but it seems that historical data is not as much of a focus for WeatherKit as Time Machine was for Dark Sky. I can only imagine that few apps are relying on their historical data.
Feb ’24
Reply to WeatherKit always fails with 404 for specific lat/long/dates with forecastDaily
I’ll also mention that this is particularly frustrating because we also routinely see requests that initially fail with 404, but if we retry a few times (sometimes even a day later) it will eventually succeed. So we have built our app to retry a few times if we get a 404 error. However, in the cases posted above, they never succeed. It is not a good experience that we seem to get the same error from WeatherKit for queries that temporarily fail and those that permanently fail, because we will have to try to distinguish the two cases based on heuristics around how often it failed for particular dates / locations for each user. WeatherKit should really throw different errors, or return an empty array, if data is never going to be returned vs a temporary failure. Of course it should never throw an error for a valid query, but given that this is happening we would like to see better errors.
Feb ’24