Tuesday, December 28, 2010

What to Do with UIRequiresPersistentWiFi

Last night I was watching a streamed TV show (*) from great archives of national broadcasting company. At about 32 minutes it stopped! Couldn't restart the show, couldn't pause and restart, couldn't stop and restart, couldn't restart the application to restart the show.

Application was ok, responsing well. Just wouldn't play anything for me.

Wednesday, December 22, 2010

Local Static Variable Lifetime Expectation in Objective-C

Something I learned today, worth remembering for performance reasons. Static variable defined inside a method is actually a global variable, which is visible only inside that method!

What this means is that you can increase your method performance by declaring variable only once and reuse it when needed next time.

Tuesday, December 21, 2010

Localization Tips

Experimenting with Localization, wondering why doesn't it work like in books? Me, too!

You should have one folder per language, e.g. "en.lproj" for English and "fi.lproj" for Finnish. This folder should contain one language specific file, which contains localized text strings:
"myString1" = "Hello, World!";
...which you use in code:
NSLocalizedString(@"myString1", nil)

Data Formatters temporarily unavailable, will re-try after a continue

Mysterious crash happens, when I'm trying to display about 65MB image in iPhone4. Wonder what could be the problem... (hint: trying to display 65 MEGABYTE image file):
Program received signal:  “0”.
Data Formatters temporarily unavailable, will re-try after a 'continue'. (Unknown error loading shared library "/Developer/usr/lib/libXcodeDebuggerSupport.dylib")

Monday, December 20, 2010

How to Detect iOS Version in Code

Bumbed into a case where code crashed iOS 4.0.2, but worked with iOS 4.2. Since crash happened because of missing NSString *const, couldn't use respondsToSelector to choose, which code to run. Decided to simply check what is current iOS version:
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version > 4.0)
{
    // iOS 4.2 specific code
}
else
{
    // iOS 4.0.2 specific code
}
Please note how three part version number gets converted to float:
NSString *s = [[UIDevice currentDevice] systemVersion];
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
NSLog(@"Version: %@ and %f", s, version);
NSLog(@"Version: %@ and %f", @"3.1.3", [@"3.1.3" floatValue]);

Version: 4.0.2 and 4.000000
Version: 3.1.3 and 3.100000
I'm not really happy with the solution, but it works. Can live with that.

Update:

Always run code in real device! My development device iPhone4 with iOS 4.1 returns "4.1" as string, but that gives 4.0999999 as float value !!!

Friday, December 10, 2010

Where is iPhone Simulator NSTemporaryDirectory

Sometimes I need to save temporary files. The problem is cleaning up afterwards: application might crash during debug sessions leaving files, which are accessed on following launch thus messing up normal expected application behaviour.

iOS provides application specific temporary folder. The benefit in using this is that even if the worst case happens and your app fails to clean up temporary files for some reason (try to view 65 MB image, for example), application temporary folder is automatically cleaned out every 3 days. Your application is thus not able to leave behind "zombie" files, which would fill up device harddisk until all available space is used!

Wednesday, December 8, 2010

GDB: Program received signal: "EXC_BAD_ACCESS"

When your program crashes (not if, but when) with an error message...
GDB: Program received signal: "EXC_BAD_ACCESS"
...you know that there is most likely a memory leak somewhere. Your code just tried to access something, which was supposed to be there, which used to be there, which is going to be there, which should have been there - but right now is missing.

Thursday, December 2, 2010

How to Continue Music Play after Screen Auto-Lock

Your application is playing music - until screen auto-lock stops it.

This happens, because by default your application is using AVAudioSessionCategorySoloAmbient audio session category.

You could disable auto-lock, but that would decrease battery life. Might be better to continue music playing, regardless of auto-lock:
#import <AVFoundation/AVFoundation.h>

AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:NULL];
Now your application works in same as iPhone music player (iPod). Please read more technical info about Audio Session Programming at Apple iOS Reference Library.