Auto-synthesized ivar in Objective-C is full of traps

The modern Objective-C 2.0 runtime introduces the feature of property with the backing ivars variable generated automatically.
Sounds like a nice feature but you can easily fall into traps if it is not used properly.
Consider the following code:

@interface Person : NSObject
@property (retain) NSString *name;
@end

Sound nice, but the problem with this code is that the ivar that gets generated by default from this code is simply called ‘name’ and it allows for easy slips with forgetting accessing the ivar directly to be written:

-(void)foo{
   // Direct ivar access bypassing property accessors
   name = [NSString stringWithString:@"John"];
}

Note that the string returned from ‘stringWithString’ is auto-released, it would give all sorts of troubles later, possibly crash as the autoreleased variable is never retained and the synthesized property setter is never called.

As you might see some code from the XCode project template, the code uses a style that attach an underscore character as prefix to the backing ivar name, like following code:

@implementation MyUIViewController
@synthesize window = _window;

I don’t think this is good enough. You can still easily screw up yourself by writing code like:

     // compiler doesn't stop you like this
     _name = [NSString stringWithString:@"John"];

In my opinion, the only complete solution is that the backing ivar is completely hidden from the programmer and the generated name will be decorated internally and be known only the compiler, very much like it works in C#.

In that case, statement like this

      name = [NSString stringWithString:@"John"];

should be translated to the equivalent of the below code. (given the correct scope resolution)

      self.name = [NSString stringWithString:@"John"];

Reference:

Fix missing iOS 5 Documents in XCode 4.2

Just got my shiny new Mac Book Air 13″ inch core i7 and downloaded XCode 4.2 from the AppStore.

When I tried to look up any class reference from the XCode editor, I got a login form inside the document window, and after I entered my Apple ID, it shows:
“You do not have access to this resource based on your membership.”.

It seems ridiculous that I need iOS membership to access documentation as this is not the case previously; and iOS 5.0 has been released for a while now, that means shouldn’t have NDA restriction on the beta documentation.

Magically the problem was fixed by itself when I went to Xcode | Preferences… | Downloads | Documentation and click Check and Install Now.

The download started again. (I swear that I have downloaded the same set of documentation before.)

I am not alone with this problem.
See http://forums.bignerdranch.com/viewtopic.php?f=148&t=3497

iOS recipe : Storing local files in iPhone

Each iPhone iOS application on a device has its own private Documents and tmp directories into which it is permitted to read and write data. Because the location of these directories is different for each application the only way to find the correct path is to ask the iOS for the correct path.

The following code snippet will generate a file path that points to the private document directory private to your iOS app.

NSString *fileName = @"Demo.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfFileName = [documentsDirectory stringByAppendingPathComponent:fileName];

 When executed within the iOS Simulator environment, the path returned will take the form of:
/Users/<user name>/Library/Application Support/iPhone Simulator/<sdk version>/Applications/<app id>/Documents

Where <user name> is the name of the user currently logged into the Mac OS X system on which the simulator is running, <sdk version> is the version of the iOS SDK used to compile the application and <app id> is the unique ID of the app, for example:

06A3AEBA-8C34-476E-937F-A27BDD2E450A

Clearly this references a path on your Mac OS X system so feel free to open up a Finder window and explore the file system sandbox areas for your iOS iPhone applications.

When executed on a physical iPhone device, the path returned by the function call will take the following form:

/var/mobile/Applications/<app id>/Documents

Identifying the Temporary Directory

In addition to the Documents directory, iOS iPhone applications are also provided with a tmp directory for the storage of temporary files. The path to the current application’s temporary directory may be ascertained with a call to the NSTemporaryDirectory C function as follows:

NSString *tmpDir = NSTemporaryDirectory();

Once executed, the string object referenced by tmpDir will contain the path to the temporary directory for the application.

How to fix missing Microsoft’s fonts in iWork

It used to be very frustrating to see the warnings whenever you load documents created by Microsoft Office into Mac OS X iWork.

Kudos to this guy.
Fix missing fonts

No more and I can enjoy the pretty typefaces of Calibri, Cambria, Consolas etc on Mac OS X.

To repeat his excellent post, the steps basically
- Download the trial version of Microsoft Office for Mac (any version later than 2008)
- Right-click the Office Installer DMG and choose ‘Show Package Content’.
- Look for .pkg file that installs fonts, like Office2011_all_fonts.pkg.
- Double-click the package and it will install new Microsoft fonts to the system.

Open Source iPhone projects and libraries

Open.iPhoneDev.com

http://iphonedev.com/

iPhoneDev.com is a open source iPhone directory

 

Bullet Physics Engine

http://code.google.com/p/bullet/

This is a free 3D game multi-physics library that is used in some of the popular games released on the App Store.

Joe Hewitt’s Three20 Open-Source Objective-C library
http://github.com/joehewitt/three20

Three20 is a complete set of iPhone UI classes. It includes things a photo viewer and also general utilities like the HTTP disk cache. It has been derived from the famous Facebook iPhone app – which is the number one downloaded app on the App store.

Cocos2d Framework
http://code.google.com/p/cocos2d-iphone/

This is a framework for building 2D games for the iPhone and the iPod Touch. It has a very supporting community, and is completely open-source engine. This is a must get for all aspiring iPhone game developers.

Matt Legend Gemmell – Cocoa Source Code
http://mattgemmell.com/source

Matt Gemmell has put out some of the greatest code out there for the iPhone developer community.
You have probably heard of his stuff including MGTwitterEngine, the Twitter API used in iPhone apps Birdhouse and Twitteriffic.

Appsamuck

http://www.appsamuck.com/
This is a blog that is an open-source collection of 31 mini-iPhone app projects to help you polish up your skills quickly.

Learning Objective-C : Selectors

For programmers who take the transition from Java, C# or C++, it takes some time to get used to the intricacies of Objective-C

In other programming languages, we can think of a method composed by return type, method name and its list of parameters.
Lets say in Java, if a class has a member method like below, we will denote the following class has method ‘setWidth’ in the documentation.

void setWidth(int x, int y);

Objective-C is different, we must think of a method in terms of its selector.
So in below example, the method is referred as ‘setWidth:height:’, and not ‘setWidth’.
We could have a similar but different method like:
-(void)setWidth:(int)w andWeight:(int)w;

Then how to determine the selector from a method declaration?
My rule-of-thumb is

Write down the whole method without the return type,
strip the parameter type declarations, keep the parameter alias and colons in the process.

// selector = "length"
-(void)length;
// selector = "setWidth:"
-(void)setWidth:(int)w;
// selector = "setNumerator:andDenominator:"
-(void)setNumerator:(int)n andDenominator:(int)d;

Due to the unique nature of selector, one of the fact is that Objective-C does not allow method overloading.

In Objective-C run-time, method invocation relies on selector, it treats all methods with the same selector alike.

The following hypothetic methods has the same selector, thus they are not allowed in the same class.

-(void)setWidth:(int)w height:(int)h;
-(void)setWidth:(float)w height:(float)h;

Knowing this rule will help you read code easier. Consider this delegate method in the iOS SDK:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

At first glance, you would wonder why this delegation method is named ‘application’. In fact the method actually is
‘application:didFinishLaunchingWithOptions:’ based on the selector mechanism mentioned above.

A convention in naming delegation method is that the delegating class is located in the first parameter (without’NS’ prefix), in this case, you know NSApplication is the class that is sending this delegation message.

Delegation methods have a conventional form. They begin with the name of the AppKit or UIKit object doing the delegating—application, window, control, and so on; this name is in lower-case and without the “NS” or “UI” prefix. Usually (but not always) this object name is followed by an auxiliary verb indicative of the temporal status of the reported event. This verb, in other words, indicates whether the event is about to occur (“Should” or “Will”) or whether it has just occurred (“Did” or “Has”).

 

Links:
Cocoa Fundamental

Coding Guidelines for Cocoa

Java Development on Snow Leopard

I will update it when I get a new Mac with Lion……
JDK 1.6
Snow Leopard Mac OS X 10.6 only supports JDK 1.6.
Apple has been struggling with Java support on Intel Mac, specifically Leopard 10.5 does not support JDK 1.6 on 32-bit Intel Mac. This has been changed with Snow Leopard.
Currently Intel Core Duo Mac Book Pro has 32-bit JDK 1.6 installed.Noted that JDK 1.5 or older versions of Java have been removed permanently in Snow Leopard.
As shown in following, the symbolic links of older Java version point to current JDK 1.6.
/System/Library/Frameworks/JavaVM.framework/Versions$ ls -al
total 72
lrwxr-xr-x   1 root  wheel   10 Mar 16 03:56 1.5 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Mar 16 03:56 1.5.0 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Mar 16 03:56 1.6 -> CurrentJDK
lrwxr-xr-x   1 root  wheel   10 Mar 16 03:56 1.6.0 -> CurrentJDK
drwxr-xr-x  10 root  wheel  340 Mar 16 03:57 A
lrwxr-xr-x   1 root  wheel    1 Mar 16 03:56 Current -> A
lrwxr-xr-x   1 root  wheel   59 Mar 16 03:56 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents

Re-installing JDK 1.5 to Snow Leopard
See http://tedwise.com/2009/09/25/using-java-1-5-and-java-1-4-on-snow-leopard/

To install Java 1.5 First get the Java 1.5 archive and expand it.

 cd /tmp/
 wget http://tedwise.com/files/java.1.5.0-leopard.tar.gz
 tar -zxvf java.1.5.0-leopard.tar.gz

Then move it to the standard OS/X Java location.

sudo mv 1.5.0 /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0-leopard

And finally, setup all of the links required for OS/X.

cd /System/Library/Frameworks/JavaVM.framework/Versions/
 sudo rm 1.5.0
 sudo ln -s 1.5.0-leopard 1.5.0
 sudo ln -s 1.5.0-leopard 1.5

Java support in XCode 4.0
Xcode was never a popular IDE for Java development in Mac. The older XCode version like 3.1.x used to have project templates for Java, but with the ever decreasing support of Java from Apple, Java is no longer a first-class citizen language for developing Mac software, and the result is that all Java project templates (except JNI) are now gone.

Basically Apple is telling developers that there are better tools outside with Eclipse, NetBean, IntelliJ, etc.

Learning Android – CharSequence

One of the first thing I noticed while programming in Android is that a lot of functions in its API expects text uses CharSequence type instead of String type.

Actually String class implements CharSequence. You can freely pass String object without problem.

The use of CharSequence has notable advantages that not only it is lighter and more abstract than String, it widens the usage so that it allows String, CharBuffer, StringBuilder and other CharSequence implementations.

	public static void printString(String s)
	{
	         System.out.println("Len = " + len);
	}

	public static void printCharSequence(CharSequence cs){
	         System.out.println(cs);
	}

 	StringBuilder builder = new StringBuilder("hello");
	builder.append(" world");
	printCharSequence(builder);
	printString(builder);  // compilation error!!

Learning Android – Common Problems

1. Problems in starting the emulator

If you are using Windows, the default Android SDK location is c:\Program Files\Android\android-sdk, or c:\Program Files(x86)\Android\android-sdk for 64-bit PC.

Under this configuration, when you launch the emulator from Eclipse IDE or start the virtual device from AVD manager, you might encounter error messages like below:

[2011-08-20 09:20:02 - Emulator] invalid command-line parameter: Files.

[2011-08-20 09:20:02 - Emulator] Hint: use ‘@foo’ to launch a virtual device named ‘foo’.

[2011-08-20 09:20:02 - Emulator] please use -help for more information

After a bit of research and experiments, it is a shame that looks like AVD manager or ADT don’t like any space in the SDK path, as these tools treat the ‘Files’ in ‘Program Files’ as command-line parameters.

I found the best way so far is to relocate the entire SDK to a directory that has no space, for my own convenience, I move it to c:\Android.

Next change the preferences of the ADT plugin in Eclipse to the location of the Android SDK, as well as the PATH environment variable.

2. Emulator window cut off from the screen.

Depends on which target platform chosen for the Run configuration, you may see the emulator getting cut off from the screen and the window is not sizable.

Three ways to fix:

    • Select your target avd in the AVD manager, click ‘Start’. Check the option ‘Scale Display to real size’, enter your preferred size and resolution.
    • Inside the Target tab of the Eclipse’s Run configuration, goes to ‘add additional emulator command-line options’, put this  ‘-scale 0.75′ into the box.
    • In the command line, type 

telnet localhost 5554
window scale 0.75

3. Emulator starts up slow.

The boot time of Android takes up a lot of time. Emulator command-line option ‘-no-boot-anim’ disables the boot animation. It can speed up the startup time for the emulator, not significantly but will help a little. Most importantly always keep the emulator open while developing can avoid the lengthy boot time.

Learning Objective-C Synthesized ivars

I was puzzled initially when I looked at this piece of code generated from the project template for iPhone or iPad.


@interface MyDelegate : NSObject {

}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end

How come there is no backing instance variable declared in the @interface block?

The latest Objective-C Programming Language Guide (published 2010-12-08) from Apple provides the answer, though a bit convoluted.

There is actually two kinds of Objective-C runtime, one is the ‘old’ or ‘legacy’ runtime, and the other is ‘modern’ Objective-C runtime.

For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.

For the modern runtimes, instance variables are synthesized as needed, if the instance variable is omitted in the declaration. If an instance variable of the same name already exists, it is used.

iPhone OS and 64-bit Intel use the “modern” Objective-C runtime, and other programs (32-bit programs on Mac OS X desktop) use the legacy version of the runtime.