Android Saga: AsyncTask, Advantages and Limitations

07/08/2012 § 2 Comments


This is an utility class available in the Android SDK that abstracts a worker thread. An AsyncTask object can be compared to the NSOperation object from iOS.

The NSOperation object represents an operation of some kind and has to be added to a NSOperationQueue in order to execute. This queue can either be the main queue (UI thread) or another one that you create to execute operations in background. iOS doesn’t schedule an operation if it is not possible, neither throws exceptions when it is not possible to schedule an operation. Instead, iOS waits for the right moment to schedule the operation.

The difference between AsyncTasks and NSOperation lies on how they are scheduled. An AsyncTask is automatically scheduled when the method execute() is called. From API Level 11 onwards, execute() can have some parameters passed in to specify the queue on which to schedule it.

AsyncTask provides a simple API for doing work in the background and re-integrating the result with the main thread. Here’s what it looks like:


new AsyncTask<Param, Progress, Result>() {
 protected void onPreExecute() {
 // do something before the hard work, like tell the user what you are going to do

}

protected Result doInBackground(Param... aParams) {
 // do some expensive work
 }

protected void onPostExecute(Result aResult) {
 // background work is finished,
 // so update the UI here
 }
}.execute();

Both methods onPreExecute() and onPostExecute(Result) are invoked on the main thread, so that you can safely update the UI.

If you would like to show the user progress is being made, there is a fourth template method - onProgressUpdate(Progress[]) – that you can implement to update the UI. Notice that you need to regularly invoke publishProgress(Progress[]) from within doInBackground(Param[]) so that onProgressUpdate can be called for you.

The type variables of AsyncTask you saw in the code above are:

  1. Params is the argument type for the array passed in to doInBackground.
  2. Progress is the argument type for the array passed in to onProgressUpdate.
  3. Result is the return type of doInBackground, which in turn is the argument type passed in to onPostExecute.

When execute(Object.. params) is invoked the task is executed in a background thread. Depending on the API Level AsyncTasks may be executed serially, or concurrently. The only way to be sure is by invoking executeOnExecutor(Executor executor, Object.. params) method instead, and supply an executor. But this can only be done from API Level 11 onward, as I said previously.

This is a very useful abstraction of a Thread/Runnable combination. As it provides the hooks needed to keep focus only on what you application needs to do.

However you must keep in mind that it is not all flowers. If you want to support the vast majority of Android users, you must develop for API Level 8 (currently if you install Eclipse with ADT, ADT will tell you that about 80% of Android users are running API Level 8. I am not sure if this is valid only for Brazil or not. Anyways, even it is only within Brazil, that counts already hundreds of thousands users – Brazilian population is approximately 194 million people).

And API Level 8 doesn’t support executeOnExecutor. API Level 8 AsyncTask supports 10 threads and a work queue depth of 10. In theory, that would support 20 threads if nothing else is using AsyncTask as well. This limitation easily crashes your app if you are using AsyncTask to fetch thumbnails from some remote URL for a list view to present in each row.

If you are consuming a web service, the right approach would be to use a Service instead of a worker thread. So you could use the same service to request the image, store it locally and fetch it somehow from your local filesystem so that your ListActivity can present it. But if you wish to keep things simple and don’t handle image caching at all, the solution is to implement a queue and execute your requests serially.

Personally I think this should be provided by Google in the Support Library. But it isn’t, so the solutions is to copy the newly version of AsyncTask (from API Level 11) into our own AsyncTask implementation and make it work with earlier Android SDK (down to API Level 3). The modified source code is available here.

If you decided to grab that code, you should start using your.package.AsyncTask instead of android.os.AsyncTask, call executeInExecutor(Executor executor) instead of execute() and create your own Executor:


private static final BlockingQueue<Runnable> sWorkQueue = new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE);

public static final ThreadPoolExecutor SERIAL_EXECUTOR = new ThreadPoolExecutor(1, Integer.MAX_VALUE, 30, TimeUnit.SECONDS, sWorkQueue);

Note: It is important to keep in mind that this alternative works very well (since it doesn’t really matter what API Level your user is running), but it is also considered to be bad practice since you don’t get updates on AsyncTask when a new API Level is released unless you manually apply any changes to your class.

Another thing to keep in mind is that AsyncTasks are there for you to void blocking the main thread, but you have to properly handle them considering the Activity lifecycle and also that your application runs in an environment where users switch contexts frequently and quickly.

For example, if your AsyncTask retains a reference to the Activity, not cancelling the task when the Activity dies wastes CPU resources on work that cannot update its UI, and creates a memory leak. Don’t forget Activities are destroyed and re-created when some configuration changes (ie: device orientation). So these are not edge cases.

AsyncTask is good, but also has its limitations – depending on the API Level – and constraints. Having those in mind, think about your task before coding with AsyncTasks. Maybe they are not the best approach. Maybe they are. And maybe you should grab Google’s code, modify it and use it instead.

Android Saga: Adapters are Cool Stuff!

06/30/2012 § 1 Comment


I am still covering the basis, but I can tell that Adapters are cool stuff.

An Adapter object acts as a bridge between a view and the underlying data for it. For example, the ListAdapter is specialized in handling data for a ListView (it corresponds to the implementation of UITableViewDelegate on iOS).

What is so cool about Adapters?

They allow high level of code reuse and easy customization.

How did I get to this conclusion? Well, let me tell you my story.

I started with a ListView backed by a custom ArrayAdapter that I called PlacesListAdapter. All that it did was receive a list of items as argument, inflate and populate a specific view for each item in the list.

To reduce the time for initial view loading and be as parsimonious with memory usage as possible, I considered to lazily load data as the user scrolls.

As I am new to Adapters, I couldn’t see an easy way to make this happen. Looking for how other developers approach this pattern, I found this solution from Mark Murphy that caught my attention.

Why? Because it is a gorgeous solution. He came up with an adapter – he called it EndlessAdapter – that wraps a ListAdapter and provides the means for loading more items once the user gets to the end of the list. Basically it sums 1 to the number of items in the wrapped list adapter and returns a pending view for this last item. Once this pending view is inflated, the Endless Adapter calls cacheInBackground() in a worker thread for you to load data in background. Once its done, appendCachedData() is called in the main thread and you are able to add that data to your wrapped adapter and notifyDataSetChanged() so that more data is shown on the list. The stop criteria is the amount of items you fetched.

Once this was made past, I changed just a little bit my custom list adapter to fetch data from a ContentProvider. Basically I inherited from CursorAdapter instead of ListAdapter and provided a Cursor object as argument.

It happens a Cursor object represents the results of a query, so in order to load the next set of items, I needed to do a new query and retrieve a new cursor – so everytime cacheInBackground() is called, the query limit is increased by limit, grabbing more data each time. Besides that a CursorAdapter requires the current cursor to be swapped to the new one so that it can reflect the data set change in the list.

But this is not optimal. I looked the documentation and found the MergeCursor, a convience class that lets you present an array of Cursors as a single linear Cursor. Although this approach was very interesting it did’t quite meet my requirements because I needed to fetch the next set of items from the local cache – so the users sees right away the data he wants –  and then from a web service – so I get to update the data I have in the cache. Therefore I would have to query the ContentProvider for all the items again.

So I thought of doing as Mark did and create a MergeAdapter class that would present an array of adapters as a single linear adapter. This way I could read only new data of page limit size from the local cache (by increasing the offset instead of the limit), provide the cursor to a brand new PlacesListAdapter and append it to the MergeAdapter. Once the data for that page is fetched from the web service, I could just grab the list adapter for that page and swap the cursors. Beauty!

Fortunately I found a convience class for this as well, and guess who wrote it? Mark Murphy.

In the end the architecture is very simple: an EndlessAdapter wraps a MergeAdapter that wraps a list of PlaceListAdapters.

To get this working on iOS is not that easy. Mostly because of its architecture. In first instance, UITableViewDelegate methods are implemented by the controller, so the developer needs to create the concept of ListAdapter and implement its lifecycle in the controller. Then inherit from this custom controller every time a table view is required. Once this is done, the Android approach can be taken.

But this is not the most important part. The highlight here is that Android helps the developer to write better code than iOS does in this case.

Android Saga: Pull to Refresh revisited

06/27/2012 § 2 Comments


Previously on Android Saga..

“I find the solution very bizarre, but it worked out and that is what I am using right now. The only thing that still upsets me, is that the feature is not polished enough. It is still sluggish to pull, flicks once in a while, and lacks animation.”

It happens I was wrong. Yesterday I tested the app on the device – precisely a Samsung Galaxy i5500 running API Level 8 – and I was surprised when it didn’t work since all this time I was testing on an emulator running the very same API Level. I know the emulator is different from the device. This is true for the iOS simulator as well. But not THAT different.

Anyways, Johan’s implementation doesn’t work either on Samsung Galaxy i5500 running API Level 8 nor Samsung Galaxy S2 running 4.0.3 (Yes I tried a newer version to see if I was pushing to hard by using an old API version).

I got to a point where I started to think that maybe pull to refresh wasn’t the answer for Android. Actually my girlfriend asked me if I was not trying to put an iOS app into Android. And she had a good point: Android doesn’t support bouncing in the list view, so Android users are not used to pull the list hence they don’t easily discover how to pull to refresh.

Discussing this matter with some co-workers, I was presented with a list of well known Android apps (Twitter, Facebook, LinkedIn…) that actually do a very good pull to refresh. This convinced me that Android apps can be as good as iOS apps.

So I kept looking for other pull to refresh implementations. In the end, I got to Chris Banes’s library.

This time as soon as it worked on the emulator, I tried on both devices I have here and it worked pretty well. In fact, it is as good as Twitter’s pull to refresh.

Now, the interesting fact is: Chris Bane’s implementation needed 6 Java classes (and they are not tiny), 8 XML files and 2 images. His implementation is very interesting and truly had outstanding results. BUT this is TOO MUCH WORK FOR SUCH A SIMPLE FEATURE!

Knowing there are developers and developers (although this guy deserves respect since he is the only one that got a – open source – pull to refresh to properly work on Android), I tried not to think: “On iOS it would take a class for the header view and another to use it. Really.”.

Instead I googled for the Twitter APK file, downloaded it and decompiled it (a pretty painful process – by the way – that requires decompressing the APK, converting smil files to dex, from dex to jar and finally to Java source files). Of course, I wasn’t able to just grab and use their implementation, but that was enough readable code to see that they use just about the same number of files that Chris Bane’s does.

I am sure every file has its meaning and need, but still too much work for this feature. And just to be sure we are in the same page, I am not counting any i18n files neither assets for supporting multiple screen densities whatsoever.

Anyways, I learned two things on all of this:

1. Android apps can be as good as iOS apps
2. #1 requires a lot more work than it takes on iOS (and I am not talking about device fragmentation)

For those that like references, here are the best pull to refresh libraries I tried on Android:

https://github.com/chrisbanes/Android-PullToRefresh
https://github.com/johannilsson/android-pulltorefresh
https://github.com/woozzu/RefreshableListView.git
https://github.com/erikwt/PullToRefresh-ListView

And the tools I used for decompiling Twitter:

http://code.google.com/p/android-apktool/
http://code.google.com/p/smali/
http://code.google.com/p/dex2jar/
http://www.varaneckas.com/jad/

Android Saga: Pull to Refresh

06/25/2012 § Leave a comment


Pull to refresh is an extremely popular UI gesture (that Loren Brichter pioneered in Tweetie) used in a lot of iOS apps. Basically it makes refreshing part of the scroll gesture itself.

The iOS community have had library support for this for a long time – I think that Three20, back in 2010, was the first library to offer this feature out of the box.

This very feature has come to the Android world later on and today many apps use it.

Since I don’t have much experience with Android, the first thing I did was to search for an open source implementation. I found plenty of them in a couple seconds.

(I also found a lot of Android developers thanking the Android open source eco-system for making libraries available as if that wasn’t true for other platforms. iOS as many other mobile platforms counts with a strong open source community too ^^)

The best implementation I found out there was a contribution from Johan Nilsson. Besides the sluggish scrolling and lack of animations, it works pretty well (correct me if I am wrong, but we can’t blame Johan for half the issues here since Android makes it really difficult to have smooth scrolling and bounce animations on ListViews).

I didn’t have any problems to import his library and use his implementation. Specially because he provides a very straightforward demo. The only thing that was really upsetting me though, was that pull to refresh header is supposed to be hidden all the time when the user isn’t scrolling or refreshing the list. And the header was standing there presenting a “Tap to Refresh” message.

That was when I decided to look the code and fix it. To be honest, the idea behind Johan’s implementation is very similar to the iOS approach. But not quite.

Let me tell you why.

On iOS, Pull To Refresh is implemented by the following steps:

1) Create the header view which displays the arrow, the spinner and the text messages
2) Add it to the UIScrollView with a negavite y value
3) Implement the UIScrollView’s delegate to set the contentInset as the header height (therefore making it visible) and ask the controller to refresh the content
4) Once the controller is done, it sets the contentInset to zero (therefore hiding the header view)

On Android, all the implementations I found follow the steps below:

1) Create the header view which displays the arrow, the spinner and the text messages
2) Extend the ListView and implement onAttachedToWindow, setAdapter, onTouchEvent to select the first row (WTF!?)
3) Implement the onScrollListener (equivalent to the UIScrollView’s delegate)
4) Once the controller is done, select the first row so the list scrolls to the top and hides the header if the content is higher then the list view

Although the approaches are very similar, Android’s version is essentially a hack that exploits the optional header in standard ListViews. When the list is displayed, it scrolls to the first item on the list, effectively hiding the header. When the list is short enough to be displayed entirely on screen, no scrolling is necessary, hence the “Tap to Refresh” button is always visible!

After an hour, I didn’t find a way to fix the issue of keeping the header hidden since hiding it would not make it disappear. That is when I came to a StackOverflow post  that basically told me to put the header in a LinearLayout that wraps it’s content, and hide the content so the wrapping LinearLayout collapses when its content is hidden, resulting in the header view being 0dip high and therefore invisible.

I find the solution very bizarre, but it worked out and that is what I am using right now. The only thing that still upsets me, is that the feature is not polished enough. It is still sluggish to pull, flicks once in a while, and lacks animation.

I will get back to this post once I figure out a better solution, if any. I am counting on you – Android devs – to help me out  ;)

EDIT:

Found a library that provides a very good user experience. Full story here.

Android Saga: Applying an image as the background pattern of a ListView

06/23/2012 § 2 Comments


This is the first (I hope) of many episodes of an epic saga where an iOS developer (me) adventures himself in the (so far painful) Android developers world.

Before we get started, let’s get synced. Long before mankind (back in 2007), when Android was on a very early stage, I got all fired up and started one (if not THE) first Android community in Brazil. It turns out I ended up working with iOS on the next year (which won my heart) and since then I have not write a single line of Android code. So, today I am nothing but an iOS developer struggling to build an Android application that actually feels as good as an iOS app.

We all know iOS has such appealing features that Android still lacks, like smooth scrolling apps, list views that are able to nicely bounce, a simulator that is a piece of cake and system upgrades ;P

But I am not going to write bad stuff about Android trying to make iOS shine. I am actually following an advice of a friend of mine (idevzilla). After hearing me mumbling for a couple days, he got tired and told me to go share the experience of coming out from the iOS platform and diving into the Android SDK.

Personally I hope Android experts will come to me and show me better ways of writing Android code so that I can get the user experience I want for my Android app.

Since every awesome app is made of tiny little details, let’s get started with one: apply an image as the background pattern of a ListView (equivalent to UITableView).

Let’s start with Android.

After an hour researching on how to do this, I found out that Android requires the creation of a XML file that describes a bitmap which the source is the image I want to use as the pattern and the tile mode is repeat. This file must be placed under a drawable folder.

res/drawable/app_background.xml

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
 android:src="@drawable/background_pattern"
 android:tileMode="repeat" />

Then we need to create a set of styles for the ListView that use this bitmap and tell the app it should use those styles.

Running the app I saw that nice background. Then I scrolled down the list and it became black. I lifted my finger and then the background was there again (WTF!?).

It happens by default an Android View has a transparent background and transparency involves a lot of calculation when rendering your application on screen. In order to avoid blending and make the rendering faster while scrolling, the ListView widget uses a cache mechanism. This mechanism consists on “turning opaque the view hierarchy”. So I researched a little more until I found out that I needed to set the cache color hint to “transparent”. This solves the issue but also disables the optimization we just discussed.

res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="app_theme" parent="android:Theme">
 <item name="android:windowBackground">@drawable/app_background</item>
 <item name="android:listViewStyle">@style/TransparentListView</item>
 <item name="android:expandableListViewStyle">@style/TransparentExpandableListView</item>
</style>

<style name="TransparentListView" parent="@android:style/Widget.ListView">
 <item name="android:cacheColorHint">@android:color/transparent</item>
</style>

<style name="TransparentExpandableListView" parent="@android:style/Widget.ExpandableListView">
 <item name="android:cacheColorHint">@android:color/transparent</item>
</style>
</resources>

AndroidManifest.xml

<application
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/app_theme">

Okay. This works out. BUT…I want the background to scroll together with the ListView so the user feels he is actually moving the list down or up.

Unfortunately the only way I found to achieve this goal is to forget about that styles.xml file and undo the changes to the AndroidManifest.xml file. Instead, we need to create a layout file for the list item (equivalent to UITableViewCell) and add the following to the root Layout element:

 android:cacheColorHint="@android:color/transparent"
 android:background="@drawable/app_background"

This however will not disable any highlights caused by the list selectors…but this post already got too long.

Let’s ignore this issue for a moment and see how iOS handles this.

self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-pattern.png"]];

That is all for today.

Tracing routes with MapKit

05/22/2012 § 23 Comments


Presenting a map to the user is a common feature of mobile apps. And very often this feature comes with an additional requirement: to trace the route from the current user location to some arbitrary destination. The thing is, most apps accomplish this last requirement by adding a button to the right navigation item that opens up google maps on the browser. But usually this is not the best user experience.

Most developers don’t know this (and I was one of them not too long ago), but it is possible to use the MKMapView to easily render paths between to locations. There isn’t however (for now) any native APIs that magically handle this kind of drawing.

iOS handles routes using MKOverlay objects (just like it handles pins using MKAnnotation). There is a native MKOverlay class called MKPolyline which consists of an array of CLLocationCoordinate2D structures that MKMapView knows how to draw.

The thing is: We know only two locations (coordinates). The current one (our origin) and the place’s location (the destination). AND we need all the coordinates in between these two end locations describing a smooth path following the roads and streets considering traffic and so on, in order to properly create the MKPolyline object and add that to the map.

This is where Google Directions API comes in. Google offers an API (both JSON and XML) that among other options let’s you specify two locations and returns a complex set of information containing all sorts of data, like routes (with alternatives), waypoints, distance and directions (instructions). At first, you might look to the documentation and think that you may need to write a parser, iterate through the structure and grab what you need. That is exactly what you need to do, but not as difficult as it seems. The information we are looking for is available as a string named overview_polyline available under the route tag. Just grab that.

If you are using JSON (the recommended output), there are a lot of third-party libraries out there that represents a JSON string as native data structures such as NSArray, NSDictionary and NSString. Now if you are really lazy (and smart), then you use some sort of library like AFNetworking to handle requests and get for free JSON parsing right on the response callback.

Almost every step of the process is a piece of cake until here. The MapKit has a native overlay view that knows how to display a route. The route is given to you for free and with almost no efforts by Google and AFNetworking provides you automatic parsing of the response Google sent you.

The only remaining detail is: Google Directions API gives us a string representing the route and we need an array of CLLocationCoordinate2D structures.

Fortunately the Encoded Polyline Algorithm Format used by google is fully described in the docs and an Objective-C implementation was made available by Ankit Srivastava on stackoverflow.

For those lazy guys who are in a hurry, good news: There is a code snippet below for every point of our discussion.

(WordPress sucks when it comes to presenting source code, but there is a “View Source” button that lets you copy the code and properly paste it! But just in case you wish to read the code I have also attached a file here ;)

  • Create the Map View
_mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
_mapView.showsUserLocation = YES;
_mapView.delegate = self;
[self.view addSubview:_mapView];
  • Once you have the current location, define the map region you want to be visible:
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(self. location.coordinate, REGION_SIZE, REGION_SIZE);
MKCoordinateRegion adjustedRegion = [_mapView regionThatFits:viewRegion]; [_mapView setRegion:adjustedRegion animated:NO];
  • Also request Google Directions API to retrieve the route:

AFHTTPClient *_httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://maps.googleapis.com/"]];
[_httpClient registerHTTPOperationClass: [AFJSONRequestOperation class]];

NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:[NSString stringWithFormat:@"%f,%f", location.coordinate.latitude, location.coordinate.longitude] forKey:@"origin"];
[parameters setObject:[NSString stringWithFormat:@"%f,%f", endLocation.coordinate.latitude, endLocation.coordinate.longitude] forKey:@"destination"];
[parameters setObject:@"true" forKey:@"sensor"];

NSMutableURLRequest *request = [_httpClient requestWithMethod:@"GET" path: @"maps/api/directions/json" parameters:parameters];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

AFHTTPRequestOperation *operation = [_httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id response) {
	NSInteger statusCode = operation.response.statusCode;
	if (statusCode == 200) {
	 [self parseResponse:response];

	} else {

	}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];

[_httpClient enqueueHTTPRequestOperation:operation];

  • Get what you need:
- (void)parseResponse:(NSDictionary *)response {
 NSArray *routes = [response objectForKey:@"routes"];
 NSDictionary *route = [routes lastObject];
 if (route) {
 NSString *overviewPolyline = [[route objectForKey: @"overview_polyline"] objectForKey:@"points"];
 _path = [self decodePolyLine:overviewPolyline];
 }
}
  • And use the code provided by Ankit Srivastava:
-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr {
 NSMutableString *encoded = [[NSMutableString alloc] initWithCapacity:[encodedStr length]];
 [encoded appendString:encodedStr];
 [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
 options:NSLiteralSearch
 range:NSMakeRange(0, [encoded length])];
 NSInteger len = [encoded length];
 NSInteger index = 0;
 NSMutableArray *array = [[NSMutableArray alloc] init];
 NSInteger lat=0;
 NSInteger lng=0;
 while (index < len) {
 NSInteger b;
 NSInteger shift = 0;
 NSInteger result = 0;
 do {
 b = [encoded characterAtIndex:index++] - 63;
 result |= (b & 0x1f) << shift;
 shift += 5;
 } while (b >= 0x20);
 NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
 lat += dlat;
 shift = 0;
 result = 0;
 do {
 b = [encoded characterAtIndex:index++] - 63;
 result |= (b & 0x1f) << shift;
 shift += 5;
 } while (b >= 0x20);
 NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
 lng += dlng;
 NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
 NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];

CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
 [array addObject:location];
 }

return array;
}
  • Create the MKPolyline annotation:
NSInteger numberOfSteps = _path.count;

CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
 CLLocation *location = [_path objectAtIndex:index];
 CLLocationCoordinate2D coordinate = location.coordinate;

 coordinates[index] = coordinate;
}

MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[_mapView addOverlay:polyLine];
  • And make it visible on the map view:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
 MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
 polylineView.strokeColor = [UIColor redColor];
 polylineView.lineWidth = 1.0;

 return polylineView;
}

Please note the code snippets provided on this post doesn’t have any error handling neither are optimized. Remember to fix these issues before copying them to your application.

Natural Code Just Works.

01/13/2012 § 2 Comments


As soon as I heard about ARC I thought “WOW, this is amazing! A compiler-time garbage collector! Why didn’t anyone think about this before!?”.

But then even after migrating to iOS 5 I got a little scared about changing the compiler and the whole memory management schema that I have been using my entire life.   Actually I was waiting to being able to work on a new project so that I could start using these new concepts. It turns out I couldn’t wait anymore and decided to migrate this huge project I am working on to ARC. Not only for the promise of “running faster”, but also for education (in the end I love to explore and learn new ways of writing code).

After migrating the source code by using the automatic migration tool provided by Xcode 4.2.1 (and set the Simulator as deployment target hahahah) I was immediately able to see that natural code just works. That is the way Apple wants us to think about using ARC. And my impression tells me this is totally possible.

But I am a man full of questions about the meaning of life and all this crap, so I couldn’t just believe on that and started to watch some ARC talks Apple has done to comprehend how this magic works behind the scenes. Truth is I can’t live with something I don’t understand when it comes to coding.

Although ARC is pretty simple, here are some annotations I have made that really helped me to understand “da magic”.

First of all there are 5 things you cannot forget:

1) Strong references. Every variable is a strong reference and is implicit released after it’s scope ends. A strong reference is the same thing as a retained reference that you don’t manage. For example:

When you declare NSString *name; the compiler understands you actually meant __strong NSString *name;. And this means you don’t need to retain the reference nor release it afterwards anymore.

- (id)init
self = [super init]; 
if (self) { 
name = [@"Name" retain]; 
}

return self;

}

- (void)dealloc
[name release]; 
[super dealloc];

}

becomes

- (id)init
self = [super init]; 
if (self) { 
name = @"Name"
return self;

}

2) Autoreleasing References. Every out-parameter is already retained and autoreleased for you.

- (void)method: (NSObject **)param { *param = …; } 

means

- (void)method: (__autoreleasing NSObject **)param { 

*param = … retain] autorelease];

}

3) Unsafe references. If you see this, keep in mind you are working with a non-initialized, no-extra compiler logic and no restrictions variable. An unsafe reference tells ARC not to touch it and as a result what you get is the same as an assign property. The advantage here is: you can use this inside structs. But be warned this can easily dangling references.

 __unsafe_unretained NSString *name = name; 

4) Weak References. Works like an assign property, but becomes nil as soon as the object starts deallocation.

 __weak NSString *name = name; 

If you want to create a reference weak, just add __weak before the variable declaration or weak to the property instead of the old assign parameter.

5) Return Values. They never transfer ownership (ARC does a retain and returns a autoreleased object for you) unless the selector starts with alloc, copy, init, mutableCopy or new. In these cases ARC returns a +1 reference (for you), which you also don’t need to bother with on the caller side due to the rules we discussed above.

Now that you know how ARC works and what it does, you can write natural code in peace =)

Follow

Get every new post delivered to your Inbox.

Join 37 other followers