AppleScriptObjC in Xcode Part 5 - Converting ObjC to ASOC

Translating Objective-C into AppleScriptObjC
To truly utilize AppleScriptObjC we need to understand some Objective-C and how to read the documentation. During this tutorial we will look at similar code in both languages to gain a better understanding of how to implement Objective-C methods in AppleScriptObjC.

UI Elements
Since we are using AppleScriptObjC to build applications we will start with something we all use; text fields.

If you type NSTextField in your Xcode document, hold down the option key and double-click. A small window pops up with some information about this NSTextField. Click the “book symbol” at the top right of this window and the Documentation window will open up to the NSTextField class reference. This is an easy way to get to documentation quickly and search on a specific item. You can also open the documentation from the Help menu.

Popup Information

If you do not have the documentation open and viewing the NSTextField’s class reference, do that now. Make sure you can see the “Table of Contents” on the left hand side. If not, click on the words “Table of Contents” near the top and it will open.

Table of Contents

Toggle open the “Instance Methods” under “TOC”
Here is a list of all the instance methods for NSTextField. Notice that there are no class methods for NSTextField. The reason for this is all of your applications’ NSTextField’s are instantiated when your application is launched.

NSTextField’s Instance Methods

Background and Text Color
There is a lot we can do with an NSTextField but for now we are going to change the background and text colors. Notice that we have “backgroundColor” and “setBackgroundColor:”, “textColor” and “setTextColor:.” These are called setters and getters and they conform to key-value coding naming conventions. The “set” versions are for setting the value and the others are for getting the value.

setTextColor Method
If the “Instances Methods” under “TOC” is not open click the disclosure triangle. Now click on the “setTextColor:” method.

setTextColor

- (void)setTextColor:(NSColor *)aColor
So, what does that mean? We’ll go through it a piece at a time.

“-” means that this is an instance method and requires an instance of the class to use this method. It will make more sense when we deal with classes that have both instance and class methods. Class methods have a “+” instead.

“(void)” means that this method does not return a value to the calling code. Some methods return values but this one does not.

“setTextColor:” is the name of the method and the colon means it takes a parameter.

“(NSColor *)” is the required “type” for this parameter. Types or Kind are what the object or class is. For instance, you will get an error if you try to send an NSString instead of an NSColor. The “*” means that this is a pointer to a place in memory and not the value itself. It is referred to as “pass by reference.” The other option is to “pass by value.” Don’t worry too much about pointers right now.

“aColor” is the variable holding the NSColor.

How do we use it?
Create a property for our text field called “textField.”
We will cover NSColor soon.

In Objective-C

In AppleScriptObjC


tell class "NSColor" of current application
	set blueColor to its blueColor()
end tell

textField's setTextColor_(blueColor)

What is happening here?
We are telling the NSColor class to execute its blueColor() method and return the NSColor object to the blueColor variable. We then tell the textField’s method “setTextColor_()” to execute its code with our blueColor as its parameter.

Look at it this way. In AppleScript we could do something very similar using a script object.


script textField
	on setTextColor(theColor)
		color me theColor
	end setTextColor
end script

set blueColor to {0, 0, 65535}
textField's setTextColor(blueColor)

Creating an NSColor
Click on the NSColor inside the method and the documentation will switch to the NSColor Class Reference.

NSColor Link

Toggle open “Tasks” inside the “Table of Contents” and click on “Creating an NSColor with Preset Components.”

Toggle Presets

NSColor Preset Colors
As you can see, all of these have a “+” next to their name meaning they are class methods.
Click on “blueColor.”

Color Presets

Blue Color Preset

blueColor

Here the “(NSColor *)” at the beginning of the line says that the return value is a pointer to an NSColor object. Again, don’t worry right now about pointers, just realize that what you get back after calling this method is a blue color of type NSColor.

Setting the Background Color
Setting the background color will involve the same procedure but this time we will use a custom color using NSColor’s “colorWithCalibratedRed:green:blue:alpha:” method. All of the parameters are expecting a type of CGFloat. If you click on that you will see that it is just a typdef of float for 32 bit and double for 64 bit. What this means to us is that we need to provide a decimal number. Notice also that the values must be between 0.0 and 1.0.

CalibratedColorMethod

I am using the Digital Color Meter, found in /Applications/Utilities/ folder, to discover a particular rgb color. I chose the 8 Bit representation but it is based on a range from 0 to 255. To convert these values to values between 0.0 and 1.0, we divide the number by 255.

Digital Color Meter

Objective-C Method
One of the things I really love about Objective-C is “keyword:value” parameters. There is no confusion about what the method is wanting from you. Lining up the “:” is another Objective-C convention and really makes reading the code easier.

Now, I am giving something away in this code snippet. We will need to use NStextField’s “setDrawsBackground” method to see our change.

AppleScriptObjC Method
Here is the AppleScriptObjC way to write the Objective-C code above. Is this starting to make sense?


tell class "NSColor" of current application
	set blueColor to its blueColor()
	set backgroundColor to its colorWithCalibratedRed_green_blue_alpha_((243.0 / 255.0), (120.0 / 255.0), (31.0 / 255.0), 1)
end tell

textField's setTextColor_(blueColor)
textField's setBackgroundColor_(backgroundColor)
textField's setDrawsBackground_(true)

How did we know to use “setDrawsBackground:”
How did we know that we needed to use the additional method? Well, I didn’t. This is the first time I have set the background color of a text field. When it didn’t work, I went back to the documentation to see if I had missed something. I noticed “setDrawsBackground:” in the See Also section.

setDrawsBackground

Click on “setDrawsBackground:” and let’s see what it says.

[/center]

setDrawsBackground Method

This method must go after the “setBackgroundColor:” method for it to draw the new color.

Final Code
After all that work this is all the code for the project. After all, it doesn’t do much.


script TextFieldsAppDelegate
	-- Inheritance
	property parent : class "NSObject"
	
	-- IBOutlets
	property textField : missing value
	
	-- IBActions ( button clicks )	
	on changeTextColor_(sender)
		tell class "NSColor" of current application
			set blueColor to its blueColor()
			set backgroundColor to its colorWithCalibratedRed_green_blue_alpha_((243.0 / 255.0), (120.0 / 255.0), (31.0 / 255.0), 1)
		end tell
		
		textField's setTextColor_(blueColor)
		textField's setBackgroundColor_(backgroundColor)
		textField's setDrawsBackground_(true)
	end changeTextColor_
	
end script

To Test it Out
Add this code to a new project but remember to change the script’s name from “TextFieldsAppDelegate” to what you named your project. Add a text field and a button to your layout, hook them up and build and run.

Remember, there is a GUI Building Video that demonstrates how to make connections in IB if you need a refresher.

Reading the documentation took me awhile to understand so I hope this helps.

Until next time, happy coding!

Yet another great tutorial from you Craig !

Keep up the good work, it’s really awesome that you contribute for everyone who is lost in ASOC :slight_smile:

You are very welcome.

Are you ready for more advanced techniques or should I spend some more time on basics?

This one was very helpful for me. How about one that does return a value? I’m trying to figure out createSnapshotImage from class QCView.

I’d like to see a tutorial on how to control other applications from your project–example:

Tell application “iTunes”
play next track
end tell

How would you do something like that in the new AppleScriptObjectiveC language? This used to be that easy to do.

It still is. You only need to hook that code to a button.

But, what (or how) do you surround it with the new handler code? I’m still not good with all that language. Do you have a quick example of what it would look like in the code somewhere?

Have you gone through the other tutorials? If not, they will help a lot.

Connect this to a button.

on playNextTrack_(sender)
tell application “iTunes”
play (next track)
end tell
end playNextTrack_

Hi Craig, great tutorial, but this was needed after or in Part 1. Logic is you need to do the tutorials previous to understand the next, 2 was deep end, drowning (still am table view wise), and I would have loved this but tutorial number ‘5’ says “fat chance if you haven’t done 1-4, don’t bother looking”. Perhaps my fault for not ‘jumping ahead’ when you told me to do the rest. :confused:

There is now a comment at the beginning of tutorial #1 suggesting they read this one first.

Thank you!

If your thinking of a next one I would suggest a simple tutorial on help files, not everything, but enough to find out the rest yourself, same with saving preferences, I know there are quite a few methods for plists and another for user defaults but I only have the ability to use delimited text files. I don’t need any of this anymore until I’ve added every user interaction to Dialog Maker but many people would like to see a tutorial on it I think.

I tried this program and almost every thing worked (i.e., when I typed something into the text box and hit the button, the color of the text changed to blue), but the background color did not work. I noticed a slight change in the text field box so I suspect the background color was changed, but the “textField’s setDrawsBackground_(true)” statement did not. Is there something else that I need to do? By the way, I’m using OS X 10.6.2, Xcode 3.2 (64 bit), and Interface Builder 3.2 (732).

Carl

Model: iMac
AppleScript: 2.1.1
Browser: Firefox 3.5.5
Operating System: Mac OS X (10.6)

I can confirm that this is not working on my machine with AppleScriptObjC or Objective-C. It still works on Leopard though. Others are saying it is still working on their machine running Snow Leopard so I am not sure what the specific issue is.

I just checked this out. If you hit enter after you hit your button, the colour changes in the background.

Could it be something about finished editing?

Ah, Found the problem.

On a hunch, I suspected that if the TextField is set to draw background in IB. That it may interfere with the code to tell it to do so… why I thought this who knows…

But when I un-check the ‘Draws background’ in IB.

All worked as expected.

*edit

If you take out the ‘textField’s setDrawsBackground_(true)’ and check the 'Draws background in IB.
It does not work.
So the bug is in 'Draws background in IB.
It will override the code ‘textField’s setDrawsBackground_(true)’ .
And not complete on its own, until enter is hit.

Thanks Mark!

I could have swore I had tried that but I guess not.

Hope you had a wonderful Christmas!

Craig

I did, thanks, hope you had a good one, And have a happy New year…

I think the problem is that it won’t draw the background while there is uncommitted editing.