Observing changes in TableView


Gerriet M. Denkmann
 

macOS 12.6

I have an ArrayController which has ContentArray bound to AppDelegate.contentArray
The contentArray contains MutableDictionaries with a key “Flag”, value: boxed BOOL.

And a TableView which has Content bound to ArrayController arrangedObjects.

The TableView (View based) has a TableColumn which has s Button in Table Cell View.
Its Value is bound to: Table Cell View.objectValue.Flag

Everything works fine, but now I want to get notified when the user clicks on some Button in the TableView (and thus changes Flag in some dictionary inside contentArray).

I seem to remember that on can not observe changes inside contentArray.

So I gave the Button a target and action, but this never results in a message sent.

How can I accomplish this?

The best (not very good) I can think of is a timer which every half second checks all dictionaries in contentArray.
Very wasteful indeed.

There surely must be a better way.


Gerriet.


Quincey Morris
 

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@...> wrote:

So I gave the Button a target and action, but this never results in a message sent.

This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn't depend on the cell itself, like the view controller or the app delegate.


Gerriet M. Denkmann
 

On 9 Nov 2017, at 01:36, Quincey Morris <quinceymorris@rivergatesoftware.com> wrote:

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@mdenkmann.de> wrote:

So I gave the Button a target and action, but this never results in a message sent.
This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn’t depend on the cell itself, like the view controller or the app delegate.
It was the app delegate.

I found another solution:
The contentArray contains only a few dictionaries - less than a dozen.
So I decided to observe all of them:

for( NSDictionary *d in self.contentArray )
{
[ d addObserver: self
forKeyPath: kKeyPath // “Flag”
options: 0
context: (__bridge void * _Nullable)(kKeyPath)
];
};

Kind regards,

Gerriet.


Alex Zavatone
 

Gerriet, I am doing the same thing now on iOS.

Here’s what I am doing and am open to better approaches.

Being able to do this requires a special set up where the cell contents are retrieved from a data set based on indexPath.

All my data is in a dictionary that is keyed off of indexPath row and section, so displaying the data is simply a case of getting the proper index and using the section and row to retrieve the correct data from the data source.

I have subclassed UITableViewCell but I don’t think you need to do this. A cell has access to its indexPath, but you can set the indexPath of the clicked/tapped item in another object if you wish.

Once this is done, I send a notification of processTappedCellItem to the tableViewController and it checks the indexPath of what was tapped.

Since everything is keyed off of the item’s indexPath, we know the item for which the button was clicked/tapped.

Does this approach work for you?

I’m using this to manage editable fields in a tableViewController for data entry.

Cheers.
Alex Zavatone

On Nov 8, 2017, at 3:47 AM, Gerriet M. Denkmann <g@mdenkmann.de> wrote:

macOS 12.6

I have an ArrayController which has ContentArray bound to AppDelegate.contentArray
The contentArray contains MutableDictionaries with a key “Flag”, value: boxed BOOL.

And a TableView which has Content bound to ArrayController arrangedObjects.

The TableView (View based) has a TableColumn which has s Button in Table Cell View.
Its Value is bound to: Table Cell View.objectValue.Flag

Everything works fine, but now I want to get notified when the user clicks on some Button in the TableView (and thus changes Flag in some dictionary inside contentArray).

I seem to remember that on can not observe changes inside contentArray.

So I gave the Button a target and action, but this never results in a message sent.

How can I accomplish this?

The best (not very good) I can think of is a timer which every half second checks all dictionaries in contentArray.
Very wasteful indeed.

There surely must be a better way.


Gerriet.




Alex Zavatone
 

Though in concept, I love the idea of KV observers, in practice, I’ve found that they lead to too many crashes.

I’ve switched over to sending notifications and it’s much less to worry about and much less wasted time. FWIW.

Alex Zavatone

On Nov 8, 2017, at 12:48 PM, Gerriet M. Denkmann <g@mdenkmann.de> wrote:


On 9 Nov 2017, at 01:36, Quincey Morris <quinceymorris@rivergatesoftware.com> wrote:

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@mdenkmann.de> wrote:

So I gave the Button a target and action, but this never results in a message sent.
This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn’t depend on the cell itself, like the view controller or the app delegate.
It was the app delegate.

I found another solution:
The contentArray contains only a few dictionaries - less than a dozen.
So I decided to observe all of them:

for( NSDictionary *d in self.contentArray )
{
[ d addObserver: self
forKeyPath: kKeyPath // “Flag”
options: 0
context: (__bridge void * _Nullable)(kKeyPath)
];
};

Kind regards,

Gerriet.






Gerriet M. Denkmann
 

On 9 Nov 2017, at 01:36, Quincey Morris <quinceymorris@rivergatesoftware.com> wrote:

On Nov 8, 2017, at 01:47 , Gerriet M. Denkmann <g@mdenkmann.de> wrote:

So I gave the Button a target and action, but this never results in a message sent.
This ought to work, so I think you should focus on finding out why it isn’t. What are you specifying for the target? It should be something that doesn’t depend on the cell itself, like the view controller or the app delegate.
I just tried it again, and now Xcode told me that: “ Action ‘boxClicked:' sent by 'Check Box' is connected to 'File's Owner,' an invalid target (Objects inside view based table views may only be connected to the table view's delegate.)"

So I made the ‘File’s Owner’ the table view’s delegate and now it works as expected.

Kind regards,

Gerriet.