What is the intended response to Array change notification for dependents?


(Edward Connell) #1

I would like to have an Array implementation where I get more information
than just "the whole thing changed".
As a value type I get it, but lets say it's a list of 500 image info
structs and it's bound to UI. You change one item, now the whole array
changes and you have to rebuild the entire visual tree right? Rebuilding
the state of dependent objects can be really expensive, not just UI things.

Is there some efficient strategy that the library designers intended for
this situation?
It seems like a really common and obvious scenario.
Insights and suggestions are appreciated.

Thanks, Ed


(Rien) #2

I don’t think there is a single answer to this. It is all highly dependant on what the application does with the info.
Sometimes it will indeed be necessary to rebuild the entire gui, other times it is enough to simply insert a new table cell.

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Balancingrock
Project: http://swiftfire.nl

···

On 07 Mar 2017, at 03:56, Edward Connell via swift-users <swift-users@swift.org> wrote:

I would like to have an Array implementation where I get more information than just "the whole thing changed".
As a value type I get it, but lets say it's a list of 500 image info structs and it's bound to UI. You change one item, now the whole array changes and you have to rebuild the entire visual tree right? Rebuilding the state of dependent objects can be really expensive, not just UI things.

Is there some efficient strategy that the library designers intended for this situation?
It seems like a really common and obvious scenario.
Insights and suggestions are appreciated.

Thanks, Ed

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Michael Gardner) #3

The general approach would be to run a diff between your old and new arrays. Something like https://github.com/jflinter/Dwifft could help, though I haven't used it personally.

Another approach is to build a wrapper around your source array with limited modification methods and a KVO-like notification system. The notifications can map cleanly to UITableView updates, and there's no extra diffing calculations involved. Of course, this method won't work if your source array needs to be modified by code you don't control.

···

On Mar 6, 2017, at 18:56, Edward Connell via swift-users <swift-users@swift.org> wrote:

I would like to have an Array implementation where I get more information than just "the whole thing changed".
As a value type I get it, but lets say it's a list of 500 image info structs and it's bound to UI. You change one item, now the whole array changes and you have to rebuild the entire visual tree right? Rebuilding the state of dependent objects can be really expensive, not just UI things.

Is there some efficient strategy that the library designers intended for this situation?
It seems like a really common and obvious scenario.
Insights and suggestions are appreciated.

Thanks, Ed

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jens Alfke) #4

In Apple’s Foundation framework, Key-Value Observing (KVO) fills this need, and can be used with NSMutableArray, including when it’s bridged to Swift. But it doesn’t really transfer to a pure Swift environment since arrays are value types: changing one item is actually replacing the entire array with a new one (optimized through clever internal data-sharing.)

I would assume that the people working on the design of the Swift Foundation library are thinking about similar observer APIs, but I don’t know the details.

—Jens

···

On Mar 6, 2017, at 11:36 PM, Rien via swift-users <swift-users@swift.org> wrote:

On 07 Mar 2017, at 03:56, Edward Connell via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I would like to have an Array implementation where I get more information than just "the whole thing changed".
As a value type I get it, but lets say it's a list of 500 image info structs and it's bound to UI. You change one item, now the whole array changes and you have to rebuild the entire visual tree right? Rebuilding the state of dependent objects can be really expensive, not just UI things.


(Edward Connell) #5

Thank you Jens, that is exactly the point of my question.
At the moment in pure swift there is no incremental array change API for observers. This must have been considered by the library designers.

My question is, what was their design intent? Rebuild all dependents every time?

···

Sent from my iPhone

On Mar 7, 2017, at 7:59 AM, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 6, 2017, at 11:36 PM, Rien via swift-users <swift-users@swift.org> wrote:

On 07 Mar 2017, at 03:56, Edward Connell via swift-users <swift-users@swift.org> wrote:

I would like to have an Array implementation where I get more information than just "the whole thing changed".
As a value type I get it, but lets say it's a list of 500 image info structs and it's bound to UI. You change one item, now the whole array changes and you have to rebuild the entire visual tree right? Rebuilding the state of dependent objects can be really expensive, not just UI things.

In Apple’s Foundation framework, Key-Value Observing (KVO) fills this need, and can be used with NSMutableArray, including when it’s bridged to Swift. But it doesn’t really transfer to a pure Swift environment since arrays are value types: changing one item is actually replacing the entire array with a new one (optimized through clever internal data-sharing.)

I would assume that the people working on the design of the Swift Foundation library are thinking about similar observer APIs, but I don’t know the details.

―Jens


(Jens Alfke) #6

Swift started out by piggybacking on facilities provided by Foundation. Over time it’s becoming self-sufficient, but it’s a work in progress. Putting “design intent” in the past tense is inaccurate … I would say that this seems to be something to come in the future.

Are you asking how to use KVO with Swift arrays, or are you looking at pure Swift?

—Jens

···

On Mar 7, 2017, at 8:08 AM, Edward Connell <ewconnell@gmail.com> wrote:

My question is, what was their design intent? Rebuild all dependents every time?


(Edward Connell) #7

My project is on Linux, so pure Swift.
So you don't think this is an issue of intentional library design, but a
recognized problem that hasn't been addressed yet?

Thanks, Ed

···

On Tue, Mar 7, 2017 at 8:13 AM, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 7, 2017, at 8:08 AM, Edward Connell <ewconnell@gmail.com> wrote:

My question is, what was their design intent? Rebuild all dependents every
time?

Swift started out by piggybacking on facilities provided by Foundation.
Over time it’s becoming self-sufficient, but it’s a work in progress.
Putting “design intent” in the past tense is inaccurate … I would say that
this seems to be something to come in the future.

Are you asking how to use KVO with Swift arrays, or are you looking at
pure Swift?

—Jens


(Jens Alfke) #8

The general approach would be to run a diff between your old and new arrays. Something like https://github.com/jflinter/Dwifft could help, though I haven't used it personally.

I’ve implemented something like this in the past. It’s fairly expensive, though; that library does claim to use an optimized algorithm, but the cost is still a lot higher than just posting a notification. (And my own experience of using KVO is that notifications can become significant hot spots in performance, because they happen a lot.)

On the other hand, if the array is expected to change often, more often than you want to redraw the GUI, it could make sense to ignore the fine-grained changes and just set a timer to trigger after a few hundred ms, which would then compare the old and new arrays this way and apply a minimal update to the view.

Another approach is to build a wrapper around your source array with limited modification methods and a KVO-like notification system. The notifications can map cleanly to UITableView updates, and there's no extra diffing calculations involved. Of course, this method won't work if your source array needs to be modified by code you don't control.

I would favor this, even though Swift’s strict typing [and lack of inheritance in struct types] means this class can’t interoperate with regular arrays. (Vs. Objective-C, where you can either subclass NSMutableArray, or even make an unrelated class that walks & quacks like an NSArray.)

This seems likely to have been created by someone already; I wonder if there’s an implementation floating around Github?

—Jens

···

On Mar 7, 2017, at 9:28 AM, Michael Gardner via swift-users <swift-users@swift.org> wrote:


(Jens Alfke) #9

Exactly.

—Jens

···

On Mar 7, 2017, at 8:45 AM, Edward Connell <ewconnell@gmail.com> wrote:

My project is on Linux, so pure Swift.
So you don't think this is an issue of intentional library design, but a recognized problem that hasn't been addressed yet?


(Michael Gardner) #10

The general approach would be to run a diff between your old and new arrays. Something like https://github.com/jflinter/Dwifft could help, though I haven't used it personally.

I’ve implemented something like this in the past. It’s fairly expensive, though; that library does claim to use an optimized algorithm, but the cost is still a lot higher than just posting a notification. (And my own experience of using KVO is that notifications can become significant hot spots in performance, because they happen a lot.)

True, but if your array tends to change in limited ways (say, inserting/removing/changing a single contiguous slice), smart diffing algorithms are essentially linear-time. As long as equality-testing your items is fast and your source array isn't huge, diffing can work well. It's certainly simpler to integrate than the other approach, since it requires fewer changes to the rest of your code.

On the other hand, if the array is expected to change often, more often than you want to redraw the GUI, it could make sense to ignore the fine-grained changes and just set a timer to trigger after a few hundred ms, which would then compare the old and new arrays this way and apply a minimal update to the view.

Good idea. Coalescing UI updates is a really useful technique in general.

Another approach is to build a wrapper around your source array with limited modification methods and a KVO-like notification system. The notifications can map cleanly to UITableView updates, and there's no extra diffing calculations involved. Of course, this method won't work if your source array needs to be modified by code you don't control.

I would favor this, even though Swift’s strict typing [and lack of inheritance in struct types] means this class can’t interoperate with regular arrays. (Vs. Objective-C, where you can either subclass NSMutableArray, or even make an unrelated class that walks & quacks like an NSArray.)

This seems likely to have been created by someone already; I wonder if there’s an implementation floating around Github?

I couldn't find one when I was working on a project that needed this a while ago, so I wrote my own. But it had some assumptions specific to that project, and I'm not sure how much work it would take to get it ready for general use. In any case I don't have time at the moment to do anything with it, unfortunately.

https://github.com/lorentey/GlueKit looks promising, though it's in alpha.

···

On Mar 7, 2017, at 10:14, Jens Alfke <jens@mooseyard.com> wrote:

On Mar 7, 2017, at 9:28 AM, Michael Gardner via swift-users <swift-users@swift.org> wrote: