Assorted, Scattered Objective-C Notes as compared to C#

A outlet is like a pre-known property that can be bound
(ie: drag destination object to origin object and assign to the outlet (property) nextKeyView)
is like
[myObject methodToCall:parameters];
int i = myObject.assignValue;
is like
int i = [myObject assignValue];
is like
[[form window].makeKeyAndOrderFront:target];
object myObject();
is like
id myObject;
string myString;
is like
NSString *mystring;
Defining an instance method:
private string myMethod();
is like
– (NSString *)myMethod;
Defining a class method:
public DateTime myMethod();
is like
+ (NSDate *)myMethod;
private float convertAmountbyRate(float amt, float rate)
is like
– (float)convertAmount:(float)amt byRate:(float)rate;
convert.convertAmountbyRate(1.0, 2.3);
is like
[convert convertAmount:1.0 byRate 2.3];
public interface myInterface : myClass {…}
is like
@interface myInterface : NSObject {…} @end

Assorted, Scattered JavaScript Notes

Boolean(value) method returns false for falsey values, true for truthy values
falsy: false, null, undefined, “”, 0, NaN
truthy: everything else: “0”, “false”

+ as a leading operator converts a string to a number: +”42″ = 42. Same as Number(“42”) = 42), parseInt(“42”, 10) = 42
+”3″ + (+”4″) = 7

=== !== do not do type coercion, slightly faster

if (a) {
return a.member;
} else {
return a;
can be written as
return a && a.member;
if the first operand is truthy, return the second operand, else, return the first

but for || if the first operand is truthy, return the first operand, else, return the second:
var last = input || somethingElse;
so if input is truthy, then last is input, otherwise set last to somethingElse

you can label loops and break them by label:
myloop: for (whatever)
break myloop;

//other loop
for (var name in object) {
if (object.hasOwnProperty(name))        //avoids looking at objects we might have inherited from
name //is the current member
object[name] //is the current member value

//multiple conditions in switch statements
switch(something) {
case “;”;
case “,”;
case “.”;

//exceptions and object literals
throw new Error(myReason);

throw {         //create an “object literal” creates an exception object on the fly
name: myexceptionName,
message: reason

//object literals
an object literal is wrapped in { }
a name can be a names or a value
values are any type
: seperates names and values
, seperates pairs
object literals can be used anywhere a value can appear
var myObject = {name: “Jack”, ‘goto’: ‘Jail’, grade: ‘A’, level: 3};
var myName =;     //extracts “Jack”
var destination = myObject[‘goto’];     //extracts “Jail”
var destination = myObject[“name”];     //extracts “Jack”
var destination = myObject[goto];       //returns an error because goto is a reserved word, hence the other notation

//maker function
function maker (name, grade)
var it = {}; //makes a new empty object, good shorthand = name;
it.grade = grade;
return it;
var myObject = maker(“Jack”, “A”);

//an object with an object as a member, shorthanded
var myObject = {
name: “jack”,
grade: “a”,
clothes: {
pants: ‘blue’,
shirt: ‘red’

//if you have more than a couple parameters in a function, why not make them an object?
function myfunc(pa, pb, pc, pd, pe, pf)
myfunc(pa, pb, pc, pd, pe, pf)
function myfunc(specs)
myfunc({ pa: ‘1’, pc: ‘3’, pb:’2′, … })

** note: variables that are not var’ed become implicitly global

//specify object’s prototype on creation? linkage — doesn’t really exist
var newObject = object(otherObject);
//gives it a secret pointer to otherObject, but the secret pointer is used for retrieving only NOT storing
//object (lowercase) is a method that Yahoo made up
//different than

var newObject = Object() which equals: var newObject = object(Object.prototype)

delete myObject[memberName];    //deletes (sets to undefined) a member of an object

myArray[myArray.length] = 3     //appends to end of array (same as pop)

var myArray[]   //creates a new array?

Resolving missing dependencies when building a NeXTStep/OpenStep App

If you’ve played around with NextStep/OpenStep trying to build a sample app — say, so you can find out how much OS X/the iPhone is like those sweet black machines of yesteryear — you might have an error like this one, when attempting to build a sample app you’ve created: AppKit.h not found (or any one of the other billion header files that are missing)
This may mean an incomplete installation of the Developer tools. Here’s what to do:

  • From the Developer CD, open the NextCD folder and then Packages.
  • From the Services menu, use Open Sesame to open the Package as Root
  • Install the Package to its default file locations.

NextStep: Open as Root
Now, in your project in PB, you may need to tell the compiler where to find those libraries.

  • From the Tools menu, open the Inspector and look at the Build Attributes.
  • Under Framework Search Order, Set… a new path to where those files just got installed: /NextLibrary/Frameworks
  • Do the same for Header Search Order, but use /NextDeveloper/Headers

Project Builder: Framework Search
Now you should be able to Build in Project Builder! Note that PB doesn’t have a “Build and Go” that I can find, so once you build, you need to use Workspace Manager to find your newly made .app and double click it to test it out.

Automating an Apple TV with Cron

Copy and enable Cron from 10.4.
Schedule Cron jobs using crontab at the command line. Use Ctrl+D to exit crontab once all your jobs are created.
Restart the AppleTV at 8:10am every morning (say, to re-establish network connections with computers that were off during the night):
10 8 * * * sudo /sbin/reboot
Shutdown the AppleTV at 1:00am every morning:
0 1 * * * sudo /sbin/shutdown -h now
You’ll need to enable the frontrow account to use sudo without a password.

Hacking Time Machine

This past week I was the unfortunate victim of hard drive failure on my 1stgen Macbook Pro. After looking through my local NAS and finding that my most recent backup was done in April, I kicked myself a little bit. I have everything available to me to do regular backups, but like most people I am just too lazy. I decided that I wanted to try and get Time Machine to perform backups to a network share instead of a local drive. A simple terminal command was all that was needed to make my network volumes show up in Time Machine.
defaults write TMShowUnsupportedNetworkVolumes 1
Just changing this preference has worked for many other people, but I get the a message from Time Machine stating “The backup disk image could not be created.” Nothing on google or the apple support forums seems to give any good info on the situation.
Any ideas?

Bridging networks with WDS

WDS stands for wireless distribution system. The system was intended to allow a wireless network to span accross multiple access points without needing a wired backbone between them. This can be useful when you cannot physically connect the access points with a cable, but note that a hardwired backbone is preferred as WDS will cut your available wireless throughput in half. For more information on WDS check out wikipedia.
Editor’s note: If you can connect your two Linksys routers via a cable, check out this post for some tips.
My setup is using two Linksys WRT54G v2 routers running the third party Tomato firmware. My initial home network was setup using version 1.19 of the firmware and I haven’t seen any reasons to upgrade it right now. The new router that I am adding using WDS was recently bought at a swap meet for $10 and is running version 1.21 of the firmware. The reccomended setup for using WDS is available in the FAQ on the tomato website and is what I based my setup on.
Main router setup:
WAN: Setup as required by your ISP.
LAN: Pick an IP address ending in .1 for your router (usually and ensure the DHCP server is turned on.
Wireless Setup:

  • Wireless Setup: Access point + WDS (If you are only joining two wired networks you can set this to WDS only.)
  • SSID: [Pick one for your network.]
  • Channel: 3 (I tried using channel 10 first because that’s what my original wireless setup and was unable to get WDS to work. I also tried using channel 1 and couldn’t get that to work either.)
  • Wireless mode: Mixed. (I also tried using G only when I had the channel set to 1. This is supposed to work but I couldn’t get it to.)
  • Security: WPA Personal (WPA2 Personal will not work and neither will WPA / WPA2 Personal.)
  • Encryption: AES (I tried AES / TKIP and it would only work if it was only AES.)
  • Shared Key: [Pick one for your network]
  • WDS: Link with [MAC address of your 2nd router.] (There is also an option for Automatic / Lazy which I was not able to get to work.)

Second Router Setup:
WAN Setup: Disabled.
LAN Setup: Manually assign an IP to this router. Normally ending in .2 (Like Make sure that this IP address is not available to be assigned by DHCP from the main router.)
DHCP: Ensure that this is OFF!
Wireless Setup:

  • Wireless Setup: Access Point + WDS (This could also be only WDS if you want only one access point or if you are joining two wired networks together.)
  • SSID: [The same as the main router’s SSID]
  • Channel: 3 (Again this has to be the same as your other router.)
  • Wireless mode: Mixed.
  • Security: WPA Personal
  • Encryption: AES
  • Shared Key: [The same as your main router.]
  • WDS: Link with [MAC address of your main router.]

I also found that I had to enable STP in the Advanced > Routing options page. All other options were left at their default settings with the exception that I also have QoS setup in a manner similar to this post on the main router. You can check to see the status of whether or not your routers are communicating via WDS by looking at the Status > Device List page to see if you have a listing for WDS on both routers.
You an add as many additional routers as you would like by adding their MAC addresses to the “Link with” field of your wireless setup. You should avoid creating routing loops when adding additional routers and setup them up in a star, line, or tree topography. If you absolutely have to setup a ring topography for redundancy I recomend finding a way to join the routers together using a wired configuration and doing some research on STP and RIP.
Author’s Note: WDS is not officially part of any 802.11 standard and is not recognized by the Wifi Alliance. Many different products implement the feature differently and may be incompatible with other devices that also support WDS. The only way to be sure that your setup will work is to follow guides like this one of people who have tested known configurations. Your milage will vary. Good luck!

Using PHP and a Shell Script to Restart an AppleTV remotely — via the web

As a follow up to my previous post, here’s how to do the same thing, but from a web browser (say, on your iPhone) — it assumes you’ve already written a shell script, as discussed earlier.

  • Configure Apache to run PHP on your Mac (these instructions are for Leopard, but similar ones are out there for Tiger)
  • Configure Apache to run as your own user, instead of the WWW user — a serious security risk. Only do this on an internal network! The WWW user won’t have adequate permissions to do what we need to.
  • Put this .php page in your /Library/WebServer/Documents/ folder as RestartMedia.php — you’ll need to supply your own image file in the same path as well.
  • Visit http://yourcomputer.local/RestartMedia.php from a browser. Clicking on the text or image will execute a shell script located at: /Applications/Automation/

Obviously you can customize this at will, including file locations. This was just a quick hack that does the job for me — and the webpage is optimized for Mobile Safari.

Using AppleScript and a Shell Script to Restart an AppleTV remotely

Both my media serving devices (a NAS, and a Mac Mini) are using TwonkyVision Media Server to share media using uPnP. It works great, but as I mentioned earlier, I needed a script to make it start back up in the morning.
Unfortunately, I’ve found that my AppleTV freaks out a bit when this happens, and as a result, needs its own reboot. Restarting the Finder helps, but streaming still gets weird, so a full, daily reboot is in order. Using the same iCal-alarm-firing-an-AppleScript trick, I updated my Twonky restart script to also tell the AppleTV to restart. But it wasn’t that easy.

  • First of all, you need to exchange keypairs with the AppleTV so that you can login over ssh without a password. If you’re using an older patchstick, the process is a little different, since it may only support ssh1. This wiki page explains the process, and the slight tweak to it for ssh1.
  • Second, you need to set the AppleTV up to allow you to sudo without a password. This is harder than it sounds, and requires modifying the /etc/sudoers file on the AppleTV. The only way I found to do that was to sudo cat /etc/sudoers > ~/sudoers the file (which dumps the contents of one file to another, which you can access more easily), copy it over to my Mac, edit it, copy it back, set the permissions, and sudo mv it back over-top the original. You’ll need to add this line to the bottom of the sudoers file:
    frontrow ALL=(ALL) NOPASSWD: ALL
  • Make sure you change the permissions (chmod 0440) and ownership (chown root:wheel) on your new sudoers before you replace the original, or you’ll screw yourself out of sudo!

To test those things, you could go to Terminal on your Mac and try something like:
ssh -1 frontrow@appletv.local 'sudo ls-l'
(drop the -1 for newer Patchsticks)
If you’ve setup everything right, you shouldn’t get prompted for a password to login OR to get a directory listing. Once that works, the AppleScript is easy and looks like this:
do shell script "ssh -1 frontrow@appletv.local 'sudo reboot' &> /dev/null &"
(drop the -1 for newer Patchsticks)
At some point, I’m also going to attach this to a PHP script (somehow) so I can use Safari on my iPhone to do a reboot from the couch if needed. I’ve only found two other ways to reboot the AppleTV — yanking the power cord, or using the remote to put it in recovery mode. Neither seems as elegant as my solution.