Posts Tagged iPhone

Use tap events instead of click events in iPhone browser

When working on a web app for embedding in a iPhone application we came across jQTouch, a really nifty little jQuery plugin which makes it easy to create a web application UI that really resembles that of a native iPhone application.

We soon encountered a problem due to the fact that click events are rather slow to fire on the iPhone. There is a delay due to the fact that the iPhone waits for the user to complete a gesture before deciding that the intended gesture was in fact a click.

JQTouch uses divs to navigate between screens, so for example if you have the div

<div id="primary-view"></div>

you can simply navigate to it through a normal anchor link, and the transition will thanks to jQTouch be really “iPhone like”.

<a href="#primary-view">Primary view</a>

Our main problem is that we load our content dynamically through Ajax. So our links looked like this:

<a onclick="fetchContent();" href="#primary-view">Primary view</a>

This resulted in a race condition. The anchor link listens to the tap event which is fired much earlier than the click event, and therefore we mostly ended up in empty views. So we needed to replace all onclicks to ontap listeners. The problem then is that we could no longer test our webapp in a normal desktop based Safari browser.

So, we decided to happily go along and write inline onclick events on our links and other interaction elements. But while in the iPhone we see to it that the onClicks are removed and replaced with tap listeners.

That function looks like this:

function rebindClicks(){
    var userAgent = navigator.userAgent.toLowerCase();
    var isIphone = (userAgent.indexOf('iphone') != -1) ? true : false;
 
    if (isIphone) {
        // For each event with an inline onclick
        $('[onclick]').each(function() {
            var onclick = $(this).attr('onclick');
            $(this).removeAttr('onclick'); // Remove the onclick attribute
            $(this).bind("click", preventClickEvent); // See to it that clicks never happen
            $(this).bind('tap', onclick); // Point taps to the onclick
        });
    }
}
 
function preventClickEvent(event)  {
    event.preventDefault();
}

We now call this little function everytime the DOM is changed. If something turns up with an inline onclick. It is will be rerouted by jQuery to a tap listener instead.

Again, we felt we needed to do this because many of our developers do not have a Mac (and hence do not have the iPhone simulator). And testing on the iPhone can be really time consuming. So for testing during development we wanted to use onClick, and when testing on iPhone we wanted to use taps instead.

But the biggest bonus was without a doubt that things are overall much faster in the web application. Taps fire much faster than clicks in the iPhone.

Here’s how it looks running the same app both in desktop safari and embedded into the iPhone simulator.

, ,

No Comments

Submitting iPhone app to App Store

Finally, after two bounces and three weeks of waiting, our first app on App Store is available!

I’ll keep this post really short!

Pros

  • Great testing by the App Store review team.
  • Good and thorough feedback.
  • Cons

  • Time consuming! But, reasonable considering the amount of apps that is submitted to the App Store.
  • iTunes Connect
  • Some good to knows!

  • It takes approximately 5 working days before you hear anything from the review team.
  • If you reject (developer reject) your application and post a new version when an app is undergoing a review, then you will have to wait another 5 more days.
  • Conclusion

    The App Store review process: 4 stars out of 5

    Projectplace for iPhone

    If you are curious about our iPhone application, please visit our app section @ App Store.

    , , , , ,

    3 Comments

    Use Flex and set it free

    I work at Projectplace Labs. In fact I’m managing it. No doubt it’s the best job I’ve ever had. Imagine getting payed for experimenting with far out things all day. Two examples:

    Samuel is da man!

    Samuel is da man!

    • Samuel, who also works at the lab and blogs on this site, started to play with the iPhone SDK some month ago and just yesterday he sent a Projectplace client for the iPhone to AppStore. It should appear there any day soon. Computer Sweden wrote about it today (Swedish).
    • A year ago I tried out Sandy3D (awesome 3D engine for Flash written in AS3) and quickly got a prototype up for a Cooliris-inspired photo wall, it was WOW to me so I called it WowAlbum. Not as immediately business applicable as Samuel’s iPhone app, but a fun thing to do.

    Projectplace Labs is very much inspired by those big, innovative, forces out there. Mozilla Labs, Microsoft Office Labs, Adobe Labs and, of course, Google Labs. Google is probably our main inspirational source. We’re trying to reverse engineer Google’s innovation machine and apply what we feel fits us (or at least try to convince our managers to let us apply it). We’ve also taken Quincy Jones’ receipt for success to our hearts;

    Hire the best and set them free.

    We apply it on all levels. Ideas, creativity, people, innovation, inspiration, code, joy, love. Unleash!

    Yap - planning made fun

    Yap - planning made fun

    Ummm, I was definately not planning to write about Projectplace Labs in this blog. Got a bit carried away there. I was mainly about to use the Bagonca server to make a development version of Yap available to a guy I’m working with at A-Dato. Then I thought, heck I can blog about it, and then I felt I needed to tell about where I work.

    And now I need to tell you something about Yap too, right? You can read a little about it at Projectplace Labs and also at Projectplace Ideas. To cut a long story short:

    We, Projectplace, want to be the company who made project planning fun.

    That development version of Yap that you can access even before it appears on Projectplace Labs? Don’t worry, I haven’t fogotten, here goes:

    Now, how cool does this make Bagonca? It even publishes Projectplace Labs stuff before Labs! =)

    , , , , , , ,

    6 Comments

    iPhone tip #2 – What is my current location?

    The iPhone has GPS built-in, which makes the phone really powerful and enables developers to innovate cool and cutting edge applications!

    The iPhone devcenter has some sample code explaining how the CoreLocation framework works. But, I found that example a bit hard to understand…

    Here is an easier way of finding your current location from your iPhone.

    Let’s start with the interface/header file.
    CurrentLocationController.h

    #import <CoreLocation/CoreLocation.h>
     
    @interface CurrentLocationController : NSObject <CLLocationManagerDelegate> {
    	CLLocationManager *locationManager;
    }
     
    @property (nonatomic, retain) CLLocationManager *locationManager;
     
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
     
    @end

    Note: Our object “implements” the CLLocationManagerDelegate protocol. We “implement” two methods, locationManager:didUpdateToLocation:fromLocation: and locationManager:didFailWithErrorfrom :, from CLLocationManagerDelegate. The first method is invoked when a new location is available and the second one if an error has occurred.

    Here comes the implementation:

    #import "CurrentLocationController.h"
     
    @implementation CurrentLocationController
     
    @synthesize locationManager;
     
    - (id) init {
        self = [super init];
        if (self != nil) {
            self.locationManager = [[[CLLocationManager alloc] init] autorelease];
            self.locationManager.delegate = self;
        }
        return self;
    }
     
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
        NSLog([newLocation description]);
    }
     
    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
        NSLog([error description]);
    }
     
    - (void)dealloc {
        [self.locationManager release];
        [super dealloc];
    }
     
    @end

    The only important thing to note is the line

    self.locationManager.delegate = self;

    . Here we set our own object as the delegate, which means that all the location messages will be forwarded to CurrentLocationController.

    I hope this will give you more time innovating, instead of developing Trichotillomania.

    , , , , , , , ,

    5 Comments

    iPhone tip #1 – URL encoding in Objective-C

    If you are n00b when it comes to iPhone development, then you’ve come to the right place! We’ll be posting howtos, tips and tricks continuously.

    So, how do you URL enconde a string? It’s quite simple if you know how. :)

    + (NSString *)urlEncodeValue:(NSString *)str
    {
    NSString *result = (NSString *) CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR(:/?#[]@!$&’()*+,;=”), kCFStringEncodingUTF8);
    return [result autorelease];
    }

    To create an URL object, do like this:

    [NSURL URLWithString:encodedUrlString]

    , , , , , , ,

    6 Comments