Posts

Post not yet marked as solved
2 Replies
846 Views
In my SwiftUI/SwiftData application, I want to store videos in SwiftData objects (using external storage). To display them, I need to instantiate an AVPlayer (for use in a VideoPlayer view). But AVPlayer expects a URL, not a Data object. Obviously, I can solve this problem via a file-caching scheme (i.e., by creating a local file when needed, using an LRU cache to control it's lifetime), but this results in an extra copy of the data (besides the hidden local file managed by SwiftData/CoreData). However, since videos can be quite large, I would prefer not to do that. Has anyone any thoughts about how I can avoid the extra data copy?
Posted Last updated
.
Post marked as solved
2 Replies
1.3k Views
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).
Posted Last updated
.
Post not yet marked as solved
0 Replies
297 Views
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.
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.1k Views
SwiftUI & SwiftData. I have a view that lists SwiftData objects. Tapping on a list item navigates to a detail view. The list view also has a "New Object" button. Tapping it opens a sheet used to create a new object. There are, obviously, two possible outcomes from interacting with the sheet — a new object could be created or the user could cancel without creating a new object. If the user creates a new object using the sheet, I want to open the detail view for that object. My thought was to do this in the onDismiss handler for the sheet. However, that handler takes no arguments. What is best practice for handling this situation? In UIKit, I would return a Result<Object, Error> in a closure. That won't work here. What is the "correct" way to handle this that is compatible with SwiftData and the Observation framework?
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.1k Views
In CoreData, many-relationships are implemented as NSSet objects. In the SwiftData examples, they are shown as arrays. Are they really arrays (i.e., order-preserving and duplicates allowed) or are they arrays made from CoreData NSSets? In my applications, this makes a HUGE difference.
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.3k Views
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?
Posted Last updated
.
Post not yet marked as solved
0 Replies
454 Views
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?
Posted Last updated
.
Post not yet marked as solved
4 Replies
1.8k Views
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...)
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.3k Views
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.
Posted Last updated
.
Post not yet marked as solved
0 Replies
853 Views
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?
Posted Last updated
.
Post not yet marked as solved
0 Replies
853 Views
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?
Posted Last updated
.
Post not yet marked as solved
0 Replies
2.0k Views
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?
Posted Last updated
.
Post not yet marked as solved
0 Replies
651 Views
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.
Posted Last updated
.
Post not yet marked as solved
4 Replies
1.3k Views
According to the documentation, trailingSwipeActionsConfigurationForRowAt() is supported for MacCatalyst, but I can't seem to get it to work there. On iOS, my tableView has rows with detail accessories, so the user can (all without entering "editMode") tap for more information swipe-left to delete swipe-right to edit (in some cases) When running on the Mac via MacCatalyst, the swipe gestures do not seem to work and only clicks (i.e., to show detail) have any effect. How can I retain the desired behavior?
Posted Last updated
.
Post not yet marked as solved
0 Replies
569 Views
I have what must be a common problem, and am looking for some architectural suggestions. Over the years, I've built custom objects (e.g., popup calendars, button menus, etc) which have now been added to iOS as of iOS 14. This presents a problem for me, because I want my apps to support pre-14 systems. What I want to implement is: An @IBDesignable object which implements a custom class on pre-14 systems, but implements the new iOS-14 objects on 14+. The object must compile and build with a deployment target of 12.0. Obviously this means that I need to use @available and #available to make the link work. I expect to use adaptor (wrapper) patterns to present a common external API that is iOS-version independent. BUT, I can't figure out how to make this happen. I have some thoughts about making the @IBDesignable class a proxy for an implementation class (which is factory-constructed in the proxy's init methods). The implementation object would be intalled as a subview of the proxy object so all UI would go to it. But I'm sure I'm not thinking of all of the potential issues here. Have you done something similar to this? Can you give any help or advice about such an undertaking before I sit down and get mired in code? (Maybe even a design pattern to share?) Any help would be welcome.
Posted Last updated
.