Problems with receiving notification from table views

Hello,

I have setup a few table views in my interface, and I would like to be made aware by the notification center that a selection has changed in any of them and then act accordingly, but despite a few hours of testing and searching, I have no result. I have this called within the “applicationWillFinishLaunching” routine, and it seems like my selector routine is not being called when I select any row of any table views:

tell current application's NSWorkspace to set theWorkspace to sharedWorkspace()
set theNotificationCenter to theWorkspace's notificationCenter()
tell theNotificationCenter to addObserver_selector_name_object_(me, "tableViewSelectionChanged:", "NSTableViewSelectionDidChangeNotification", missing value)
on tableViewSelectionChanged_(sender)
		log "tableViewSelectionChanged_"
		log sender
		log sender's |title|
end tableViewSelectionChanged_

Anyone got any ideas on why the routine is not being called? Thanks.

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

You’re registering with the wrong notification center – that one is just for workspace changes. Try this:

		set theNotificationCenter to current application's NSNotificationCenter's defaultCenter()
		tell theNotificationCenter to addObserver_selector_name_object_(me, "tableViewSelectionChanged:", "NSTableViewSelectionDidChangeNotification", missing value)

You can also make your script the delegate of the table views and implement on TableViewSelectionDidChange_(notif), and that way not have to use a notification.

Ah, I knew something was off. Thanks.

I also found out that I could bind the table view to the app delegate and select any routine of my choosing, so this solved my problem quite well.

I’ll keep this in mind though if I eventually need something more universal. Thank you very much!

Regards
Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Small update: looks like I’m going to have to go with the notification center solution in the end, because the solution I found only works if the user clicks a row, not if it being cycled through with the keyboard. The “action” seems to be only relating to clicks, not keyboard actions.

I still have two questions: Is it possible to specify only one table view in particular with the object parameter? What does it need? an iboutlet? or a name?

And why is every time I change the selection, the selector gets called twice?

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

Presumably an outlet. What have you tried?

But if you want it for only one table, the delegate is probably a better solution.

Your presumption was correct! Outlet worked fine.

Can I specify different observers for different table views and with different selectors?

And what can delegate do that observers can’t? Or better said, what are the differences? I’m unfamiliar with delegates…

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

You make a script a delegate for one or more tables, and you can have handlers that match he notifications. It’s simpler – no registering for notifications, and you can only make delegates for the tables you’re interested in.

You are familiar with delegates – look at the name of your main script…

Alright, my curiosity is piqued. :slight_smile:

So If I wanted to proceed the delegate way, I assume that I would have to create a new AS class, create a blue cube in IB and connect them, then control-drag the blue cube onto the table views I’d like to control notifications for and select delegate, then within my new class I setup a method that will be activated when the table view’s selection changes, correct?

Which method do I have to subclass? Not “NSTableViewSelectionDidChangeNotification” as it is a constant… Default center maybe? It’s the “when selection changes” part that activates the delegate that is still mystifying me. :confused:

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

I think you’re making this a lot harder than it needs to be. If you have a table called table1, for instance, all that you need to do is add “table1’s setDelegate_(me)” to your applicationWillFinishLaunching method. That sets your AS to be the delegate of table1. Then you can use the methods in the NSTableViewDelegate Protocol Reference to do what you want in response to user actions. For instance, to respond to the user changing the selection in table1 you could add this method to your script:

on tableViewSelectionDidChange_(aNotification)
		log aNotification
	end tableViewSelectionDidChange_

In, this case, I’m just logging what happened, but you could put whatever you want into this method. You don’t need to do anything to call this method, it gets called automatically by the table view when a user changes the selection by clicking on a new place in the table.

Ric

Indeed, sounds simpler. Then could I call from another script the IBoutlet that is bound in the main one and tell it to call the tableViewSelectionDidChange handler from this second script? Something like this I imagine:

MainScriptAppDelegate's tableView1's setDelegate(me)

and then call from my applicationWillFinishLaunching method call this second script to set the delegates? I just want to simplify the main script as much as possible… Or maybe do a connection in IB?

Thanks for the help,
Fred

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

If I’m understanding what you want to do, I don’t think you want to use setDelegate_(me), you want to use setDelegate_(otherAS) (in your main script’s applicationWillFinishLaunching method), where otherAS is a property in your main script that is connected to the blue cube that represents another applescript. If you had two tables, you could have 2 other applescripts, one to handle each table if you wanted, like so:

script TableViewsAppDelegate

	property parent : class "NSObject"
	property table1 : missing value
	property table2 : missing value
	property otherAS1 : missing value
	property otherAS2 : missing value
	
	on applicationWillFinishLaunching_(aNotification)
		table1's setDelegate_(otherAS1)
		table2's setDelegate_(otherAS2)
	end applicationWillFinishLaunching_
	
end script

You would then put the various handlers, like tableViewSelectionDidChange_(aNotification), in the 2 other applescripts to handle the events.

Ric

You don’t need to use code to set a table’s delegate; just control-click on the table in Interface Builder and drag from delegate to the script you want to make the delegate.

This is exactly what I want to do. Thanks to the both of you!

Now, when I log the event, this is what I get:

NSConcreteNotification 0x20184f540 {name = NSTableViewSelectionDidChangeNotification; object = <NSTableView: 0x200820f80>}

from this I know I can call upon the notification’s object, but this <NSTableView: 0x200820f80> is evidently the reference to the object that represents the table view, but how can I distinguish them?

I’ve tried this in my delegate script to compare the object to the reference I have of it as an IBOutlet in my main script:

if (aNotification's object) = (current application's MainAppDelegate's tableView1) then log "success"

and it crashes… I know i’m close. I’ve looked at the definition for the NSTableViewSelectionDidChangeNotification thinking I could get more info out of the object property, and it says this:

Posted after an NSTableView object’s selection changes. The notification object is the table view whose selection changed. This notification does not contain a userInfo dictionary.

does this mean that the object property does not contain any more info beside this object reference?

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

That looks like a reference to a table belonging to a class, not an object. Try cutting out the “current application’s”.

Yes.

Works like a charm. I set up a property in my second script that is connected in IB to the main app delegate blue cube, and this worked perfectly:

if (aNotification's object) = (MainAppDelegate's tableView1) then log "success"

Also, I think I will go the code way for setting up the delegates, because the IB binding way logs a million calls before even having the interface show up. I’ll put it as the last thing in my applicationWillFinishLaunching method.

Thanks a million, I’m learning a lot in these forums. These bindings, delegates, classes… pure genius. Can’t believe how far this can go. And that we couldn’t use this before in ASS was really creating a huge limit in possibilities. i’ve done more in less than 1000 lines of code in my new ASOC version of my app than I did in more than 3000 in the old one. Genius, pure genius. i’m in love… :slight_smile:

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)

The IB connection way – there are no bindings involved – shouldn’t result in any log calls.

Oh? Well, like you said in your previous post about control-clicking and dragging from the table view to the app delegate, that works, but while I still was logging the notification there was a lot of activity in these table views… the setDelegate_ method solved that. I didn’t want things happening when there was no need to.

I was doing the logging, not the app. But still, unwanted activity at the wrong time.

Browser: Safari 531.22.7
Operating System: Mac OS X (10.6)