Archive | iPhone Development

Successful iOS Background Location reporting

We’re working on a location product right now and one of the little challenges along the way has been how to report background location updates back to our servers.

First, some basics.

We’re going to be using the Significant Location Changes feature introduced with iOS 4 as this is the recommended way of tracking the approximate device location in a low power way. As always, the Apple documentation is excellent and is worth reading so you are aware of the detail.

Note the really key features here;

a) If the application is suspended when an update occurs, the system wakes it up in the background to handle the update.

b) If the application starts this service and is then terminated, the system relaunches the application automatically when a new location becomes available.

That’s just perfect, so what we can now do is turn on significant location updates when the user hits the home key and we can let the system wake us up when needed.

-(void) applicationDidEnterBackground:(UIApplication *) application
{
    // You will also want to check if the user would like background location
    // tracking and check that you are on a device that supports this feature.
    // Also you will want to see if location services are enabled at all.
    // All this code is stripped back to the bare bones to show the structure
    // of what is needed.
 
       [locationManager startMonitoringSignificantLocationChanges];
}

Then to perhaps switch to higher accuracy when the application is started up, use;

-(void) applicationDidBecomeActive:(UIApplication *) application
{
       [locationManager stopMonitoringSignificantLocationChanges];
       [locationManager startUpdatingLocation];
}

Next you’ll likely want to change your location manager delegate to handle background location updates.

-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    BOOL isInBackground = NO;
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
    {
        isInBackground = YES;
    }
 
    // Handle location updates as normal, code omitted for brevity.
    // The omitted code should determine whether to reject the location update for being too
    // old, too close to the previous one, too inaccurate and so forth according to your own
    // application design.
 
    if (isInBackground)
    {
        [self sendBackgroundLocationToServer:newLocation];
    }
    else
    {
        // ...
    }
}

OK, so now to the crux of it all. If we are running in the background, we can’t just use the network as we would normally. In background mode the iOS controls very strictly what is allowed, and for how long it is allowed, so if we were just to send the location to our server as normal, we will find this will be highly unreliable. It may work sometimes, it may not, and you will have no control over what is going on.

We can however TELL the operating system in advance that we are doing a background task that should be allowed to run to completion. By doing this, we can ensure that our network activity is given enough time to complete and so the remote server will get the location updates OK.

-(void) sendBackgroundLocationToServer:(CLLocation *)location
{
    // REMEMBER. We are running in the background if this is being executed.
    // We can't assume normal network access.
    // bgTask is defined as an instance variable of type UIBackgroundTaskIdentifier
 
    // Note that the expiration handler block simply ends the task. It is important that we always
    // end tasks that we have started.
 
    bgTask = [[UIApplication sharedApplication]
               beginBackgroundTaskWithExpirationHandler:
               ^{
                   [[UIApplication sharedApplication} endBackgroundTask:bgTask];
                }];
 
    // ANY CODE WE PUT HERE IS OUR BACKGROUND TASK
 
    // For example, I can do a series of SYNCHRONOUS network methods (we're in the background, there is
    // no UI to block so synchronous is the correct approach here).
 
    // ...
 
    // AFTER ALL THE UPDATES, close the task
 
    if (bgTask != UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication} endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }
}

The key to this whole process is the use of background tasks to ensure that our synchronous network activity is given enough time to complete. This lets us update a couch database for example where we might need to make 1 network call to get the current document revision and then a second network call to actually PUT the new data.

Posted in iPhone Development4 Comments

Viewing iFolder’s FLAIM store with StoreBrowser

In the midst of debugging login issues with Novell’s iFolder, I stumbled over this post about a tool for accessing the FLAIM database that underpins the whole system.

One of the problems is that the tool itself seems to have vanished from the trunk repository and so its existence was not at all obvious. There seem to be a few people having problems finding it and so I thought it worthwhile including the storebrowser files here so that you can get up and running more easily.

I’m going to document running StoreBrowser on your SERVER first. I’m assuming that you have a standard installation running on OpenSUSE 11.3 as that seems the best open source option at the current time (April 2011).

1) Download the zip package and unzip to a suitable location on your system.

2) Open a terminal window and navigate to the folder containing the StoreBrowser.exe file. It is important that you cd to this location as otherwise you will not be able to run it correctly.

3) Copy the asmx file to the appropriate place. This is OS specific and this guide is for OpenSUSE 11.3

cp SimiasBrowser.asmx /usr/lib/simias/web/

4) Ensure you have the directory ~/.local/share/ you may well need to mkdir ~/.local and then mkdir ~/.local/share .This location is used by the application to store its config data and it won’t auto create it, it will just complain.

5) if  echo $DISPLAY shows nothing in your terminal, enter the following command

export DISPLAY=:0.0

It is important to set the display otherwise mono will abort with an error like this;

Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for System.Windows.Forms.XplatUI —> System.ArgumentNullException: Could not open display (X-Server required. Check you DISPLAY environment variable)

6) mono StoreBrowser.exe

If all is well, the application should launch with an empty window. First click on file and select Open Store as shown below;

After selecting Open Store, you will need to enter the url for the local simias store. For example this will typically be http://localhost/simias10

Click on OK and assuming all is well, you will be prompted to login. You need to enter your ADMIN username and password in order to access the store, normal user accounts won’t do.

Once logged in, you will see the store tree to the left, however there is actually more to see but it’s hidden to the right of the window. To make it visible, drag the bottom right corner of the application window to enlarge it, and then drag to the left the dividing line that you will be able to see when you enlarge the frame.

You should end up with something that looks like this;

If you expand the Store and select an entry, you will get screens like this;

You can edit items by double clicking them. BUT FIRST A WARNING. MAKING ANY CHANGES TO A LIVE SYSTEM COULD RESULT IN THE LOSS OF YOUR DATA. This is a low level debugging tool that should be wielded by experts (feel free to get in touch if you know any!) and making changes could leave your system in an unstable state. Don’t go editing and deleting things and then complain to me afterwards that all your users have lost their data … it will be your fault not mine.

Don’t say I didn’t warn you …

 

 

Posted in iFolder, iPhone Development0 Comments

iFolder for iPhone now available!

UPDATE: The first release is now available in the app store. At the moment it’s US only but we expect to do a global release by the end of February 2011.

Available in the US App Store

We’ve just put the finishing touches to our iFolder for iPhone app and are recruiting enterprise beta testers who have their own iFolder installation. The easiest way of describing iFolder is probably to say that it’s dropbox for the enterprise – it’s a cross-platform secure file sharing system originally developed by Novell and now open sourced. There are existing open source clients for Windows, Apple Mac and Linux, but mobile support is currently limited (well, non-existent).

You can check out the app and apply for the beta programme over at ifolder.mindsizzlers.com

Posted in Development, Featured, iPhone, iPhone Development, News0 Comments

Writing Apps for iPhone OS3, 3.2 and iOS4

The recent launches of iPad and iPhone4 have led to a flurry of activity on the iPhone operating system front. iPad launched with iPhone OS 3.2 but this OS was never destined for iPhone itself. iPhone 4 has introduced another OS release, with a nameshift from ‘iPhone OS’ to ‘iOS’ 4. iPhone and iPod users are expected to migrate to iOS 4, but the upgrade isn’t mandatory. Eventually no doubt the iPad will join iPhone on a universal OS, in the meantime, you’re likely to find that your having to support three, and maybe more, different versions of the OS, across various devices.

When you’re coding for a specific OS, you should not look at the version number and base your logic on that. Here is an example of what to avoid:-

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2)
        { /* do iPad stuff here */ }
    else
        { /* do iPhone stuff here */ }

Whilst that is a perfectly legitimate way to be looking up the OS version, in reality you are less interested in the OS version per se so much as the capabilities of the underlying OS. Code that might work today can easily break. Here for example, you iPad intended code is going to run on iPhone’s upgraded to iOS4.

Instead, you should use the class method available to NSObject and all descendants:-

+(BOOL) instancesRespondToSelector: (SEL) aSelector

So you could write, for example:-

if ([[UIApplication sharedApplication] respondsToSelector: @selector(setStatusBarHidden: withAnimation:)])
        { [[UIApplication sharedApplication] setStatusBarHidden: YES withAnimation: UIStatusBarAnimationFade]; }
    else
        { [[UIApplication sharedApplication] setStatusBarHidden: YES animated: YES]; }

Here we test whether we use the method setStatusBarHidden: or the newer method setStatusBarHidden: withAnimation:. This will compile and run under different OS versions and give us the required means to act according to OS capabilities.

This test can be particularly important when writing for newer version of the OS but looking to support older ones. Occasionally additional classes and methods that have previously been private are promoted to public use and are documented, but using these under older OS’s will still trigger the automatic rejection for using undocumented methods in the Cocoa Touch libraries. For example, UINib is a new class made available in iOS 4.0 for working with cached NIB files. Although this class was always there, it used to be out of bounds. Using this class in an app written for iPhone OS 3.x will lead to rejection. Testing methods for this class with ‘respondsToSelector’ will only return true if the method is public and you are entitled to work with it.

If you are looking to change screen layouts or other functionality depending on the actual device, Apple have created a new property of a UIDevice object. This macro will test whether you are on an iPad (UIUserInterfaceIdiomPad) or iPhone/iPod Touch (UIUserInterfaceIdiomPhone).

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
     {     /* The device is an iPad running iPhone 3.2 or later. */ }
else
      {  /* The device is an iPhone or iPod touch. */ }

Wrap this around views where you want to achieve different layouts according to the screen sizes, and anywhere else that you have iPad specific behaviour.

Posted in Development, iPhone, iPhone Development, Objective-C0 Comments

Delegation and Notifications, Oddities or Pure Elegance?

Objective-C and Cocoa Touch are strong on design patterns and principles. If you adhere to Apple’s way of coding then you’ll create reliable and reusable code. If you’re new to Objective-C, some of the design principles can be quite daunting and if your background is in other object oriented languages, some of the design patterns may initially appear quite alien.

Delegation and notifications present two such slightly odd patterns, but once you understand them they are actually rather elegant in what they achieve.

Delegation

Most people describe delegation as a method of subclassing, and essentially that’s right. Delegation wouldn’t exist though if it were simply an alternative to subclassing, so you can be sure that it solves other problems. I like to think of delegation almost as a work in progress – a class knows what it has to achieve and is implemented accordingly, but delegation allows a broad class to be written in such a way as to leave the final detail to future imagination. This is achieved by assigning your object as a delegate to a predisposed object; your new object can implement a bunch of methods that will be called by the delegating object whilst benefiting from the much broader underlying library.

The most common use of delegation must be handling UITableViews. The core Cocoa Touch library implements nearly everything a table requires in order to handle display itself, but how the cells are laid out, how your app responds to touches and so on is all left to your implementation. Most of the table handling code is given and you need not concern yourself to the inner workings, but you have to complete the final part – you must define how many sections there are in your table, how many cells in each section, how each cell will be laid out, whether there is a disclosure button and what should happen if the table is selected. All of this behaviour is defined by you – you are offered templated ‘hooks’ that you can fill in or remove depending on how you want your actual implementation to behave. Sometimes delegate methods are required to be completed, other times they are optional.

Cocoa Touch uses delegation extensively, indeed the main application is executed via delegation, hence your appDelegate. You’ll come across delegation in many other situations as you start creating apps for the iPhone and iPad.

Notifications

Another peculiar design pattern in Objective-C is that of notifications – that’s NSNotifications, not the more recently implemented Push Notifications. Notifications are very different to delegation and yet they share a common goal – both offer a way for remote classes to interact with your own objects.

An app has a ‘notification centre’ that is like a central switchboard within your app. Any method can send notices to the notification centre as it does its work. Any object can ‘tune in’ to the notification centre, choosing to listen to all broadcasts, or just to notices relating to particular topics. The API’s that you use with Cocoa Touch broadcast messages extensively in the background. You won’t be aware of this until you subscribe to notifications, and suddenly you’ll be inundated with reams of information as your app goes about its duties!

You can take advantages of notifications by responding to events that you wouldn’t otherwise have visibility of. For example, MPMoviePlayerController prior to iPhone OS 3.2 gave almost no access to know when a movie was stopped, started or when other buttons were pressed. Monitoring when a movie was stopped was widely documented – you subscribed to the relevant notification that the movie had stopped. But you could also subscribe to other notifications for other events triggered by the player controller and implement your application’s response accordingly.

In the same way that delegates can be used for a remote object to call a method on your own object, so notifications can be used as a way of triggering methods in your classes from a remote object. Whilst delegates can only have one object respond to them, notifications allow for many objects all to respond to a single event. Beware if you are working in a multithreaded environment because you can only subscribe to notices broadcast within your own thread.

Final Words

Delegation and notifications offer two design patterns used widely in Cocoa Touch, there are many more besides. All in all they each offer a distinct way of achieving some task; on the whole they add flexibility to the main workings of many of the Cocoa API’s, decoupling the bulk of the workings from the finer implementation. Often they allow the programmer to achieve some monumental tasks in just a few lines of code. How many lines of code to implement a table? …now consider how easily you could do it just using views and subviews and coding it from scratch!

Delegates and notifications are not the exclusive preserve of Apple – you too can create your own delegates and fire your own messages to the notification centre. Once you are familiar with Apple’s design patterns, perhaps you will adopt best practice and model them in your own classes?

Posted in iPhone Development, Objective-C0 Comments

Web Apps vs. Native Apps

When the iPhone was first launched, it didn’t launch with a marketplace for apps – indeed Apple didn’t even enable programmers to create applications for the platform at all. Quite quickly though, people worked out that you could create a web based application and style it specially to run in the iPhone screen. The Web App was born, and Apple quickly embraced this entrepreneurial approach by setting up a Web App directory. To have an app listed you just have to submit your URL to Apple and if it conforms to their loose rules and guidelines, it will be added to their listings.

The iPhone runs a very competent and capable Safari web browser which supports current web standards. Interactivity can be achieved using Javascript, there are even a few proprietary extensions to HTML and Javascript (undergoing formal approval to become standards) to cater for some of the capabilities of a touch and multitouch environment.

With the success of Web Apps, Apple took the bold decision to open up the iPhone platform to any programmer, making the SDK freely available, introducing a nominal fee to join their developer program, adding app support into iTunes and introducing a revenue-share model for app publishers. This was a game changing move which other mobile platforms have tried to replicate with mixed results.

Native applications are written in Objective-C, a superset of C and C++, and the SDK includes hundreds of API’s and libraries that allow any programmer to create the true ‘iPhone experience’ for their own applications. There’s a steep learning curve for anyone that hasn’t developed for the Mac platform before, but it’s a rewarding experience – Objective-C is an elegant language and the rich SDK often makes complex tasks relatively straightforward.

Programmers can still create web applications in favour of native applications, and if you don’t want formal listing in the app store or the web app directory, then there are no restrictions on what your app can do, how it behaves or on your business model – you can encourage people to add your app to their iPhone from your own website. However, you cannot recreate the rich experience of native applications, and such apps require an internet connection at all times. Much of the iPhone experience is down to the Wow factor given by:-

  • the animated interface
  • tab and navigation controllers
  • access to the camera, contacts and iTunes library
  • access to location information, compass data and movement data from the accelerometer

Most of this can only be replicated in a web app in a ‘hacky’ way that won’t make your app stand out, and doesn’t do the platform justice.

You can create ‘hybrid’ applications for the iPhone and many apps in the store take this approach. They take advantage of the native SDK to give the app the overall iPhone navigational experience, but they are filled with HTML content, either stored locally or on a remote web server. If your company has web content that you want embedded in your app, then this presents a great way to do this without having to maintain different information sources. Beware that apps taking this approach may display no content if there isn’t an internet connection, and part of Apple’s requirement is that apps handle lack of internet connectivity gracefully.

The ‘hybrid’ nature of such apps is achieved through a few simple mechanisms:

  • A screen (view) can contain a web ‘canvas’ (UIWebView) that you can populate with HTML, CSS and Javascript
  • The content of a UIWebView is addressed by a URN pointing to a local file or a remote resource
  • You can have multiple UIWebViews in a single screen (view)
  • Javascript can call out to Objective-C methods
  • Objective-C methods can call Javascript functions within a UIWebView

Learning just enough Objective-C to enable you to build hybrid applications is a great first step to learning how to do much more. At Mindsizzler’s we’re convinced that once you set out, you’ll enjoy the experience and will be thirsty to learn more!

If you need that introduction to learn how to create iPhone applications and achieve a good understanding of Objective-C, Xcode and the iPhone SDK then why not join in one of our training courses?

Posted in iPhone, iPhone Development0 Comments

Objective-C and the Properties of BOOL

At a basic level, boolean logic allows for a value to be either true or false, on or off, 1 or 0. The ways in which boolean types are implemented vary widely across languages and implementations. At the most granular level, computers work with bits that are either set to on or off, whereas some boolean data types in databases cater for three or even four values: 1, 0, null or undefined. Dennis Ritchie’s original C language lacked a boolean type at all but it was added in C99, and C’s primitive ‘bool’ type is available in Objective-C. ‘bool’ can be set to either true or false, 1 or 0.

Objective-C has implemented a more standard boolean property – it offers the BOOL type in addition to the primitive ‘bool’. The Cocoa and Cocoa Touch API’s use BOOL as the standard message response in favour of ‘bool’, so it is a property you must get to understand, and should code your own methods using BOOL as well.

Unlike most other things in Objective-C, BOOL is NOT an object, it is a raw data type. The standard values of BOOL are YES and NO rather than true or false, or 1 or 0. However, under the bonnet YES and NO are simply definitions given to the preprocessor as aliases for 1 and 0. In Cocoa Touch YES and NO are defined in NSObjCRuntime.h:-

#if !defined(YES)
    #define YES (BOOL)1
#endif

#if !defined(NO)
    #define NO (BOOL)0
#endif

This means that BOOL values are NEVER ‘YES’ and ‘NO’ so you cannot test them as such:-

if (myBOOL == 'YES') { ... }

…and they are NOT objects, so you cannot send the message:-

if ([myBOOL isEqualToString: @"YES"]) { ... }

Instead you must test them for true or false, or zero or non-zero:-

if (myBOOL) { ... }

or

if (!myBOOL) { ... }

If you want to log the value of a BOOL property using NSLog, then you can use the decimal signed integer format identifier %d:-

NSLog(@"MyBOOL value is %d", myBOOL);

Because BOOL represents 1 and 0 internally, you can also use the ternary operator to test BOOL values:-

myBOOL ? NSLog(@"Yes") : NSLog(@"No");

…and you can use this technique to convert between bool and BOOL should you so wish:-

mybool = myBOOL ? true : false;

Remembering that BOOL is NOT an object type makes it easy to remember how to declare BOOL properties, namely:-

BOOL myBOOL = YES;

…rather than using a pointer:-

BOOL *myBOOL = YES;

BOOL properties can be set with any of YES / NO, true / false or 1 / 0. All map back to 1 or 0.

Understanding that Objective-C’s BOOL data type is simply mapped to 1 and 0 makes working with BOOL values completely straightforward!

Posted in Development, iPhone Development, Objective-C2 Comments

KVO and Bindings on iPhone

‘Google’ for KVO and bindings for iPhone, and too many results tell you that KVO is not supported on the iPhone platform.  Well, if it wasn’t once, it is now, and it’s a really powerful feature.  KVO is Key-Value Observing – essentially you can add have one object ‘observe’ changes to a property of another object.  When that property changes, a callback is fired and you can trigger an action.  In many respects it’s similar to delegation or notifications, in this instance allowing a callback event to be triggered by changes in your objects.

KVO is commonly used to bind your application data to the interface so that whenever your data changes, the interface is automatically updated to reflect the change.  Here’s an example: imagine that you are writing a game and your score is stored in a property.  Rather than looping continually and updating the score on every iteration, you can observe your score and every time it changes, trigger the display to update automatically.

There are countless uses for KVO, and once you understand how it works, you will probably start using it regularly in your applications.  KVO also helps to implement a clean MVC architecture, although the callback MUST be implemented, so your view controller does require some prior knowledge of the architecture.

Implementation is really straightforward, but you do need to understand key-value coding.  Key-value coding (KVC) offers a different way to access properties of an object.  You’re probably familiar with:-

[anObject setProperty: @"Some string"];
 

or:-

anObject.property = @"Some string";
 

KVC allows you to access an object property by using a key, thus:-

[anObject setValue: @"Some string" forKey: @"property"];
 

If you are writing your own accessors you MUST comply with traditional naming conventions (setter = setPropertyName, getter = propertyName) because KVC assumes the names based on the key.  If you only need standard accessors, you can synthesize your properties and KVO works fine.

If you’re comfortable with that, then setting an observer is as simple as:-

[anObject addObserver:self forKeyPath:@"property" options: 0  context: NULL];
 

…then when ‘property’ in anObject is changed through the KVC method:

[anObject setValue: @"Some string" forKey: @"property"];
 

The observer fires an observer callback, passing in the key of the changed property.  By looking at the key value, you can trigger the appropriate work:-

- (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id)  object
change: (NSDictionary *) change context: (void *) context {
     if ([keyPath isEqualToString:@"property"] ) {
         // update your interface or do something else here...
     }
}
 

You MUST implement the observeValueForKeyPath: ofObject: change: context: method otherwise your app will crash.  Change allows you to access the old or new value, or both, and context allows you to pass in a pointer, enabling you to pass more information into your callback.

That’s pretty much all there is to KVO.  Observing can be quite resource intensive so try to avoid setting lots of observers.  If you want to track a lot of properties, look at implementing a single flag that can trigger work to update all of your properties.

Posted in iPhone Development, Objective-C1 Comment

MP Finder iPhone app released

MP Finder iPhone app released

Our latest iPhone application is a small demonstration of what can be achieved using the newly released data from The Ordnance Survey under the Open Data initiative combined with public domain data on Members of Parliament and Constituencies.

MP Finder locates where you are and then drops a pin on the map identifying your constituency and MP. No entering postcodes, searching for addresses, simply turn on and find your MP!

Visit the app store

Posted in Featured, iPhone, iPhone Development, News, Products0 Comments

OS Open Data Shapefile to KML

In early April the Ordnance Survey released a whole set of previously expensive geographic data into the Open Data initiative. The data is often in ESRI shapefile format as that is pretty much the norm for GIS software. That’s great if you are taking the data into a GIS workstation, but what if you want to turn the data into XML or JSON for use in a web service for example?

That was the problem I faced last week when working on the MP Finder application that should soon hit the Apple app store.

My specific goal was to turn the shapefile data into KML as an intermediate format which I could then write a perl parser for. KML is great as an intermediate format because I can visualise it in Google Earth to check that the export has gone OK and of course it is a structured document expressed in XML – so it’s perfect for machine parsing.

It turned out to be not quite as easy as I first thought.

The issue was the sheer length of some of the polygons in the shapefile, and more specifically northern Scotland which has a crinkly coastline to rival that of Norway. This was causing a lot of software to either crash, or silently dump the datapoints over a certain threshold. Not good.

The solution was to use the snappily named “ogr2ogr” tool which forms part of the toolset compiled by Frank Warmerdam and released as FWtools.

My first attempt was to use the simple command;

ogr2ogr -f KML output.kml input.shp

And whilst at first glance this seemed to have worked, the data points in the polygons were certainly not latitude and longitude. The problem was the map projections were not matching and after a bit of research and a big clue from stack overflow, I corrected the projection using the new command;

ogr2ogr -t_srs EPSG:4326 -f KML output.kml input.shp

Now we have a correctly projected KML file of the original shapefile data. You can test it by viewing it in Google Earth and more importantly, now that it is in KML it becomes trivial to write a parser to extract the data you might require … but that will be the subject of another post altogether.

Posted in Development, iPhone, iPhone Development0 Comments

Advert

For more information about our services…

Contact Us

Wordle of the Day

Image from software at http://wordle.net
Data by Web Trends Now

Categories