iOS 4.1 due September 8th, solves iPhone 3G performance problems

iOS 4.1 was announced last week with promises to fix incredibly slow UI for iPhone 3G amongst other goodies and fixes. The official release is due September 8th 2010 but the developers have access to GM release for a week now. I have an iPhone 3G so I installed this GM right away to see if it fixes the problems for me and it did. At least a bit.

With 4.0 entering text was slow and painful process, also interacting with the most GUI elements sometimes took a second or even more. Installing 4.1 made UI responsive again, I’m actually able to type SMS and emails without so much frustration. Now the thing I’m worried about is that after almost a week of 4.1, I’m starting to notice some lagging. It’s not nearly as much as I used to have with 4.0 but still, the phone doesn’t appear as fast as it was 5 days ago. It’s probably due to a bunch of stuff I sync’ed with it or at least I hope so.

If you’re an iPhone 3G owner with iOS 4.0 you should most definitely upgrade. And not to forget, Lifehacker uploaded this great video of comparison if you still have doubts whether or not you should upgrade.

6 Useful Objective C & Cocoa macros

Here are a few useful cocoa & cocoa touch macros that I’ve come across and thought I share here. Some of those I use regularly and some I just know about but you may find them useful.

Hex (HTML) color to UIColor macro

I found this macro a long time ago somewhere and I’m not sure what’s the original source, yet the Google search returned this blog so I’m going to give him the credit.

#define HEXCOLOR(c) [UIColor colorWithRed:((c>>24)&0xFF)/255.0
                                  green:((c>>16)&0xFF)/255.0
                                     blue:((c>>8)&0xFF)/255.0 \
                                    alpha:((c)&0xFF)/255.0]
//usage
UIColor* color = HEXCOLOR(0xff00ff00);

Enumerating collections macros

The following macro helps you with fast enumeration over collections, credit goes to Wincent.

#define WOEnumerate(collection, object)                                     \
for (id enumerator = [collection objectEnumerator],                         \
     selector = (id)@selector(nextObject),                                  \
     method = (id)[enumerator methodForSelector:(SEL)selector],             \
     object = enumerator ? ((IMP)method)(enumerator, (SEL)selector) : nil;  \
     object != nil;                                                         \
     object = ((IMP)method)(enumerator, (SEL)selector))
 
#define WOKeyEnumerate(collection, object)                                  \
for (id enumerator = [collection keyEnumerator],                            \
     selector = (id)@selector(nextObject),                                  \
     method = (id)[enumerator methodForSelector:(SEL)selector],             \
     object = enumerator ? ((IMP)method)(enumerator, (SEL)selector) : nil;  \
     object != nil;                                                         \
     object = ((IMP)method)(enumerator, (SEL)selector))

Logging macros

CMLog - use to extend NSLog functionality.

#define CMLog(format, ...) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:format, ## __VA_ARGS__]);
 
//usage
CMLog(@"My iPhone is an %@, v %@", [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion]);

MARK - method stamp macro, use to output class and method name.

#define MARK	CMLog(@"%s", __PRETTY_FUNCTION__);

Benchmarking macros

Use START_TIMER and END_TIMER to get the timing between these two calls.

#define START_TIMER NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
#define END_TIMER(msg) 	NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate]; CMLog([NSString stringWithFormat:@"%@ Time = %f", msg, stop-start]);
 
//usage example
- (NSData *)loadDataFromURL:(NSString *)dataURL
{
  START_TIMER;
  NSData *data = [self doSomeStuff:dataURL];
  END_TIMER(@"loadDataFromURL");
  return data;
}

Logging and benchmarking macros, courtesy of Stephan Burlot.

UIView frame (CGRect) macros

And for the end, here’s my own modest addition to the list. When developing an iPhone or iPad apps, you probably found yourself lots of times working with UIView frames, changing them etc… Often times I just change the UIView size or I just need to move it around the screen, reposition the view and each time I need to do CGRectMake etc… The following macros have helped me and saved me some typing.

#define width(a) a.frame.size.width
#define height(a) a.frame.size.height
#define top(a) a.frame.origin.y
#define left(a) a.frame.origin.x
#define FrameReposition(a,x,y) a.frame = CGRectMake(x, y, width(a), height(a))
#define FrameResize(a,w,h) a.frame = CGRectMake(left(a), top(a), w, h)

Obviously you can do the same for UIView ‘bounds’ instead of ‘frame’.

Handling layout on UIInterfaceOrientation change

In iOS version >= 3.0, it’s very simple to support interface orientation changes and layout your GUI elements accordingly. Support for landscape and portrait mode are very important for user experience and I think even essential on iPad. In this short text, we’ll cover several UIViewController instance methods that help dealing with UIInterfaceOrientation on iOS devices.

As an example, we can use the YouTube app that comes installed with iOS operating system. This great app shows how simple GUI provides perfect user experience in both landscape and portrait mode. Rotating your iPad makes it remove not needed GUI elements, at the same time unclutter the screen and resize visible controls to fit new layout.

YouTube iPad app

YouTube iPad app

In order to support a certain interface orientation, first you need to override the following method:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	//we want to support all orientations
    return YES;
}

Now that you enabled the interface rotation, you would want to implement the methods that inform you when the rotation (and rotation animation) starts and finishes. Those are:

  • willRotateToInterfaceOrientation:duration:
  • willAnimateRotationToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:

Simple enough – willRotateToInterfaceOrientation will be called just before the the device layout rotates, willAnimateRotationToInterfaceOrientation gets called inside animation block just before the animation of the rotation starts and finally didRotateFromInterfaceOrientation gets called once everything is finished and the rotation ended.

With these descriptions alone it’s easy to understand that your logic would be to:

  • Create views/controllers inside willRotateToInterfaceOrientation and add them to the layout
  • Modify view’s attributes (position, size etc…) inside willAnimateRotationToInterfaceOrientation
  • Clean up & remove not needed views inside didRotateFromInterfaceOrientation

Important thing to mention is that willAnimateRotationToInterfaceOrientation method is called inside an animation block so every animatable properties of your views you modify inside this method will be automatically animated. This is very neat, for example, if you just need to reposition and resize your views. You would just change pass desired CGRect as view’s frame and the change would be automatically animated for you when the device changes it’s orientation. to either portrait or landscape.

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
	if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
		previewLayout.frame = CGRectMake(695, 13, previewLayout.frame.size.width, previewLayout.frame.size.height);
	} else {
		previewLayout.frame = CGRectMake(413, 575, previewLayout.frame.size.width, previewLayout.frame.size.height);
	}
}

This example demonstrates view reposition only and as you can see the coordinates are hardcoded. I also used a macro UIInterfaceOrientationIsLandscape() which totally simplifies how you determine whether the interface orientation is portrait or landscape.

Besides mentioned methods for responding to view rotation events, there are another 3 that I’m just going to mention now and possibly cover in a future post. Basically they are triggered during animation and inform you about the first half of animation start/finish and the second half animation start. They are also called during animation block just like willAnimateRotationToInterfaceOrientation.

  • willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
  • didAnimateFirstHalfOfRotationToInterfaceOrientation:
  • willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:

Check out the Apple’s developer docs for more info.

To sum up – by responding to view rotation events using above mentioned methods, you can create rich user experience and make you app accessible in all orientations. Transitions from one orientation to another can also be enriched with nice animations in few lines of code so make sure you take advantage of that.

Showing network activity indicator in status bar

Showing network activity indicator in iOS device’s status bar is fairly simple job and can be done in 1 line of code. However, I’ve seen lots of apps with bugs in this area and moreover I see them every day. Reason for this is because few people actually pays attention to coordinate network activity indicator showing and hiding. Let’s see how do you show and hide the indicator.

	UIApplication* app = [UIApplication sharedApplication];
 
	//to show it, set it to YES
	app.networkActivityIndicatorVisible = YES;
 
	...
 
	//to hide it, set it to NO
	app.networkActivityIndicatorVisible = NO;
iPhone Status Bar

iPhone Status Bar w/ network activity indicator on

So, just this 1 line to either show or hide it. It’s that simple. But the problems may show up if you have multiple requests that release the indicator at different times so you get yourself a race condition. This problem can surely be fixed by using some of the concurrency techniques but I use a simpler method which includes request/release counter and updates the indicator accordingly.

First you need to find a suitable place for sending requests/releases to. I use app delegate as it’s singleton and can be accessed from any class but you can decide to use something else. You declare one integer ivar e.g. netActivityReqs and assign a property to it (optional). Now all you need is just these two methods and you’re done.

-(void) requestNetworkActivityIndicator {
	UIApplication* app = [UIApplication sharedApplication];
	app.networkActivityIndicatorVisible = YES;
 
	self.netActivityReqs++;
}
 
-(void) releaseNetworkActivityIndicator {
 
	self.netActivityReqs--;
	if(self.netActivityReqs <= 0)
	{
		UIApplication* app = [UIApplication sharedApplication];
		app.networkActivityIndicatorVisible = NO;
	}
 
	//failsafe
	if(self.netActivityReqs < 0)
		self.netActivityReqs = 0;
}

As you can see it’s extremely simple and straight-forward, you just need to pay attention to these details that may hurt user experience. You still, however, need to be careful to match your request and release calls as this idea only helps with preventing race conditions from multiple activity request calls but it can’t even your calls so you might end up with activity indicator spinning forever if you’re not careful.

Consuming ASP.NET web services in iOS part 2

In previous blog post I’ve explained how to create iOS friendly ASP .NET web service with JSON RPC so now we’re going to take it further by creating an iPhone app that will consume this web service. Since iOS natively does not support JSON, we’ll be using this nice JSON framework available on Google Code here. This framework provides NSObject categories which allow simple JSON parsing and and it’s really convenient to use with iOS SDK. Other than that, we’ll be using native iOS SDK APIs only to create HTTP connection and query our JSON RPC service. Calling this web service is done by creating NSURLRequest with HTTP POST method and passing method name, method parameters (arguments) and identificator. NSURLConnection uses this request and does the magic we need. Let’s see the code.

First, we need to create JSON string which we’re going to POST to our RPC service. We do this by simply creating a dictionary and breaking it down to JSON representation.

 
//RPC
 
NSMutableDictionary* reqDict = [NSMutableDictionary dictionary];
 
[reqDict setObject:methodName forKey:@"method"];
 
[reqDict setObject:parameters forKey:@"params"];
 
[reqDict setObject:identificator forKey:@"id"];
 
//RPC JSON
 
NSString* reqString = [NSString stringWithString:[reqDict JSONRepresentation]];

We should note 3 arguments we’re posting to the service – method, params and id. Method is RPC method name as declared in JSON RPC web service. Params are arguments this method requires and ‘id’ is the call identifier which RPC call returns when sending back response and it’s used to link the response to the request in case you’re sending out multiple requests. In our case, the method name is ‘HelloWorld’ without arguments and as the identifier we’ll just put 1.

So now we create NSURLRequest and NSURLConnection using this reqString. This is the main part of code so pay attention.

 
//Request
 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
 
NSData* requestData = [NSData dataWithBytes:[reqString UTF8String] length:[reqString length]];
 
//prepare http body
 
[request setHTTPMethod: @"POST"];
 
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
 
[request setHTTPBody: requestData];

First we create a mutable url request, set it’s HTTP method to “POST” and fill out other HTTP specific header fields. Finally we set our JSON request string as HTTP body.

Now we simply create NSURLConnection, assign a delegate to it and wait for our data.

 
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
 
[request release];

The delegate part of the calling object has these methods defined.

#pragma mark -
#pragma mark NSURLConnection delegate
 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	NSLog(@"Did receive response: %@", response);
 
	[webData release];
	webData = [[NSMutableData alloc] init];
}
 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
	assert(webData != nil);
	[webData appendData:data];
}
 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	[webData release];
	webData = nil;
	[urlConnection release];
	urlConnection = nil;
 
	UIApplication* app = [UIApplication sharedApplication];
	app.networkActivityIndicatorVisible = NO;
 
	//notify
	[delegate loadingFailed:[error localizedDescription]];
}
 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
	[urlConnection release];
	urlConnection = nil;
 
	UIApplication* app = [UIApplication sharedApplication];
	app.networkActivityIndicatorVisible = NO;
 
	//DO something with webData
	[delegate dataLoaded:webData];
 
	[webData release];
	webData = nil;
}

Once the connection gets a response we create NSData (webData) and we append bytes to it in didReceiveData callback. In the end we either get didFailWithError or didFinishLoading and take actions accordingly.

Finally, the app would return something like this when launched.

iPhone calling JSON RPC web service

iPhone JSON RPC

For your convenience, I have attached XCode project for download. Please note that this is an example only and should be treated as such, I don’t provide guarantee of any kind for this code.

JSON RPC iOS example project

Consuming ASP .NET web services in iOS part1

Since, at the time of my writing, iOS SDK does not natively support SOAP WebServices many have found different ways to consume these web services. Some of them include manually making HTTP requests and parsing response, using WSDL to ObjectiveC generators and more. One of the convenient ways I found when it comes to RPC is to combine the niceness of ASP .NET with JSON-RPC which can be accessed in iOS easily. So, let’s begin creating an iOS friendly ASP .NET web service.

The framework which makes this possible is Jayrock. Jayrock is a modest and an open source (LGPL) implementation of JSON and JSON-RPC for the Microsoft .NET Framework, including ASP.NET.

Let’s see how we can make this work. First, let’s create a simple HelloWorld() web service. Open up Visual Studio and create ASP .NET web project (or any other suitable type).

Visual Studio New Web Application Dialog

Create New Application

Add a generic handler to your app and call it whatever you like.

Visual Studio Add Handler

Add generic handler

Now we need to reference Jayrock library, so right click your project and “Add Reference”, browse to find Jayrock.dll and Jayrock.Json.dll and add references to them. Once you’ve finished that, we can continue to build our web service.

Open the handler you’ve created and modify the class to look something like this:

[csharp]public class my_service : Jayrock.JsonRpc.Web.JsonRpcHandler
{
	[Jayrock.JsonRpc.JsonRpcMethod("HelloWorld")]
	public string HelloWorld()
	{
		return "Hi iOS, this is ASP.NET!";
	}
}[/csharp]

  And now we’re ready. Try out this service in your browser, you should be able to see its description and test page. You can also test to see if it actually works, like this.
Jayrock RPC page

Jayrock RPC

If you see this, we’re completed JSON RPC web service in C# ASP .NET. In the next part of this blog, we’ll create an iOS app which will consume this service. Stay tuned!