Many thanks for your sample Jim, it looks very clear.Unfortunately, in practise, this will not work for me.This mechanism only seems to work for items wrapped in List at source and destination and once I had edited my project down to use List and got the Drag and Drop working, it was obvious that (for me) the wrong assumptions are being made.I need to drag a representation of a child Entity, onto a parent Entity to create a relationship between them (similar to the Files App, dragging a Tag onto a File).What occurs in practice is that the List makes room to drop the child Entity between two parent Entities, rather than onto one.It looks like this is designed for move type operations rather then apply type operations.
Post
Replies
Boosts
Views
Activity
Thanks JimBoth additions are great news ... except, I still do not trust the outstanding issues with Catalina (which I beleive the new Xcode requires?).One day I hope ...
This solution is OK for simple static content, localisation is a problem but it is a problem with NSAttributedString as well.The App I am developing allows the user to write rich notes to attach to their content, which gets stored in CoreData. I do not see how this solution could work in these circumstances.Currently we store the rich text as NSAttributedString.Will NSAttributedString have a future in a SwiftUI world?
I have tried using the AQUI Library version of this control in my App.I find that if I use it like this :ScrollView {
VStack(alignment: .leading, spacing: 20) {
Text("A long title that needs to wrap to multiple lines ... blah blah blah")
.font(.largeTitle)
Spacer()
TextView(text: $referenceToEditableText)
Spacer()
/* more controls */
}
}the text wrap of the Text control gets broken unless I set a fixed height on the TextView.Is there a trick to get this control to self-size?
This is still a problem with Xcode 11.4 beta 3 (11N132i)I use SPM to import two 3rd party packages.They are each needed both in the iOS App and an accompanying share extension.I do not know how to resolve this.
OK, I have the solution, posting it incase anyone else has the same problem.The entitlements file for the Share Extension was missing some keys that existed in the App :I needed to add values for iCloud Container Identifiers and iCloud Services
I have got it working now but for what feel like all of the wrong reasons.I moved the notification handler up a level, so that the view that contains all of the @FetchRequest is force refreshed by being re-constructed.The solution feels dirty, I still beleive that the @FetchRequest should be able to trigger a data reload itself when the data changes.The top level ContentView is now having to be very heavy handed IMHO. by: struct ContentView: View {
private var didUpdate = NotificationCenter.default.publisher(for: .coreDataRemoteChange)
@State private var renderID = UUID()
var body: some View {
NavigationView {
MasterListView()
.navigationBarTitle(Text("Things"))
.navigationBarItems(
trailing: EditButton()
)
Text("No Content").noContentStyle()
Print("ContentView \(renderID)")
}
.id(self.renderID)
.onReceive(self.didUpdate) { _ in
print("ContentView received .coreDataRemoteChange")
self.renderID = UUID()
}
.navigationViewStyle(DoubleColumnNavigationViewStyle())
.accentColor(.accent)
}
}... attaching a UUID to the NavigationView.Because the notification is reliable and the data was actually being updated, techniques likeNSManagedObjectContext.mergeChanges(fromRemoteContextSave: [NSInsertedObjectsKey: addedThings], into: [taskContext])are not actually required.I would be surprised if this was the way we are intended to use @FetchRequest
I have resolved this but still do not know why the two ways of presenting made such a big difference.Instead of having a @State var on the View (bound to the SearchField, sent to the SearchPublisher), I performed the binding inside the SearchPublisher by adding a new @Published var :@Published private(set) var hits = [ThingViewModel]()
@Published var term: String = UserDefaults.standard.string(forKey: .key) ?? "" {
didSet {
guard let search = term.trimmed(), !search.isEmpty else {
self.hits = []
UserDefaults.standard.removeObject(forKey: .key)
return
}
self.perform(self.predicate(search))
UserDefaults.standard.set(search, forKey: .key)
}
}Then bind the SearchField directly to it :SearchBar(text: self.$thingSearch.term, placeholder: "Search for Things")However, this does not answer the original question.
I no longer find this solution works reliably.Sending a DarwinNotification from the App Extension to the App may be making it more reliable.If it really needs this Notification, it would make me think of two issues :CloudKit synchronisation is not functioning properly when data is saved to CoreData in a shared App Group by an App Extension.For correct synchronisation to occur after a save from an App Extension, the containing App would have to be running.The real problem is reliability.Sometimes, the save does propogate to other devices in both cases (parent app running or not), sometimes it does not.Sometimes the propogation is partial (missing relationships).Should I expect CoreData + CloudKIT as it stands to be production-ready or am I doing something wrong?
OK, WWDC 2020 has started, I would love to get an Apple Engineer to respond to this issue, will this reply signal this or do I need to raise a new issue?
The proposed solution does work but it means loosing other features from List, like an EditMode and the ability to re-arrange and delete items.
To test my hypothesis about the environment being the cause, I replaced my two custom UTIs with system UTIs (public.item and public.folder).
The missing provider issues went away, my code was working but the system was not making the custom UTIs available to the DropDelegate.
However, the issue I raised with the filter not working in onDrop(of:delegate:) still seems broken.
Resolved the problem.
The layout above works fine, the problem was with my Model.
Items in the collection had unstable identifiers.