Thursday, July 22, 2010

How to Solve Ad Hoc release "value not permitted by a provisioning profile"

Ever since I submitted an application to App Store I've had lots of problems creating Ad Hoc release. Though first fix was simple, it's not a complete solution.

Error messages are:

Thu Jul 22 11:46:34 jouni-iDevice installd[643] : entitlement 'keychain-access-groups' has value not permitted by a provisioning profile

Thu Jul 22 11:46:34 jouni-iDevice installd[643] : entitlement 'application-identifier' has value not permitted by a provisioning profile
...
Thu Jul 22 11:47:06 jouni-iDevice SpringBoard[28] : Application 'Zattr' exited abnormally with signal 11: Segmentation fault

This time the solution was found in TUAW article "devsugar: A better way to share ad-hoc builds".

Summary: instead of normal Build use Build and Archive, find your application, find the last date, press Share Application button and - The Critical Phase - verify your identity is your Ad Hoc Distribution Provisioning Profile. Save locally and install e.g. via iPhone Configuration Utility.

...suspect Ad Hoc release problem is caused by having two different provisioning profile files using same application id. I generate three applications (development, release test, public) from same sources with some compile time flags and different provisioning profiles and app ids. Guess code signing identities got mixed.

Warning - No location found for "MyFile.m:42"

Debugger Console might show you something like this:
Warning - No location found for "GuestLoginNote.m:33"
This is most likely a forgotten breakpoint in a file which doesn't exist any more. To get rid of the warning, please go to XCode menu Run - Show - Breakpoints. Locate the problem breakpoint and delete it.

Tuesday, July 20, 2010

The Curse of Version Control

Version control is a MUST for any developer - but that doesn't mean you have to use an external version control system. The importance is in the idea and attitude instead of using any specific tool.

Last week we got a harddisk crash, removing SVN version control and TRAC project management from service. Regardless of that - and summer vacations causing delay in repair - work must go on. Was shocked to realize how much I had started to rely and depend on SVN as part of normal development cycle. Suddenly I was on loose ground!

Version control without a version control tool requires certain kind of routines:
  • Think before you start doing anything
  • Complete your thinking before you start doing anything
  • Test your thinking before you start doing anything
  • When thinking is done, start doing - don't procastinate

This time it's all about you. It's all in the mind. It's personal.


  • Split the work into small enough parts which you can design, implement, test and release during one cycle
  • Never start anything you can't complete during same session
  • Make regular backups of your progress, even local ones
  • Document what you plan to do and how you think you did it
  • Automate anything you can
The less you have to keep in your mind, the better you can focus. The better you can focus, the faster you get results. The faster you get results, the easier it will be to fix them.

Thursday, July 15, 2010

How to Accept Self-Signed Server Certificate

We have public server, test server and release test server. Likewise I generate three different binaries, each connecting to different server. The problem is that test servers have self-signed certificates and iPhone fails by default in NSURLConnection sendSynchronousRequest. The error note is:

ERROR CODE -1202 = The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xx.xx.xxx.xxx” which could put your confidential information at risk.
The solution with iOS4 is this one line:
#if (defined(TEST_VERSION) || defined(RELEASE_TEST_VERSION))
    [NSURLRequest setAllowsAnyHTTPSCertificate:YES
                                       forHost:[url host]];
#endif
    [NSURLConnection sendSynchronousRequest:request 
                          returningResponse:&response
                                      error:&error];
Please note that the specific line is undocumented class method and thus not used in official release, only for testing with simulator or ad hoc releases.

To remove compiler warning add this at the beginning of your file:
#if (defined(TEST_VERSION) || defined(RELEASE_TEST_VERSION))
@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end
#endif
More info at Dr. Touch article: Ignoring Certificate Errors on NSUrlRequest.

iOS5 update: this code might (or maybe not) help a little from my blog article Server API change from HTTP to HTTPS

Random Crashes while Debugging - by Debugging

Sometimes the problem is that there is no problem. Trying to debug it more can make the situation even worse - while the real problem was caused by debugging in the first place!

If you have mysterious freezes while debugging UITableView, try reducing the amount of logging. Fixed one such problem by NOT sending any NSLog messages from cellForRowAtIndexPath delegate callback. Seems like too many log messages messed up internal iOS timing.

Wonder how many times I have to re-iLearn this iLesson!

Tuesday, July 6, 2010

UITextField textFieldShouldBeginEditing called twice in iOS4

When you tap UITextField, you get two textFieldShouldBeginEditing calls. This looks like a bug in initial iOS4 release. Workaround is to use a BOOL flag to decide what you should do with that call:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if (self.allowEdit)
    {
        [self askUser];
        return NO;
    }
    return YES;
}

- (void)askUser
{
    if (self.alertVisible)
        return;    
    self.alertVisible = YES;
    
    UIAlertView *alert =
    [[UIAlertView alloc] initWithTitle:@"Please verify"
                               message:@"Do you want to edit?"
                              delegate:self
                     cancelButtonTitle:@"Cancel"
                     otherButtonTitles:@"Yes",
     nil];
    [alert show];
    [alert release];
}

- (void)alertView:(UIAlertView *)alertView
    clickedButtonAtIndex:(NSInteger)buttonIndex
{
    self.alertVisible = NO;
    if (buttonIndex == 1)
        [self doSomething];
}
The bug will (should) be fixed in some future iOS4 release, so it's more safe to isolate your work-around inside your own routines as much as possible to minimize possible unwanted side-effects.

Friday, July 2, 2010

Entitlement 'keychain-access-groups' has value not permitted by a provisioning profile

You build and install application you are developing and fail with a flash without any obvious error note. Using iPhone Configuration Utility you're device's Console contain something like this:
Fri Jul 2 10:26:23 jouni-iDevice installd[6313] : entitlement 'keychain-access-groups' has value not permitted by a provisioning profile
Fri Jul 2 10:26:23 jouni-iDevice installd[6313] : entitlement 'application-identifier' has value not permitted by a provisioning profile
The reason is that you have previously installed your application from App Store and overwriting app binary with a developer version is not enough.

Quick fix is to delete the application from device, then build and install again.

Thursday, July 1, 2010

Class does not implement the 'NSStreamDelegate' protocol

Got this warning after upgrading to Xcode 3.2.3. To fix it add NSStreamDelegate into your class interface:
@interface MyClass: NSObject {}
@interface MyClass: NSObject <NSStreamDelegate> {}
NSStreamDelegate is defined for Cocoa, but not Cocoa Touch. iPhone stream:handleEvent: is an informal delegate method.

On Mac OS X 10.6 SDK (used by iPhone OS 4) delegate methods are generally defined in formal protocols rather than informal protocols as before, which means you have to declare the protocol conformance in the class interface of the delegate. More info at Mac OS X SDK release notes.

How to target pre-iOS4 devices with latest XCode

Had a moment of confusion when upgrading to XCode 3.2.3. That version seems to support only iOS3.2 (iPad) and iOS4. Tried using previous XCode 3.1.3 for developing iOS3 software, just to get frustrated by non-backwards compatibility issues.

Use latest XCode 3.2.3. Set project Base SDK as iPhone Device 4.0 and iPhone OS Deployment Target as iPhone OS 3.0 - or anything as far backwards as iPhone OS 2.0.