How to add an iPAD UIPopoverController style floating menu to your iPhone/iPod app

June 16, 2011 1 comment

The Problem :

You love that cool UIPopoverController class that Apple has added to the iPad. But wait a minute, why is it not there on an iPhone or iPod ????

I have no freakin idea!! But the developer community comes to rescue at times like this.

The Solution :

Enter WEPopover (github link) by Werner Altewischer. I believe he is from Netherlands. His simple yet effective implmentation will give you an almost UIPopoverController replica. Check out the github link for source code and example project. Have fun and Thanks Werner !

How to check for Network Connection in your IOS apps

June 16, 2011 4 comments

The Problem :

IOS apps need to handle network connectivity very carefully. An iOS user may travel from a Wifi connection to a 3G connection to a dead spot all while using your app. For this reason, Apple is extremely strict about developers handling network connectivity problems elegantly. They will outright reject your app if it errors out due to no network.

Why doesn’t Apple do it for me? 

Since this is such a common requirement, you must be wondering why IOS (even IOS5) doesn’t handle this for the app. All Apple has to do is allow developers to add a .plist setting called “NetworkRequired=1” and iOS should handle the error for you. Since, all network calls will go through iOS SDK stack, it should be able to catch the errors right?

The most obvious reason that comes to my mind about why they want you to handle the issue is – Only your App knows what to do when a network failure occurs.

  • Maybe the network failure is something which you don’t care about and the app can continue working.
  • Maybe it is a critical error and you need to notify the user about it.
  • Maybe your app can afford to retry the operation based on the nature of the network API call.

So, it makes sense for your app to handle the network issues.

The Solution :

So, the solution is very simple. First make sure that you have a helper class that you use to make every single network/API call. This way the network/API code is in one place. Easier to maintain and easier to add error handling.

In Loqly (iTunes Link), we use the below two functions to check for internet.

  • (BOOL) connectedToNetwork  is used when we just want to check for a network connection and not notify the user if an error occurs.
  • (BOOL) checkInternet is the same but automatically shows user an error message to notify him if no internet connection is present.

There is no rocket science here. In fact this code is available in one of Apple’s own samples and we have just used it in our app.

- (BOOL) connectedToNetwork
{
	Reachability *r = [Reachability reachabilityWithHostName:@"www.google.com"];
	NetworkStatus internetStatus = [r currentReachabilityStatus];
	BOOL internet;
	if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN)) {
		internet = NO;
	} else {
		internet = YES;
	}
	return internet;
} 

-(BOOL) checkInternet
{
	//Make sure we have internet connectivity
	if([self connectedToNetwork] != YES)
	{
		[self showMessage: @"No network connection found. An Internet connection is required for this application to work"
				withTitle:@"No Network Connectivity!"];
		return NO;
	}
	else {
		return YES;
	}
}

Someone has answered this question in great detail on Stackexchange as well
WARNING: As must be obvious from the above,  don’t use the IP address of a user to uniquely identify him for any purpose. Since the user could travel from wifi to 3G to edge to another wifi in minutes, his IP is likely to keep changing. UDID is a good option for this.

Solved : iPhone / IOS app stuck at loading state

June 14, 2011 1 comment

The Problem :

This is the 3rd time this has happened to me. Navigon, a GPS app which is huuuge (1.64 GB huge) in size gets stuck at loading status when downloading an update. Since the app takes 30 minutes to download, what happens is if I start the download and before it completes I move out of my wifi zone, it gets stuck at loading… This is what I have tried so far and failed miserably :

Failed Attempts (These have apparently worked for others, so feel free to try them if you want):

Rebooting the phone/Full Reset –>Keep the power button and Home Button pressed until you see the Apple Logo then let go = FAIL !
Paused the app download and Started it again = FAIL !
Opened Appstore and signed out of my Apple account, Signed back in to see if that helps = FAIL !
Pressed the Navigon icon long enough so that it starts dancing and attempt to delete it = FAIL !
Connected to my iMac and attempt to sync with ITunes = FAIL !

Solution :

After trying all of the above, what finally worked for me is this :

FIX 1:

  • Connect iPhone to your computer (Mac/PC)
  • In iTunes on your computer, uncheck the culprit application
  • Click Sync button
  • After sync is finished, you will notice that although iTunes on your computer thinks the app is gone, it will still show in stuck stage on your iPhone. Don’t worry coz the next step will fix this !!
  • Now check the app again in iTunes and sync again
  • Voila!!! It will get fixed. Phew !!!

FIX 2:

This one is weird and I came across it in a forum and didn’t believe it would work initially. But guess what? It works!

  • All you need to do is Settings->General->International->Languages–>Change to British English
  • This will cause the Springboard to soft reset and the stuck apps will automatically resume and download themselves!
  • You can now change the language back to US English or whatever (I am in U.S)

Beta testing your IOS Apps with TestFlightApp.com

You are almost done implementing that brilliant “iPhone app idea” in your mind and cannot control your excitement for sharing your iPhone app with the world.  But you know in your heart that, it is the programmer speaking within yourself.

The cold businessman/entrepreneur within you unfortunately knows, that there is a Beta testing period ahead where you will want to get at least 50-100 users to use your app, report bugs and suggest changes before you can even think of releasing the app to the AppStore.

The Problem :

The problem now is Apple has made it so difficult for you to do an Adhoc distribution for your app, it is nothing short of a nightmare. Let us start with a few things you would have to do for Ad-hoc dist :

  1. Find users of course, to test your app in Beta. These would ideally be non-technical users who represent a real audience, rather than you and your geeky friends doing the testing for you.
  2. Generate an AD-HOC cert from Apple developer portal, download it and sign your app with that
  3. Email all these non-techie users and ask them to send you their UDID (good luck with that!). Most probably they will think you are asking for their SSN !
  4. Add these UDIDs to the provisioning portal and download a new provisioning profile and update it in your project
  5. Make an AD-HOC build, create an .IPA file and email it to your beta testers.
  6. Get your beta testers to download the .IPA to their desktop, drag and drop it to their iTunes and sync their phone (again good luck with this! Nobody every syncs their iPhone to the desktop iTunes btw.)
  7. We tried to do this with Loqly (iTunes Link) and out of 80 users who were willing to help, 10 users replied with UDIDs and believe it or not, 2 users were able to install the app through iTunes.
  8. Now, imagine fixing a bug and sending out an update. In our case, only 1 person tried to update and his iTunes kept erroring out.

The Solution :

Enter the awesome folks at http://testflightapp.com. We discovered them when were on step 8 above. i.e our Beta testing was pretty much halted!! Testflightapp was in their Beta at that time. And they were God sent angels for us. Let us see how testflight helped us :

  • Step#1 and #2 above – We had to take care of it ourselves of course.
  • Step# 3 – You add a user’s email ID to testflight app and it automatically emails them and the moment they click accept/register on their iPhone, their UDID magically shows up in testflight app portal.
  • Step#4,#5 – You still do it manually
  • Step#6 – This is where the magic happens. The beta tester gets an email on his IOS device, he clicks the install button and bam! the app is installed.
  • Once we integrated testflightapp.com, we got 70 users to do our beta testing for us.

Bottomline : As you may have noticed, there is nothing magical about testflightapp, since it just adds a layer on top of what Apple offers you. But the key is to notice that they have taken care of the main pain points. i.e Getting the users to Signup for beta, download the app and receive future updates.

Faking geolocation to test your IOS apps – CLLocationManager

The Problem:

If anyone of you are having trouble testing your IOS apps with fake locations. eg. I am in Dallas but I want to test how my app behaves in New York, Toronto, Australia, India, wherever…there is no magic solution built into Simulator for this. We ran into this same problem while developing Loqly – http://loqly.me. Here is the iTunes link:http://bit.ly/e5u4jv (it is free!) and this is how we solved it.

The Solution: (This is natively supported in IOS 5/XCode 4.2 simulator. Yipee! no more hacking)

The easiest way (may not be the most elegant way) to do this is as below. You can change it to any geolocation and when you run in simulator, it will fake the geolocation

#ifdef TARGET_IPHONE_SIMULATOR

@interface CLLocationManager (Simulator)
@end

@implementation CLLocationManager (Simulator)

-(void)startUpdatingLocation {
CLLocation *fake = [[[CLLocation alloc] initWithLatitude:45.523450 longitude:-122.678897] autorelease];
[self.delegate locationManager:self
didUpdateToLocation:fake
fromLocation:fake];
}

@end

#endif // TARGET_IPHONE_SIMULATOR

Does your IOS App welcome attackers with open arms ?

May 27, 2011 1 comment

I have added an HTTP sniffer on my network countless times and freely see passwords travelling back and forth between IOS apps and the servers where their APIs reside. I am sure you remember that Instagram took lot of flak when it was discovered that they were transmitting passwords in clear text across the network. The argument was that although there is zero value for anyone to hack your instagram credentials, but even the smartest of us tend to use the same login name and passwords for a lot of sites. And it doesn’t take a long time for a hacker to realize that and use your instagram login to hack your bank account or mint account or email account. SCARY !!!!!!

I am not going to detail how exactly to protect your API here but here is a quick thought on how to easily do it without SSL (call it poor man’s SSL). We have used an advanced form of encryption and rolling/expiring tokens to protect our API from prying eyes in Loqly. Here is the iTunes link:http://bit.ly/e5u4jv (it is free!)

  • When you launch your app, contact your server to get a random key
  • Every API call you make to the server from now on should send this key back to the server using any simple encryption algorithm. If nothing else, just base64 encode it. The server should then validate that every API call contains this key.
  • Along with the above key send some token which will expire after X minutes. eg. 10 minutes

What will you get from this? If a hacker is sniffing your network and he sees the exact API call and copies it, guess what? He cannot make that call more than X minutes at which time the validity of that API call expires. Which means nobody can use DOS attacks to bring down your entire server.

But in the above sentence the hacker can use your API call for at least X minutes. Well, in that case send some random number(encrypted) with every API call. The server should then reject API calls with the same number in them (i.e copy /paste API URLs will not work for the hacker)

Also, think of rejecting API calls not originating from a certain USER_AGENT. i.e people trying to paste your API calls into your browsers should be slapped in their face if they are coming from Mozilla, IE, Safari, Chrome etc. Your IOS app can modify the USER_AGENT and insert its own value in there.

Also, try to HTTP POST these security keys to make it a little more difficult for the hacker to call your API. An HTTP GET call is as simple as copying and pasting it on the browser.

Error reporting in your IOS apps

The Problem :

You are a good programmer who likes to know what the code is doing before copying and pasting it from the internet. You always write efficient code and your code never leaks memory. You use instruments and profiling to profile your leaks, zombies, allocations etc.

But shit happens! And no matter how hard you try and how good your testing team is, your app will eventually crash. I have seen all sorts of good apps crashing. Google App, Loopt, Facebook, Heytell, Instagram to name a few which have crashed on me. I am a power user though, which means I have around 70 apps easily running on my iPhone all the time. This causes apps to run out of memory and guess what..when you run out of memory–>BAD THINGS HAPPEN! = CRASH!

The Solution :

So, as a good developer, you should definitely build some error logging/reporting capabilities in your apps. Yes, Apple iTunes has the option to collect your crash logs and stuff. But hey! please leave a comment on this post; I am curious to know how many people use it.

At Loqly – http://bit.ly/e5u4jv, we use something called Hoptoad for error reporting for both our server side errors and IOS app errors. It is amazing that with a few lines of code how nicely Hoptoad takes care of everything for you. If your app crashes, the next time you run the app, Hoptoad presents this screen to the user, allowing him to send a crash report to you. The crash report has the standard stacktrace and it normally takes me 10 seconds to narrow down the culprit by looking at the report.

Obviously, I won't show a Loqly crash report here 🙂

Yes, it is debatable if you want to admit on the user’s  face that your app crashed last time. It is a little shameful yes, but hey who are we kidding here? Do you really think the user doesn’t realize that your app crashed, just because IOS simply closes your app and you don’t see the nasty Windows Dr. Watson message.