-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Manual data reload #14
base: main
Are you sure you want to change the base?
Conversation
This is an excellent bug! By that I mean I hate everything about it already. 😄 I was thinking about it for some time and couldn't come up with a way to avoid calling reload ourselves. I am open to ideas for avoid the whole reload business of we can. If we are stuck with reloading, Instead of providing context unaware global functions, I think we can have a slightly better API inspired from OutlineViewReader { proxy in
OutlineView(...)
.onChange(of: thatPeskyState) {
proxy.reload()
// or
proxy.reload(items: itemsToReload) // This should probably accept a "sequence" of items
}
} There are multiple ways of implementing the public struct OutlineViewReader<Content: View>: View {
@State private var proxy = OutlineViewReaderProxy()
var content: (OutlineViewReaderProxy) -> Content
var body: some View {
content(proxy)
.environment(\.outlineViewReaderProxy, proxy)
}
} The public struct OutlineViewReaderProxy {
enum ReloadState {
case items([Any]) // Must be an erased type I suppose, because the OutlineViewReader does not know the element type.
case all
case none
}
let reloadState = CurrentValueSubject(ReloadState.none)
public func reload() {
reloadState.send(.all)
}
[...]
}
public extension OutlineViewReaderProxy: EnvironmentKey {
static let defaultValue = OutlineViewReaderProxy()
}
public extension EnvironmentValues {
var outlineViewReaderProxy: OutlineViewReaderProxy {
get { self[OutlineViewReaderProxy.self] }
set { self[OutlineViewReaderProxy.self] = newValue }
}
} Finally, in the public struct OutlineView<...> {
@Environment(\.outlineViewReaderProxy) var proxy
public func updateNSViewController(
_ outlineController: OutlineViewController<Data, Drop>,
context: Context
) {
[...]
// The outlineController could have some logic for subscribing to the
// publisher for reloads and performing the actual reload.
// The proxy object may change during the runtime so need to make
// sure that we are always subscribing to the latest object.
outlineController.setProxy(proxy)
}
} |
Very cool idea! I like it... I haven't tried anything like it before, so I don't know what pitfalls there might be. But it is nice to not rely on Notifications and global functions. In the meantime I have been using an alternate solution that also solves this issue that I found recently (although I don't think you'll like this solution too much 😆 ). My solution was to require that In that way, cells would reload when data updates occur and the the |
I ran into an issue where making edits to an attribute in the
OutlineView
needed to change properties of the providedTableViewCell
s, but no state change was causing the cells to update. So I put together this pull request which adds functionality for manually calling a version ofNSOutlineView
'sreloadData
orreloadItem
.The functionality requires two steps:
reloadID
of theOutlineView
using the modifier functionreloadIdentifier(_:)
triggerReloadOfOutlineView(id:itemIds:)
, with theOutlineView.reloadID
set in the previous step as the first parameter, and an optional array ofOutlineView.Data.Element.ID
as the second parameter. If no element IDs are provided, theOutlineViewController
callsreloadData
, thus reloading the cell views for the entire view. If element IDs are provided, only the rows with the specified IDs will be reloaded.The additional functionality is entirely optional, so won't require existing projects to be updated if not using reload functions.
I also added another sample project, showing where the functionality may be needed: In it, a color picker is used to provide the text color for
FileItemView
rows. Without thetriggerReloadOfOutlineView
functions, updating the binding value ofContentView.rootTextColor
andContentView.childTextColor
would not immediately update the text color of the displayed cells. By calling the function duringonChange(of: rootTextColor)
andonChange(of: childTextColor)
, the text color updates as expected.Screen.Recording.2023-04-01.at.10.51.39.AM.mov