Determining the Class of an Object

Hi All,
I’m trying to verify that I’m doing all of my coercions properly, but I’ve run into a problem. “class of x” more often than not gives me a “Can’t get the class of” error. What is the applescriptobjc version of this? I seem to remember seeing this somewhere. In fact, I believe that the advice was that this would be one of my most used debugging tools, but at that point in my research I had no idea what the article was talking about. I tried to find the article again, and tried the documentation but no luck. Any help would be appreciated.

Try the cocoa method: x’s |class|()

Ric

Thanks Ric! I had tried that but I wasn’t getting what I was expecting. This:

set x to "some text"
log x's |class|()

returns NSObject where I was expecting “string” or “text”. Is that because x is not an an ASObjC instance? I’m just trying to figure out where I need coercion, and was hoping to use this to determine if x were an “NSString” or a “string”. Can I assume that if I get NSObject, that the variable has been coerced into an applescript data type?

I think so. If it’s not a brdgeable class such as text, a number, a boolean, a list or a record, you will get NSAppleEventDescriptor.

What you get seems to be dependent on whether the property is an applescript one or a cocoa one, and which way you do the log:

script ClassLoggerAppDelegate
	property parent : class "NSObject"
	property myText : missing value
	property myList : missing value
	
	on applicationWillFinishLaunching_(aNotification)
		set myText to "blah"
		log class of myText
		log myText's |class|()
		
		setMyText_("blah")
		--set myText to current application's NSString's stringWithString_("blah")
		log myText's |class|()
		--log class of myText
		
		set myList to {1, 2}
		log class of myList
		log myList's |class|()
		log myList's objectAtIndex_(1)
		
		setMyList_({1, 2})
		--set myList to (current application's NSArray's arrayWithArray_({1, 2}))
		log myList's objectAtIndex_(1)
		log myList's |class|()
		--log class of myList
	end applicationWillFinishLaunching_
	
end script

Running this gives me this in the log:

If you use the cocoa setter methods like setMyList or setMyText it looks like it creates the cocoa objects and you can then use cocoa methods like, myList’s objectAtIndex_(1). I don’t know if there is anything wrong with doing it this way – it’s much shorter than using “set myText to current application’s NSString’s stringWithString_(“blah”)” or “set myList to (current application’s NSArray’s arrayWithArray_({1, 2}))”. Using those methods gives the same result in the log. The 2 commented out log statements give errors like you mentioned in your first post. The setter methods will only work if you declare the variable as a property first.

After Edit:

After further experimentation, I found that there is a difference between setMyList_({1,2} and set myList to (current application’s NSArray’s arrayWithArray_({1, 2})) – the former, creates a mutable array while the latter produces an immutable one. The same is true for dictionaries, for the property myDict, setMyDict_({x:25}) creates a mutable dictionary.

Ric

Right. The AS list gets converted into a mutable array by the bridge, but calling NSArray’s class method on it returns the non-mutable equivalent.

Thanks for the help. In case anyone is interested, here is what I ended up doing:


	on getClass(x)
		try
			return class of x
		on error
			return x's |class|()
		end try
	end getClass

If x is an applescript class, this will return something like <NSAppleEventDescriptor: ‘list’>. If not, you get the NS class of x. It seems to work OK.

Since this is ASOC world and you are passing it an argument, I suggest this:

on returnClassOf_(objectToTest)
       try
           return class of objectToTest
       on error
           return objectToTest's |class|()
       end try
end returnClassOf_

Good find btw, i’ll use this instead of my clunky version…

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

There’s probably something to be said for not making it Cocoa compatible, though. That way it will fail if you try to call it via Cocoa – which is probably what you want, because calling it via Cocoa is likely to change the class in itself, courtesy of the scripting bridge.

The joys of having a foot in two worlds…

Hmmm… yes, that’s true, didn’t think of that. Think I’ll do some more testing… I’ll report back with if I have anything interesting…

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