Post

Replies

Boosts

Views

Activity

@Attribute 'unique' and complex keys
The 'unique' attribute is a really nice feature, BUT. In some of my apps, the unique identifier for an object is a combination of multiple attributes. (Example: a book title is not unique, but a combination of book title and author list is.) How do I model this with SwiftData? I cannot use @Attribute(.unique) on either the title OR the author list, but I want SwiftData to provide the same "insert or update" logic. Is this possible?
5
4
2.7k
Sep ’25
List of relationship members fails to update when member content changes
FB13099793 I have a view which lists detail information about a SwiftData object, including a list of the members of its relationship. The Problem: If I use a modal presentation to edit the content of a relationship-member, upon return, the member has been updated, but the view falis to show it. The view updates correctly on adding a new member to the relationship, deleting a member, etc. But I cannot get the List to update if the content of the member changes (in a modal presentation). A few requirements that may be of significance: (1) The relationship (and inverse) are defined as optional because it is an eventual requirement for this app to use CloudKit synchronization. (2) The display of the members must be ordered. For this reason, the member object contains a "ordinal" property which is used to sort the the members. The relevant parts of the models are: @Model final public class Build { public var bld: Int @Relationship(inverse: \ChecklistItem.build) public var checklist: [ChecklistItem]? public init(bld: Int) { self.bld = bld self.checklist = [] } } @Model final public class ChecklistItem { public var ordinal: Int public var title: String public var subtitle: String // etc. public var build: Build? public init(build: Build) { self.ordinal = -1 self.title = "" self.subtitle = "" self.build = build } } The relevant parts of the view which handles the display is shown below. (Please look at the notes that follow the code for a discussion of some issues.) struct buildDetailChecklistView: View { @Environment(\.modelContext) var context: modelContext @State private var selectedItem: ChecklistItem? = nil @Bindable var build: Build init(build: Build) { self.build = Build } var body: some View { VStack { // ... some other stuff } List { ForEach((build.checklist ?? []) .sorted(by: { (a,b) in a.ordinal < b.ordinal})) { item in RowView(item) // displays title, subtitle, etc. .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button { deleteRow(item) } label: { Label("Delete", systemImage: "trash") } .tint(.red) } .swipeActions(edge: .leading, allowsFullSwipe: false) { Button { selectedItem = item } label: { Label("Edit", systemImage: "pencil.line") } .tint(.blue) } } .sheet(item: $selectedItem) { item in BuildDetailAddEditChecklistItem(item: item, handler: updateChecklist(_:)) } } } private func updateChecklist(_ item: ChecklistItem) { if let index = build.checklist!.firstIndex(where: { $0 == item }) { DispatchQueue.main.async { [index] in build.checklist!.remove(at: index) try? context.save() build.checklist!.insert(item, at: index) } } } } Notes: (1) I cannot use a @Query macro in this case because of limitations in #Predicate. Every predicate I tried (to match the ChecklistItem's build member with it's parent's build object crash.) (2) I don't want to use @Query anyway because there is no need for the extra fetch operation it implies. All of the data is already present in the relationship. There ought to be a new macro/propertyWrapper to handle this. (3) Dealing with the required sort operation on the relationship members [in the ForEach call] is very awkward. There ought to be a better way. (4) The BuildDetailAddEditChecklistItem() function is a modal dialog, used to edit the content of the specified ChecklistItem (for example, changing its subtitle). On return, I expected to see the List display the new contents of the selected item. IT DOES NOT. (5) The handler argument of BuildDetailAddEditChecklist() is one of the things I tried to "get the List's attention". The handler function is called on a successful return from the model dialog. The implementation of the handler function finds the selected item in the checklist, removes it, and inserts it back into the checklist. I expected that this would force an update, but it does not.
0
1
549
Sep ’23
Should I worry about this error message?
I have a SwiftData Model which includes a property of type Array. @Model final class Handler { public var id: UUID public var name: String public var mailingAddress: [String] . . . public init() { self.id = UUID() self.name = "" self.mailingAddress = [] . . . } When I use this Model in code, the mailingAddress field appears to work just as I would expect, but when saving it (running in Simulator), I see the following logged message: CoreData: fault: Could not materialize Objective-C class named "Array" from declared attribute value type "Array<String>" of attribute named mailingAddress Should I be worried about this?
0
1
498
Oct ’24
NavigationPath.append but .navigationDestination Not Being Called
I am trying to do a bit of fancy navigation in SwiftUI using NavigationPath and am having a problem. I have a root view with includes a button: struct ClassListScreen: View { @Bindable private var router = AppRouter.shared @State private var addCourse: Bool = false ... var body: some View { ... Button("Add Class") { router.currentPath.append(addCourse) }.buttonStyle(.borderedProminent) ... .navigationDestination(for: Bool.self){ _ in ClassAddDialog { course in sortCourses() } } } } router.currentPath is the NavigationPath associated with the operative NavigationStack. (This app has a TabView and each Tab has its own NavigationStack and NavigationPath). Tapping the button correctly opens the ClassAddDialog. In ClassAddDialog is another button: struct ClassAddDialog: View { @Bindable private var router = AppRouter.shared @State private var idString: String = "" ... var body: some View { ... Button("Save") { let course = ... ... (save logic) idString = course.id.uuidString var path = router.currentPath path.removeLast() path.append(idString) router.currentPath = path }.buttonStyle(.borderedProminent) ... .navigationDestination(for: String.self) { str in if let id = UUID(uuidString: str), let course = Course.findByID(id, with: context) { ClassDetailScreen(course: course) } } } } My intent here is that tapping the Save button in ClassAddDialog would pop that view and move directly to the ClassDetailScreen (without returning to the root ClassListScreen). The problem is that the code inside the navigationDestination is NEVER hit. (I.e., a breakpoint on the if let ... statement) never fires. I just end up on a (nearly) blank view with a warning triangle icon in its center. (And yes, the back button takes me to the root, so the ClassAddDialog WAS removed as expected.) And I don't understand why. Can anyone share any insight here?
0
1
74
Oct ’25
Core Data: Fatal Error sorting using a computed property
I have a Core Data entity with a computed property and I want to sort the objects of this entity by this computed property. So • I build the NSFetchRequest in the normal way, including an NSSortDescriptor for sorting by this computed property. • Construct the usual NSFetchedResultController and call performFetch(). This results in a fatal error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath score not found in entity Wine' I've tried to do this in several different ways, including (a) @objc public var score: Float { get { <getter code here> } } (b) Define score in the data model as transient, then @objc public var _score: Float { get { <getter code here> } } ... and ... public override func awakeFromFetch() { super.awakeFromFetch() score = _score } But the error persists. Is there any way to get this to work without abandoning NSFetchedResultsController, fetching unsorted records, sorting them programmatically and building the snapshot from the sorted array of objects? (I know, but it's the best I've been able to come up with so far...)
4
0
2.6k
Oct ’22
SwiftUI - Open a file via a fileURL
I am writing a SwiftUI-based app and have the following requirements: Use a file browser (such as UIDocumentPickerViewController) to find an arbitrary file (not one that the application knows how to open) which is external to the app bundle but local to the device the app is running on - either in local storage or on an iCloud drive. Save this location. At a later time, open this file. The file should open in an app that knows how to open it or in a browser. Do all of the above in a way that works with multiple devices (synced via CloudKit/SwiftData). For example, select a file on my iCloud drive on my Mac, then save it (using CloudKit/SwiftData) and open it on an iPad that has an app that can open it. I am addressing requirement #1 using UIDocumentPickerViewController wrapped with a UIViewControllerRepresentable. It returns a security-scoped URL. (Note: this worries me because of requirement #4). I use the Bookmark API to implement requirement #2. For requirement #3, I load the bookmark data, convert it back to a security-scoped URL and either Link("Open", destination: url) or @Environment(\.openURL) private var openURL if url.startAccessingSecurityScopedResource() { defer { url.stopAccessingSecurityScopedResource() } openURL(url) { accepted in // do something here } } Both of these implementations fail. The Link call responds with "invalid input parameters" (Error Domain=NSOSStatusErrorDomain, Code=-50), the openURL() call just returns false. So, my questions are: Since it appears the Link and openURL work for internet URLs, but not for security-scoped file URLs, how to I cause a document to be opened (using an application which knows how to open it or a browser). Since UIDocumentPickerViewController is returning a security-scoped URL, how can I make this work on a different device than the one on which the user selected the document? (Assuming, of course, that we are talking about a document that is on an iCloud drive that both devices have access to).
3
0
3.6k
Jan ’25
How to control when a DatePicker "pops up"
I have a Date field that holds the scheduled start date for an activity.. However, activities can be unscheduled (i.e., waiting to be scheduled at some other time). I want to use Date.distantFuture to indicate that the activity is unscheduled. Therefore I am looking to implement logic in my UI that looks something like @State private var showCalendar: Bool = false if date == .distantFuture { Button("unscheduled") { showCalendar.toggle() }.buttonStyle(.bordered) } else { DatePicker(section: $date) } .popover(isPresented: $showCalendar) { <use DatePicker Calendar view> } But this approach requires that I access the DataPicker's Calendar view and I don't know how to do that (and I don't ever what my users to see "Dec 31, 4000"). Any ideas? (BTW, I have a UIKit Calendar control I could use, but I'd prefer to use the standard control if possible.)
4
0
110
Mar ’25
Automatic Code Signing Error
I am trying to update an old UIKit/CoreData app and am (among other changes) adding CloudKit synchronization support. I enabled CloudKit (ie, set up a new CloudKit domain, enabled CloudKit, Background Mode Remote Notifications, and Push Notifications. When I did this, automatic code signing failed. (see attached for the messages). I tried creating and downloading a new provisioning profile, but that did not help. FB19742743 Can someone help me? I have absolutely no idea of what to do next to get this app signed (and hopefully back into the AppStore soon).
2
0
221
Aug ’25
CloudKit Synchronized "User Defaults"
I have a CoreData-based application, set up with a private CloudKit container and using NSPersistentCloudKitContainer. However, I need additional CloudKit-synchronized data that lives in this container, but not as part of a CoreData scheme. (I.e., I need to read/write some data to the CloudKit container BEFORE initializing the NSPersistentCloudKitContainer. (1) Is this possible? [I'm assuming that the answer is YES.] (2) Since I'm a complete neophyte with CloudKit, can you give me some guidance as to how to set this all up? One way to think about what I want to do is to create a cloud-synchronized UserDefaults that provides consistent default data to all of a user's devices.
0
0
901
Jun ’21
Help with iOS 15 UIButton?
I am trying to construct a button using the new iOS15 button API. (Xcode 13ß3, UIKit & Storyboards) The button has a title (aligned .leading) and an image (aligned .trailing). The button has the following layout constraints: a fixed leading constraint (to a label that provides prompt text) a center-vertically constraint (to that same label) a trailing constraint ( >= a margin value) What I’m trying to accomplish is that the button should adjust its width based on the title content, not wrapping until the width causes the trailing constraint to be violated. What actually happens is the the button’s text wraps. It acts as if it prefers wrapping to changing its size. There are mentions in the documentation about disabling text wrapping for the button, but the obvious things, such as button.titleLabel?.lineBreakMode = .byTruncatingMiddle don’t work. Has anyone whose tried working with iOS 15 buttons have any suggestions?
0
0
2.2k
Jul ’21
Async/await and modal dialogs
In a UIKit context, has anyone had experience/success in using async/await to synchronize a modal dialog with other logic? I've tried it a bit without success. I.e, given a presented dialog, I want to capture data in the dialog, then use the results in a simple, linear fashion. (Something that looks like "Present the dialog, wait for results, use results" -- all inline without closures.) It seems to me that async/await with @MainActor ought to make that possible, but I haven't yet figured out how. I'd really like to see a real-world example.  Can you help?
0
0
984
Sep ’21
UICollectionView with DiffableDataSource
Xcode 13.1, iOS 25 SDK I have a UICollectionView (with a custom UICollectionViewLayout) which I am updating with a DiffableDataSource. This CollectionView displays a particular data object (with a given number of sections and items). The user can choose to display a different object (with a different number of sections and items), reusing this CollectionView. When this occurs, I do the following: (pass the new data object to the custom layout) let layout = collectionView.collectionViewLayout layout.invalidateLayout() collectionView.contentSize = layout.collectionViewContentSize (calculate a new snapshot and apply it) When the new data object has FEWER sections and/or items as the first, I get a series of warning messages (one for each of the cells that are no longer in the collection view) as follows: 2021-12-07 14:29:02.239301-0600 WineCorner[82916:1921357] [CollectionView] Layout attributes <UICollectionViewLayoutAttributes: 0x7f77b3047e00> index path: (<NSIndexPath: 0xa0f0b1eb018e754a> {length = 2, path = 0 - 4}); frame = (578.118 6; 160 160); transform = [0.70710678118654757, -0.70710678118654746, 0.70710678118654746, 0.70710678118654757, 0, 0]; zIndex = 1; were received from the layout <WineCorner.WineRackLayout: 0x7f77b1f1a0c0> but are not valid for the data source counts. Attributes will be ignored. Obviously, I am not handling the situation correctly. What should I do so that these warning messages are not issued?
0
0
1.1k
Dec ’21
WidgetKit — how to send data from Widget to main app
Back in the days of NCWidgetProviding, we had a button to open our app. We included code like the following in the app's info.plist: <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>com.xxxx.yyyy/string> <key>CFBundleURLSchemes</key> <array> <string>yyyy</string> </array> </dict> </array> and in the widget's button, we used code like: let appURL = URL(string: "yyyy://?url=\(zzz)") extensionContext?.open(appURL, completionHandler: nil) How can I achieve the same result using WidgetKit? (I.e., sending a URI to my main app)? The use case is that the widget displays a random record from a database and when the user taps on the widget, I want to open my app, displaying THAT SAME RECORD. Thanks.
2
0
2.6k
Sep ’22
CoreData Migration for CloudKit
I am upgrading an existing (CoreData-based) iOS app to support CloudKit synchronization. This doesn't work because the app includes an ORDERED relationship. I need to perform a migration from this ordered relationship to something else that supports both CloudKit and maintains ordering. The problem is less about WHAT I need to do to support my requirements as it is HOW to perform the migration (so that my existing customers don't lose data.) Have you encountered this problem? How did you solve it?
0
0
678
Mar ’23