Tips for Developers New to Xcode (iPhone)

 
Martin Belcher 6th September 2010

Intro

This article has some information useful to developers who are new to development for Apple platforms.


  1. Use the Latest Version of IDE
  2. Objective C Syntax
  3. Two files for every class?
  4. Calling Methods vs Sending Messages
  5. Threads
  6. Getting Answers
  7. Change to LLVM Compiler
  8. Use the Built-in Provisioning and Deployment Tools
  9. Managed or Unmanaged Code

Use the Latest Version of IDE 

Make sure you are using the latest versions of Xcode (3.2) and the iOS SDK (4.0).

Xcode currently feels very awkward to work with but each new version brings great steps forward. If you have come from another development environment such as Eclipse or Visual Studio then you will probably be surprised at how many IDE features you normally take for granted are missing and frustrated by other things:

  • weak implementation of code completion
  • many floating windows
  • lack of compilation and syntax error highlighting during editing time
  • the frustrating lack of integration between the code files and the Interface Builder files. Interface Builder itself is actually a completely separate program
  • poor built in support for SubVersion (so much so that you are better off just using command line for svn activities)

Good news is that Xcode 4 will elegantly address all these gripes and introduce some really nice extras especially in debugging and performance tuning; it looks like a great modern IDE.


Objective C Syntax 

Objective C is a language that was created to deliver object orientated programming on top of C and borrows heavily from LISP. The most popular modern languages like Java and C# developed along a different path which means that Objective C looks bizarre or even ugly to most developers. Some of the choices are plainly bad but as the IDE improves this will because less of chore to write. Good news is that all of the important commonly used OOP concepts are there;

  • Single inheritance
  • Interfaces
  • overloads
  • member methods and properties
  • constructors
  • deconstructors
  • etc

Some gotchas:

  • No Dot notation for accessing class members, this is not entirely true because you can use the Dot notation to access member properties that you have synthesized using "@Synthesize" (this creates virtual getters and setters for you) and you can use it for member method calls that do not receive any arguments. This leads to more confusion as all other method calls require a square braces notation that works like this:

      // Method call with no arguments
      [classInstance methodName];

      // Method call with single argument
      [classInstance methodName:argvalue1];

      // Method call with two arguments
      [classInstance methodName:argValue1
             methodArgumentName:argValue2];


      // **********************************
      e.printStackTrace

    This gets a bit confusing when you do nested method calls

      // Nested method calls
      [[classInstanceA methodNameA]
            methodNameB:[classInstanceB methodNameC]];

    Dot notation this would be

      // Nested method calls
      classInstance.methodNameA()
            .methodNameB(classInstanceB.methodNameC());

    Eventually you do remember to go back to the line start and put in the extra braces;

  • When declaring methods with multiple arguments each argument must be named, except the first one. This is an example of a method declaration:

      // Method declaration with multiple arguments
      - (void) methodName:(int *)intValue1
            methodArgumentA:(int *)intValue2

      {
        // Code here
      }

    Tip: This is counter intuitive but it helps to think of the argument names as being part of the method's fullname, like it was a person with first name, middle names and surname. So the example method's real full name is "methodName:methodArgumentA:".

  • Enumerators only allow integers and do not use Dot notation.

    To access a value of an enumerator use the elements directly as if you have just declared a set of constants rather than an actual enumerator. For example if you declared an enumerator as

      // Enumerator declaration
      typedef enum
      {
        RED = 1,
        BLUE = 2,
        YELLOW = 3
      } MyColourEnumerator;

    NB you put this declaration above the "@implementation" in the .m file or in a .h file

    You might expect to access these like this

      if (intValue == MyColourEnumerator.RED)

    But you have to access them like this

      if (intValue == RED)

Two files for every class? 

There is a header file .h and an implementation file .m, this will be familiar to those with a background in C. In Objective C every class needs to have a interface which describes its members, this is written in the .h file. The .h file is also a good place to declare constants and import frameworks or .h files of other classes that you want to use within your class.

In order for your class to be used in any other class that class will import the .h file of your class.

The .m file is where you put the actual class and all the code that resides within its members, you can create methods here that do not exist in the interface in the .h file but they will only be accessible from within the class itself.


Calling Methods vs Sending Messages 

When reading references, forums or watching videos on Objective C some concepts will make more sense if you keep in mind that Objective C does not call methods, rather it creates a message object and sends a message to the object that owns the method, for methods with return types a message goes the other way on completion. Most of the time this fundamental difference is indistinguishable; you “call” methods and they run, you access properties and the values return, it just works.

The compiler does not check that members exist, you can call methods that do not exist and your application will still build.


Threads 

You can create threads using the NSThread object and use them much like in any other language but there is a much better way to run asynchronous operations by using NSOperationQueue , this is a real strong point of the SDK, it manages the threads, thread pools and thread allocation on multi-core processors for you, nice.

See our article Programming threaded processes in iPhone for more information on threading in iPhone.


Getting Answers 

Forums and good old Google search will turn up answers to most of your problems but there is an excellent resource available from the Apple Worldwide Developer Conference, there are loads of clear detailed videos on the kind of things you are likely to be trying to figure out and source code available for download. It is often worth checking here first http://developer.apple.com/videos/wwdc/2010/.


Change to LLVM Compiler 

You can specify which compiler Xcode uses the default is GCC but Apple recommend using LLVM which they claim not only compiles quicker and returns better compile error messages but that it actually produces code which runs up to 60% faster on iPhones.

To do this:

  1. open your project in Xcode
  2. click Project then Edit Project Settings
  3. on the Build tab got down to the Compiler Version section and choose LLVM

Use the Built-in Provisioning and Deployment Tools 

New in the latest version of Xcode (3.2) you can automatically provision test iPhones just by plugging them into your development machine and using your developer username and password from within Xcode. No more downloading fiddly files from the provisioning portal. You can create IPA files from using the Organizer that you open by “Build > Build and Archive”, using the Organizer you can also validate your application and submit it to iTunes.


Managed or Unmanaged Code 

Objective-C is not a managed language.

Managed languages take care of memory allocation and de-allocation for you and often run in a virtual machine, they feature a garbage collector that tidies up any variable/object memory allocations once they are no longer referenced.

Objective-C does perform a light garbage collection of objects that you have not specifically marked as needing to be retained in memory, this cannot be relied upon because there is no guarantee that objects will ever have their memory released and conversely they might be released before you have finished using them. Every variable/object that you use in Objective-C should be instanciated with the alloc or received from a method call/constructor with retain.

Examples

  NSString* strMyString0 = [[NSString alloc]
initWithFormat:@”Price = %d”, intPrice];


  NSString* strMyString1 = [[myClassObject getStringMethod] retain];

Once the lifetime of the variable/object is over you are responsible for calling release on the object to de-allocate the memory.

See our article Objective-C Objects Memory Management Basics for more information on memory management.

 

Add Comment

 
Name:
Email:
This email address will not be shown on the website and will not be distributed to any other parties. By submitting this email address you agree to receive an email from Eigo in the future, that email will include an option to unsubscribe from future emails.
Comment:
(HTML allowed)
Website: (Optional)
A link to show beneath your comment.
Security Check: