Failure to turn a reference for a UI element into a variable

I was really excited to discover that you can turn the reference to a UI element into a variable, like so:

property myButton : null

on awake from nib theObject
	if name of theObject is "myButton" then
		set myButton to theObject
	end if
end awake from nib

This is specially handy because I’m creating an app that has a (invisible) tabview inside another (invisible) tabview inside a tabview. So as you can imagine, the “path” to address any UI element is terribly long.

Unfortunately, it seems impossible to store the reference to a UI item in a variable if the UI item is buried inside the tabview that’s inside the tabview. When I try to do so, I keep getting these kind of error messages when starting up the app:

Are there certain rules for turning references into variables? Is this a bug in XCode? At the moment I’m using XCode 3.0, would 3.1 make any difference?

Okay, to be more specific. So far, it seems to happen when trying to capture the reference to a Tab View Item of a Tab View inside another Tab View.

I don’t know which other factors add to the problem. It will take a while to sort out all the variables that lead to this error. But if someone already knows the answer, please feel free to chime in and save me a lot of work.

I’m not quite sure what your error message means, but I sort of wonder why you’d have multiple hidden UI elements nested. I’ve used some hidden fields occasionally, but never nested tabs. Can you reference a button or simple text field in the first hidden tab? Otherwise I bet it’s just a syntax problem. :-\

Nothing to do with syntax. And the fact that the Tab View was set to “Tabless” was a bit of a red herring too. Here’s a simple way to reproduce the problem:

1 Create new applescript studio project (Applescript Application)
2 Open the NIB file in Interface Builder
3 Drop a Tab View in the default window. You can name it “Parent”
4 Open The Tab View Attributes (Command-1) and set the first tab (called Tab) as the default tab
4 Open the second Tab View Item named “View”
5 Drop a new Tab View inside the “Parent” Tab View. You could name it “Child”
6 Select one of the tabs of the “Child” Tab View, the inspector palette should now mention “Tab View Item”
7 Go to the Tab View Item Applescript Inspector (Command-7), select the script and then tick the “awake from nib” event handler.

If you run this project, it will give an error message. Remember, so far, the only lines of code in the applescript are:

on awake from nib theObject
	(*Add your script here.*)
end awake from nib

The problem, as far as I can see, is that the Tab View Item that triggers the “on awake from nib” handler is inside the Parent’s Tab View Item that is not selected at start up. Change the 4th step to selecting the second tab of the parent Tab View as the default tab and the problem goes away.

Some other UI elements also seem to suffer from this problem, so far I’ve noticed problems with Combo Boxes, but I haven’t tested this out too much.

I hope this is not too confusing. It looks like a bug to me. If so, what is the normal procedure? Can you submit this somewhere?

OK I tried your steps, but did not name the tab items. Project built and ran OK. I am on 10.4.11 with XCode 2.5.
I assume you’re on XCode 3 (since you reference using command-7 not command-9), maybe it’s only a problem with that. ??

I don’t want to be pain, and I hate when people try second guessing my app design motives too, so please take this politely: Again, why do you need 2 invisible tab items nested? From a code perspective it seems like it’s giving you a problem, and if they are hidden from the user, why have nested items? Why not just 6 or 8 invisible text boxes or check boxes etc that store your hidden data but are top level? Maybe that would make it easier to reference them, and visually lay it out too. I mean it seems like you might be making it more complex than it really needs to be.

Naming the tabs wouldn’t have made a difference. It’s clearly a XCode 3.0 problem. I will try and install 3.1.1 later today, see if that makes a difference.

As for the tabs inside tabs question. First of all, I did get my wording a bit wrong, the tabs are not set to invisible, the Tabview is set to “Tabless”. That gives you a Tabview where the actual tabs aren’t visible. Switching between the different tabs happens with a pop-up menu that I connected in IB. None of this is really that exceptional and it works great.

Anyway, to answer you question. I am creating a little app that does lots of things with layers in Adobe Illustrator.

One of them is changing the visibility of layers based on certain search results: You Show or Hide layers based on their Name/Locked/Colour. Depending on which search-term you use, the interface has to change. When searching on Name, you need to see a textfield, when searching for locked/unlocked layers, you need to see a button with a lock icon on it…

That’s where all the tabs come in. Having three interfaces for three different types of searches sitting on top of each other and programmatically changing their visibility would be a very bad way of getting around this whole situation I think. I remember reading in one of the Apple guidelines that it’s best to use Tabviews for these type of scenarios.

I’ve only given a partial explanation of what the app does. It actually works quite well, apart from this bug that’s been plaguing me the last few weeks. I think I know what to do now to get around it.

Thanks for the support.

Browser: Safari 525.18
Operating System: Mac OS X (10.5)

I’ve come across this same problem, as have others. We discussed it a fair bit here:
http://bbs.macscripter.net/viewtopic.php?id=25609

Basically, XCode/AppleScript seems to fail to reference any object inside a tab view item if it is not the current tab view item.

Tom
BareFeet
http://www.tandb.com.au/applescript/

Thanks, that helps a lot. I’ll have a good read through that thread later on. At first glance, it looks like I wont be able to catch references in variables at all then. Ugh, this is going to diminish the readability of my script quite a bit (as if it isn’t ugly enough at the moment):confused:

Just out of curiosity. How long has this bug been around?

I came across the same disappointment, but worked around it. I just had to make sure that I only tried to access objects while the tab view item containing them was current (ie active, selected).

I don’t know. I first reported it in the discussion back in July:
http://bbs.macscripter.net/viewtopic.php?pid=102236#p102236

I haven’t seen mention of it prior to that.

Tom
BareFeet
http://www.tandb.com.au/applescript/

Thanks, it looks like an XCode 3.xx problem since SuperMacGuy couldn’t reproduce it in 2.5.

In fact, 3.xx is still very much a work in progress it seems. I upgraded to 3.1.1 yesterday to see if it helps. Disappointingly, not only does it not solve this problem, it has a very buggy applescript editor too boot.

Agreed. At home I have 3.11 and when it compiles sometimes the color just goes all black. Text is often not aligned properly. Plus the Code Folding gets totally fubar’d on really long scripts. That’s a feature I love but too bad its busted somewhat.

I haven’t tried this but since the tabs go through the ‘awake from nib’ handler when they are activated, it seems to me that you could probably write some code to programatically cycle through the tabs at program launch. Here’s what I would try…

  1. uncheck the button “Visible at Launch” for your main window in IB. This means that your program’s window will not show automatically at launch. The advantage of this will be that you can do some things with your window (such as cycle through the tabs) and the user will not see what you’re doing.
  2. use the “on launched” handler of the application to:
    a. get the count of the tabs
    b. use a repeat loop based on the count and programatically activate each tab
  3. Then perform any other program initialization stuff that you need. Since the tabs were activated prior to this your references to the tab’s objects in the ‘awake from nib’ handler should be good.
  4. show the main window of your program with the following “show window 1”

I hope this helps!

I’m not too sure how this would work. I can sort of see the thinking, but it seems to defeat the object, which is to capture the reference to a UI element in a variable at startup.

The “on launched” handler always happens after the “on awake from nib” handler. So by the time you cycle through the tabs inside the “on launched” handler, the chance to use the “on awake from nib” handler to capture references is gone.

In plain human language, I don’t want to address the UI elements in my script by their full name. I want them to leave a shortcut to themselves behind (in the form of a variable in my script) at the moment of startup. The only handler I can think of where this is possible is the “on awake from nib” handler.

This is a wrong assumption. The awake from nib handler will be called whenever one of the tab view items is activated. It isn’t only called when the program first launches. To test this put log messages in the handler. Then start your program and move through the tabs. You will see that the handler will log the messages for each tab as you choose them… thus verifying that the awake from nib handler does get called when a tab view item is activated.

As such I still think this method would work.

Unfortunately, in this case, due to what I presume is a bug in XCode 3.xx, the on awake from nib handler always get called at startup, regardless of which tab view item is selected. I know because I did a test by logging the handlers as they were called.

Well you don’t have to believe me if you don’t want to but I’ll explain it one more time… yes that handler gets called when the program starts. I assume you have different if/else if statements in that handler for each tab view item. As was explained originally, only the front tab awakes from nib during program launch… the others don’t. But as I explained when you activate the other tabs after program launch then the awake from nib handler is called again. This time it will go into the appropriate if statement section in the awake from nib handler such that you can then set a variable to theObject as you are wanting to do.

Bottom line is just try what I’m telling you and see if it works. I haven’t tried it but it should work.

Who said I didn’t try?:slight_smile:

Theoratically, yes. But the point I’m trying to make here is that XCode 3 doesn’t do that. There seems to be a bug which means that the on awake from nib handler of some UI elements inside a non-selected tab view item get called at startup, even though it should wait until the tab view item gets selected. The result is that the on awake from nib handler in the script gets a call from a non-existing UI element and returns an error message. The on launched handler only gets called after all this has happened, so it can’t make a difference.

Believe me, I’ve been testing this for the last week, I may have answered you earlier post quite quickly, but I did a quick try-out and it doesn’t work (but I agree that it should) I have put log statements inside all the different handlers to see what happens when the program runs. Bottom line is, some handlers get called at the wrong time.

Ok then.

The only thing I can think of that would make the handlers get called in an unusual order is if you have your windows set in IB to automatically open themselves. That does mess with the order in which the handlers are called. If that’s your problem then you have to uncheck that box for each window and open the windows programatically yourself as I showed you earlier. If that’s not the problem then I’m not sure what is.

Are you talking about the “Visible at Launch” option for the window?

If that’s the one you’re talking about, I’ve already tried that. Doesn’t make a difference.

Like I said earlier, I’m pretty convinced it’s a bug in xcode 3. Basically, it seems that under certain circumstances, UI elements will call the on awake from nib handler before they’re actually loaded from the nib.

I’m still a little skeptical about that statement. Could you post some code or a project that could be downloaded demonstrating this? I’m using xcode 3 and haven’t seen what you are describing.