Thursday, July 29, 2010

Mac OS, iOS, XCode4 and Foundations/Frameworks

WWDC10 videos provides a wide range of detail information about Mac OS and iOS, mainly for Mac and iPhone developers. Not only did I enjoy so much learning the new frameworks and technologies from those video sessions, but I also gained better understanding of the evolution of Mac OS and iOS, as well as the foundations or building bricks behind them.

Core Building Brick of Mac OS X and iOS

When Mac OS X Snow Leopard was released on August 8, 2009, I was amazed by its great offer: to give me back hard drive space, as I made a note in my mac blog. I got 11GB space back after I updated my OS X to Snow Leopard.

I was puzzled by this result. For sure, I guess that Apple must have done tremendous work to fine-tune its core OS engine in many ways such as rewriting its OS to optimize OS frameworks. WWDC10 reveals more information on how this was done. Apple has rewritten its compiler. The Snow Leopard was built on the new compiler LLVM, and iOS on its way from GCC to LLVM. With LLVM and Clang (compiler front end for C/C++ and Objective-C), Apple said that OS X was reduced in file size by 27%.

Compiler is the fundamental tool to convert source codes are converted into a binary language that a computer machine understands. Windows or Mac OS are built by compilers. No matter what languages we use, or whatever frameworks we have a in a language, eventually they will be compiled into machine language as packages. I think that Apple is right on the key point to restructure its compiler on assembly or machine codes. It is really hard work but all the effort has tremendous water ripple effect on Mac OS and Apple's future.

According to Apple's developer web site on What's New in XCode4, LLVM compiles codes twice quickly as GCC. The new compiler generates optimized machine codes tailored to today's modern chip architecture with a set of highly optimized libraries. As a result, the compiled applications run faster than GCC's as well.

That's why I call it as Mac OS' core building brick.

XCode4

Snow Leopard OS X has been in use for about one year. It has been approved as a solid and great OS. Now it is time for Apple to move on.

XCode 3 has been used as an IDE for developing Mac and iPhone applications. WWDC10 revealed a new beta XCode4 released for paid developers. Basically XCode4 is built based on LLVM and LLDB (as debuger). The compiler has a parser part to process source codes. XCode4 utilizes the parser to provide right and accurate information about source codes with the most advanced technology and architecture built in LLVM. As a result, XCode4 provides a much better development environment and tools for developers, than the current XCode3. For me, this is a great news. I just cannot wait for its release.

Other Foundations/Frameworks

WWDC10 reveals many other new foundations/frameworks for iOS. Most of those foundations/frameworks have been available in Mac OS since the Snow Leopard release. Those foundations/frameworks provide various ways to felicitate mobile application development, some of them with lower access to Apple's hardware, and some new ones are specially for iOS such as multitasking, iAd, GameKit, and more.

Many of new features in iOS are from Mac OS X or Snow Leopard. For example, blocks are very powerful feature in Mac OX and now available in iOS. It makes multitasking much easy to implement and many other foundations/frameworks with blocks are available as they are.

EventKit.framework provides interfaces to access calendar events on devices.

The Core Motion framework (CoreMotion.framework) provides a single set of interfaces for accessing all motion-based data available on a device. The framework supports accessing both raw and processed accelerometer data using a new set of block-based interfaces.

iAd. Framework provides simple interface APIs for developers to to deliver banner-based advertisements from their applications.

Graphics and Multimedia frameworks provides APIs in either Objective-C or C level APIs to access to graphics, video and audios devices.

GameKit provides multi-player capabilities to mobile game applications with peer to peer network connectivity, using a Bluetooth connection - no pairing required. In addition to that, it provides scores and achievement rewards to users.

iOS provides over 1500 new APIs and above are just a few of them. Refer to Apple web sites for more detail information such as What's New in iOS 4.0.

Read More...

Saturday, July 17, 2010

MyLogger Class in Objective-C (4)

In this final wrap of my MyLogger class, I'll show you my experience and usages. As most Objective-C developers know, NSLog is a C function to print out messages. It is very useful, however, as it is a function, where parameters limit its usage. It possible to pass complicated parameters, however, that' may be too difficult or just impossible. In case if you want to define different storage or format for logging message, class is the way to go. That's my initial intension to define a wrapper class for NSLog: MyLogger.

MyLogger's logging engine still uses NSLog. You can easily extend it to other storage. The API provides methods to set intention and logging message with various levels.

Usage

Normally, I initialize MyLogger settings initially in main(), where you rarely make changes. This will keep all the logging messages in the same format and consistency style. The settings are default logging level, and optional indention char and format. The great advantage of strategy is that you can easily set logging level to none if you want to disable the logging feature and you would not need to remove codes from your projects all over the places.

Here is an example of MyLogger settings:

#import <UIKit/UIKit.h>
#import "MyLogger.h"

int main(int argc, char *argv[]) {

  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  // Setup the default settings for logger
  MyLogger.defaultLoggingLevel = LogLevelDebug;
  MyLogger.indentChar = '-';

  int retVal = UIApplicationMain(argc, argv, nil, nil);
  [pool release];
  return retVal;
}

Then you are ready to use MyLogger in other places in your project. For me as a newbie of Objective-C developer, Cocoa framework and Objective-C are overwhelming to digest. It was very easy to get lost and frustrated. The way I used MyLogger is to place it in each method in my classes in a pair: logging at the first line of the method and logging at the exist point of the method, and set indent at the entry and outdent at the exit. I do get a lots debug messages; however, since all the messages are in a nice indention structured layout, it makes much easy to read and understand the flow of my class. That has been great help for me.

Another practice I have is that for each class where I want to do logging, I define a private var MyLogger* member. In the class constructor, I create the var and initialize it with a context name of that class. In this way, all the logging messages will have a clear context string to identify the messages. To set context in one place makes my logging much easy to maintain in case I need to rename my class as an example.

Taking MyClass as example, here is the way I add logging feature to the class:

// .h file
#import <UIKit/UIKit.h>
@class MyLogger;
...

@interface MyViewController : UITableViewController
  <NSFetchedResultsControllerDelegate, UITableViewDelegate> {

  ...
  @private
    MyLogger* mLogger;
  ...
}
...
@end

// .m file
#import "MyLogger.h"
...
@implementation MyViewController
...
- (id)initWithStyle:(UITableViewStyle)style {
 if (self = [super initWithStyle:style]) {
   mLogger = [[MyLogger alloc] initWithContext:@"MyViewController"];
   [[mLogger debug:@"initWithStyle: %@", style == UITableViewStylePlain ? @"Plain" : @"Group"] indent:YES];
   ...
   [[mLogger indent:NO] debug:@"initWithStyle: Done"];
 }
 return self;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  [[mLogger debug:@"numberOfSectionsInTableView:"] indent:YES];
  NSInteger count = [[self.fetchedResultsController sections] count];
  [[mLogger indent:NO] debug:@"numberOfSectionsInTableView: DONE"];
  return count;
}

- (NSFetchedResultsController*) fetchedResultsController {
  [[mLogger debug:@"fetchedResultsController"] indent:YES];
  if (mFetchedResultsController == nil) {
    ...
      [mLogger debug:@"created new NSFetchResultsConroller obj: %@"
        mFetchedResultsController];
    ...
  }
  [[mLogger indent:NO] debug:@"fetchedResultsController DONE"];
  return mFetchedResultsController;
}
...
@end

Here is a list of my loggging messages:
...
2010-07-09 16:05:28.203 ExpenseLog[2648:207] [DEBUG] MyViewController - initWithStyle: Plain
2010-07-09 16:05:28.209 ExpenseLog[2648:207] [DEBUG] MyViewController - initWithStyle: Done
2010-07-09 16:05:28.210 ExpenseLog[2648:207] [DEBUG] MyViewController - viewDidLoad
2010-07-09 16:05:28.211 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController
2010-07-09 16:05:28.211 ExpenseLog[2648:207] ----[DEBUG] MyViewController - managedObjectContext
2010-07-09 16:05:28.212 ExpenseLog[2648:207] ------[DEBUG] MyViewController - creating new managedObjectContext
2010-07-09 16:05:28.212 ExpenseLog[2648:207] ----[DEBUG] MyViewController - managedObjectContext DONE
2010-07-09 16:05:28.212 ExpenseLog[2648:207] ----[DEBUG] MyViewController - managedObjectContext
2010-07-09 16:05:28.213 ExpenseLog[2648:207] ----[DEBUG] MyViewController - managedObjectContext DONE
2010-07-09 16:05:28.213 ExpenseLog[2648:207] ----[DEBUG] MyViewController - created NSFetchedResultsController obj: <NSFetchedResultsController: 0x8611340>
2010-07-09 16:05:28.214 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController DONE
2010-07-09 16:05:28.215 ExpenseLog[2648:207] [DEBUG] MyViewController - viewDidLoad DONE
2010-07-09 16:05:28.215 ExpenseLog[2648:207] [DEBUG] MyViewController - numberOfSectionsInTableView:
2010-07-09 16:05:28.216 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController
2010-07-09 16:05:28.216 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController DONE
2010-07-09 16:05:28.216 ExpenseLog[2648:207] [DEBUG] MyViewController - numberOfSectionsInTableView: DONE
2010-07-09 16:05:28.218 ExpenseLog[2648:207] [DEBUG] MyViewController - numberOfSectionsInTableView:
2010-07-09 16:05:28.218 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController
2010-07-09 16:05:28.219 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController DONE
2010-07-09 16:05:28.219 ExpenseLog[2648:207] [DEBUG] MyViewController - numberOfSectionsInTableView: DONE
2010-07-09 16:05:28.219 ExpenseLog[2648:207] [DEBUG] MyViewController - tableView:numberOfRowsInSection:
2010-07-09 16:05:28.220 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController
2010-07-09 16:05:28.220 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController DONE
2010-07-09 16:05:28.220 ExpenseLog[2648:207] [DEBUG] MyViewController - tableView:numberOfRowsInSection: DONE
2010-07-09 16:05:28.221 ExpenseLog[2648:207] [DEBUG] MyViewController - tableView:cellForRowAtIndexPath:
2010-07-09 16:05:28.221 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController
2010-07-09 16:05:28.222 ExpenseLog[2648:207] --[DEBUG] MyViewController - fetchedResultsController DONE
2010-07-09 16:05:28.223 ExpenseLog[2648:207] [DEBUG] MyViewController - tableView:cellForRowAtIndexPath: DONE
...

I think it is really worthwhile to spend some time design this helper class. The benefits I have been received are tremendous. It greatly helps me to understand Cocoa framework, saves me enormous amount of time, and keeps my mind sharp on the business logic I want to implement.

With new iOS available, I think this class can be further enhanced with block feature to improve the performance. For example, I could put all the messages into a block so that when a logging level is disabled, the block would not be evaluated or executed at all.

Reference

Read More...

Saturday, July 10, 2010

MyLogger Class in Objective-C (3)

In my previous log, I have discussed the class level methods and some of instance methods, which as overwrites of NSObject. MyLogger class has a list of instance methods, most of them in similar structure. Those methods are defined mainly to provide convenience APIs for usage.

MyLogger Instance Methods

This snap-shot is a list of instance methods:


Here is the partial codes in .h:

- (MyLogger*) indent:(BOOL)indent;

- (BOOL) levelEnabled:(MyLoggerLevel) intentLevel;
- (BOOL) infoEnabled;
- (BOOL) debugEnabled;
- (BOOL) warningEnabled;
- (BOOL) errorEnabled;

- (MyLogger*) debug:(NSString*)messageFormat, ...;
- (MyLogger*) warning:(NSString*)messageFormat, ...;
- (MyLogger*) error:(NSString*)messageFormat, ...;
- (MyLogger*) info:(NSString*)messageFormat, ...;


I group them into 3 sections. The first one is indent. The first group contains only one simple method. This method takes only flag as parameter: indent or outdent. The implementation is very simple: it sets the global static variable (int). This integer number is used to insert number indent chars.

static int gIndent = 0;
...
@implementation MyLogger {
  ...
- (MyLogger*) indent:(BOOL)indent {
  if (indent) {
    gIndent += gIndentChars;
  }
  else if (gIndent >= gIndentChars) {
    gIndent -= gIndentChars;
  }

  return self;
}


The implementation is straightforward. One thing I should mention is that I applied the Fluent Interface pattern in this class so that some methods can be chained together to simplify its usage. I enjoy this practice very much as you can see my examples. However, it is a very controversial issue in Objective-C. I posted a question to my SO. I got some experts insights.

The next group is to get logging level status. Method levelEnabled: is a generic method to check if an intend level (MyLoggerLevel enum type) is enabled or not, and others are convenient methods to check if info, debug, warning or error logging level is enabled or not.

- (BOOL) levelEnabled:(MyLoggerLevel) intentLevel {
  BOOL enabled = NO;
  if (isValidLevel(intentLevel)) {
    enabled = self.level <= intentLevel;
  }
  return enabled;
}

- (BOOL) infoEnabled {
  return [self levelEnabled:LogLevelInfo];
}
...

here only infoEnabled is there. Other three are in the similar way. One interesting and great feature of Objective-C is that it interoperates with C well. I defined a static C function isValidLevel(...). Within the function, Objective-C types are recognized. This feature brings great power and speed into Objective-C.

The main reason I mixed C function into MyLogger class is to define private methods. Objective-C class does not provide any way or directive for private methods. All the methods in a class are public. This simplifies the compile and run time performance, no need to verify function's accessibility. Static C function is a perfect candidate for defining private methods. You will see three C functions later.

The last group of methods provides APIs to log messages. Those methods use FI pattern and C functions, as well variable arguments. Here is the method of info:, simple and straightforward again:

- (MyLogger*) info:(NSString*)messageFormat, ... {
  if ([self infoEnabled]) {
    va_list args;
    /* Initializing arguments to store all values after messageFormat */
    va_start(args, messageFormat);
    logAt(self, LogLevelInfo, messageFormat, args);
    va_end(args);
  }
  return self;
}


var_start and va_end are C macros, and logAt(...) is my C function. In the beginning part of MyLogger.m, I have the following C functions:

static NSString* nameOfLevel(MyLoggerLevel intentLevel) {
  NSString* name = kLogLevelNameUnknown;
  switch (intentLevel) {
    case LogLevelDebug:
      name = kLogLevelNameDebug;
      break;
    case LogLevelWarning:
      name = kLogLevelNameWarning;
      break;
    case LogLevelError:
      name = kLogLevelNameError;
      break;
    case LogLevelInfo:
      name = kLogLevelNameInfo;
      break;
    default:
      break;
  }

  return name;
}

static void logAt(MyLogger* logger, MyLoggerLevel intentLevel,  NSString* messageFormat, va_list argList) {
  if ( [logger levelEnabled:intentLevel]) {
    NSString* s = [[NSString alloc] initWithFormat:messageFormat arguments:argList];
    NSString* indent = [NSString stringWithRepeatedChar:MyLogger.indentChar times:gIndent];
    NSLog(gFormat, indent, nameOfLevel(intentLevel), [logger context], s);
    [s release];
  }
}

static BOOL isValidLevel(MyLoggerLevel intentLevel)
{
  BOOL valid = NO;
  switch (intentLevel) {
    case LogLevelDebug:
    case LogLevelWarning:
    case LogLevelError:
    case LogLevelInfo:
      valid = YES;
      break;
    default:
      break;
  }
  return valid;
}


This almost concludes my posts on MyLogger class. I'll wrap it up in my next post with its usages and complete codes for downloading.

Reference

Read More...

Thursday, July 08, 2010

WWDC 2010 Videos

In the past two weeks, actually since June 26, 2010, I have been watching WWDC 2010 videos. There are total 125 videos, each about one hour time. Now I have 72 left, which may take me at least one more month to finish, two videos a day.

Those are really good talks on Cocoa, Objective-C and iOS or iPhone. Most of them provide detail information about its new features and framework. I think my past years learning on Cocoa and Objective-C, and recent hands-on iPhone development benefit me a lot. Without my past knowledge and experience, it is hard to understand those new videos. I think I am on the right track with Mac and iPhone development.

Recall back the initial days when I was doing iPhone coding, it was too much and overwhelming, since the framework and syntax are so different from .Net and other languages such as JavaScript, PowerShell and Ruby. However, I knew that all those were new for me and I should not bring my past experience in other framework as pre-adjudgement to influence my learning. I tried to not just copy and paste codes. Instead, I just typed all the codes so that I got first experience with the new framework. I think my efforts are worthwhile. Now I feel the power and beauty of this new framework.

For example, the ObjC syntax is very different .Net C# one. The methods are function like: methodName(type par1, ...); while in ObjC, it is methodAndDescriptionWithArg1: descriptionWithArg2:.... ObjC actually is more descriptive and easy to read.

Taking the following C# example:

class MyClass {
...
private bool DoAction(string name,
bool condition1,
int flag)
{...}
...
}
...
obj = new MyClass();
obj.DoAction("some name",
true,
2);

When you use the method with arguments in values, it is really hard to understand the meaning of each argument. You may rely on Visual Studio intelligent hints to get their means.

The similar codes in ObjC:
@interface MyClass : NSObject {
...}

- (BOOL) doActionWithName:(NSString*)name
condition1:(BOOL)value
andFlag:(int)flag;
@end
...
obj = [[MyClass alloc] init];
BOOL result = [obj doActionWithName:"some name"
condition1:YES
andFlag:2];

As you can see the ObjC syntax is more descriptive. Here are two slides in session - 138 API Design for Cocoa and Cocoa Touch, at WWDC10:





As in the comparison, you can see that Apple's OS framework and Objective-C was fundamentally a well structured and designed even back to 1981, unlike other languages just mimic C syntax.

Read More...