NIB files (or XIB files)

So, finally I got the hang of NIB files. I can now develop simple app either without the interface builder (pure code) or with interface builder (with NIB files).

I had always thought that a NIB file was always associated to a UIViewController. This was because when you create UIViewController, there is an option whether you want to create a NIB file for it or not. If you choose to create the associated NIB file, then the file owner of the NIB file will be set to the UIViewController class.

That was until I found this sample code from Apple: http://developer.apple.com/library/ios/#samplecode/Scrolling/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008023

In that sample code, the class of the file owner is UIApplication. It turns out that you can actually develop your app from scratch using the interface builder only (well, almost). You connect the NIB file (the main NIB file) to your application by setting the key "main NIB file base name" in your plist file to the value of your NIB file name (without the XIB extension). Contrast this with the practice of calling [UIViewController alloc] initWithNibFile] when you create a NIB file for a UIViewController.

Just remember to always set the file owner of your NIB file!

Cleaning up recorded URLs on Preview, QuickTime, etc.

There are times when I watched some dirty movies on Quicktime Mac or clicked on file with embarrassing name to show on Preview. Then the names of those files will be recorded by quicktime and preview, and when I click and hold on the preview icon on the tray, those embarrasing names will show up. After wading thru the Mac file system I finally found what I should delete to remove those names:

Go to /Users//Library/Preferences

In that folder, delete the file com.apple.


NB: Mac OS X Lion.

Objective C Memory Management

I found two concise but complete references online:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/Articles/MemoryMgmt.html
http://interfacelab.com/objective-c-memory-management-for-lazy-people/
http://www.raywenderlich.com/2657/memory-management-in-objective-c-tutorial

I will summarize them here to reinforce my understanding:

  1. If you do alloc + init or new (which is basically just a shortcut for alloc + init), you must subsequently call release.
  2. After you call release, you should set the var name to nil. So: [someVar release], and then someVar = nil; This is considered good practice (at least by Ray Wenderlich), because sending message to a nil var does nothing, while sending message to a deallocated var causes EXC_BAD_ACCESS.
  3. If you get a var from framework methods, then there's this convention:
    • If the method name begins with init or copy, the object returned will have a retain count of 1, and no autorelease pending. In other words, you own that object and have to release it when you’re done.
    • If the method name begins with anything else, the object returned will have a retain count of 1, and an autorelease pending. In other words, you can use the object right now, but if you want to use it later you have to retain the object.
  4. More about property, here's a snapshot of The Elements sample code:

    // Set up the portraitWindow and content view
    UIWindow *localPortraitWindow;
    localPortraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.portraitWindow = localPortraitWindow;

    // the localPortraitWindow data is now retained by the application delegate
    // so we can release the local variable
    [localPortraitWindow release];

    Lesson: when you retain a property, you increment its ref count. So you need to release accordingly.
  5. Do this:
    -(NSImage *)getAnImage {

    return [[[NSImage alloc] initWithContentsOfFile:@"/tmp/youownthis.jpg"] autorelease];

    }
    Instead of this:
    -(NSImage *)getAnImage {

    return [[NSImage alloc] initWithContentsOfFile:@"/tmp/youownthis.jpg"];

    }
    The caller will then have to retain the returned object, and subsequently release it.
Now, on the topic of XCode profile -> leaks tool. I made a curious discovery. I build a skeleton table view app, just a navigation controller and a root view controller. Without any string occupying any table cell. And then I ran the profiler with leaks template. I randomly clicked on the table, and I pulled the table up and release it and pull it down and release it and I did it multiple times. And it red bold lines showed up! UIKit framework is leaking memory!

Even the official The Elements sample code from Apple website is leaking memory when tested this way.

Nifty Mac commands

Some nifty commands that I use often on other platforms but I miss on Mac. After googling around, I found the Mac equivalents.

Showing the desktop: Cmd+Option and then click on desktop.

Taking snapshot:

  • Command-Shift-3: Take a screenshot of the screen, and save it as a file on the desktop
  • Command-Shift-4, then select an area: Take a screenshot of an area and save it as a file on the desktop
  • Command-Shift-4, then space, then click a window: Take a screenshot of a window and save it as a file on the desktop
  • Command-Control-Shift-3: Take a screenshot of the screen, and save it to the clipboard
  • Command-Control-Shift-4, then select an area: Take a screenshot of an area and save it to the clipboard
  • Command-Control-Shift-4, then space, then click a window: Take a screenshot of a window and save it to the clipboard 
Pre compiled binary for the famous wget Linux util:

https://techtach.s3.amazonaws.com/files/wget

I will keep this list updated.

Java Home on Mac

The shortest symlink to Java home (pointing to where the JDK is installed) is:

/Library/Java/Home

To set the JAVA_HOME env var:

export JAVA_HOME=/Library/Java/Home

But that only applies for the current session. To persist it, add it as entry in ~/.profile. Check that it's set:

echo $JAVA_HOME

Install Apache, PHP and MySQL on Mac OS Lion

I found this link, but it is for Snow Leopard, and I found the first part did not apply to me: in Lion, to enable Apache you must go to System Preference -> Sharing -> Web Sharing.
Enable web sharing, which will enable Apache, and you can also see there the IP to access your computer (I found out that 127.0.0.1 or localhost did not work).

And the rest, just follow the instruction there. I copy here:

PHP

In /etc/apache2/httpd.conf, uncomment this line:

LoadModule php5_module libexec/apache2/libphp5.so

Restart Apache

sudo apachectl restart

Fix a warning appearing in phpinfo()

Create /etc/php.ini and make it writable

cd /etc
sudo cp php.ini.default php.ini
sudo chmod 666 php.ini

In php.ini, find this line:

;date.timezone =

Uncomment it and insert your time zone (http://php.net/manual/en/timezones.php)

date.timezone =America/Vancouver

Restart Apache

sudo apachectl restart

MySQL

Download the MySQL package for Mac OS X.5 (32 or 64 bits depending on your machine)
Install everything in the package in this order: mysql, the startup item, the preference pane.
Start MySQL in the preference pane.
Test it's working:

/usr/local/mysql/bin/mysql

Fix mysql.sock location in php.ini

In /etc/php.ini, replace the three occurences of /var/mysql/mysql.sock by /tmp/mysql.sock

pdo_mysql.default_socket=/tmp/mysql.sock
mysql.default_socket = /tmp/mysql.sock
mysqli.default_socket = /tmp/mysql.sock

Restart Apache

sudo apachectl restart

Extra
Activate PHP short tags

In /etc/php.ini, under Language Options, change

short_open_tag = Off

to

short_open_tag = On

Restart Apache

sudo apachectl restart