Archive of articles classified as' "Tech"

Back home

NSUserDefaults nil Setting Problem

05/26/2010

The iPhone has a handy system Settings app that has a unified location to make changes to different apps on you phone. Within your application, Settings.bundle allows the app to display settings in the iPhone Settings application and NSUserDefaults allows an application to programmatically interact with the phone’s default system. When changing a value in the Settings app it will be updated in the phone’s default system so you can retrieve these settings programmatically within your application.

The problem is if your application settings are never opened in the Settings app, when using NSUserDefaults to retrieve setting values within your application, they will be nil even if a DefaultValue is set in your settings bundle. The reason is the settings bundle and the shared NSUserDefaults object are not one in the same. NSUserDefaults needs to be populated with data either through the iPhone Settings app or programmatically in your application. There are few solutions to this floating around the web to initialize the default values but I didn’t find any that I really liked.

Below is a pretty simple method that I call in the application:didFinishLaunchingWithOptions: method of my app delegate. What it does is grab the settings from the settings bundle, and if any item value is nil it will update the value of that item with the specified DefaultValue (if there is one). This ensures that all values that need a default value will have that default value set in the NSUserDefaults shared defaults object. For more information check out the documentation for Settings Application Schema Reference and NSUserDefaults Class Reference.

- (void)setupDefaults {

    //get the plist location from the settings bundle
    NSString *settingsPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Settings.bundle"];
    NSString *plistPath = [settingsPath stringByAppendingPathComponent:@"Root.plist"];

    //get the preference specifiers array which contains the settings
    NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
    NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];

    //use the shared defaults object
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    //for each preference item, set its default if there is no value set
    for(NSDictionary *item in preferencesArray) {

        //get the item key, if there is no key then we can skip it
        NSString *key = [item objectForKey:@"Key"];
        if (key) {

            //check to see if the value and default value are set
            //if a default value exists and the value is not set, use the default
            id value = [defaults objectForKey:key];
            id defaultValue = [item objectForKey:@"DefaultValue"];
            if(defaultValue && !value) {
                [defaults setObject:defaultValue forKey:key];
            }
        }
    }

    //write the changes to disk
    [defaults synchronize];
}

2 Comments

Hide UISearchBar Background (iPhone SDK 3.2 & 4.0)

05/10/2010

Dear Non-Developer Readers,
I may start posting some technical stuff up here from time to time. I’ll try to not let it dominate my bi-annual blog posts. Also, I’m testing out this code highlighting plugin which seems to work pretty well.

My Problem:
I want to hide the background of a UISearchBar and the methods I found only worked on SDK versions 3.1.3 and below. That method basically grabs the subview (of class UISearchBarBackground) that contains the background image and sets it to hidden:

[[searchBar.subviews objectAtIndex:0] setHidden:YES];

Well that only works in versions of the iPhone SDK prior to 3.2. In 3.2 and beyond this technique no longer works (which is exactly why these sort of whatever.subviews hacks should generally be avoided).

My Solution:
In iPhone SDK 3.2 and 4.0 I’ve found this alternative technique that works:

[[searchBar.subviews objectAtIndex:0] removeFromSuperview];

And if you want to go all out and attempt to future-proof your code give this a try (no guarantee that it won’t still break though – Apple could still change the class name or change the structure of the UISearchBar in a future SDK update):

for (UIView *subview in searchBar.subviews) {
    if ([subview isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
        [subview removeFromSuperview];
        break;
    }
}
1 Comment

Who Killed the Electric Car?

07/27/2009

A while back someone (my Dad I think) recommended I add Who Killed the Electric Car? to my Netflix queue. I had completely forgoten about it until it showed up in my mailbox last week.

I really knew nothing about General Motors’ foray into the electric car market in the late nineties, but after watching this movie, I really want to get a plug-in hybrid. Basically, GM built the first mass produced 100% electic power car, the EV1. The long and the short of it is GM stopped producing it after California zero emission laws were rescended. The car no longer exists (except a few non-functioning museum cars) because GM actually reposessed every single car (which were all leased and not available for purchase) and literally crushed and shredded them. Check out the trailor below.

Well today I came across this article about a new Nissan electric car that will be unveiled this Sunday (and suppossedly available for purchase in 2010). The article has little to do with the car itself and more to do with an iPhone app Nissan has built. Basically, while you car is charging you can monitor the battery power so you will know when it’s all charged.

Nissan seems to just be scratching the surface with what they can do (the only other announced feature of the software is to remotely control the air conditioning). This is the kind of stuff companies need to start doing with smart phones. There are so many apps that are rehashed and non-innovative…I can’t wait until we start seeing more smart integration like this.

No Comments