3

I have the following code in my ApplicationDelegate. My deployment target is 3.0 and upwards, however I get a EXC_BAD_ACCESS when I launch the app with the following code on my iPhone with 3.1.3, however on the simulator which has 4.2 it runs fine.

This problem is now SOLVED. The code below is working, and it got a EXC_BAD_ACCESS due to a NSURLConnection in my code. I won't delete my code if anyone else get this problem. Thanks for your help.

UPDATE: Plist file:

<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
    <dict>
        <key>Type</key>
        <string>PSGroupSpecifier</string>
        <key>Title</key>
        <string>Check for report on start?</string>
    </dict>
    <dict>
        <key>Type</key>
        <string>PSToggleSwitchSpecifier</string>
        <key>Title</key>
        <string>Autocheck reports?</string>
        <key>Key</key>
        <string>FAutoUpdatePrefKey</string>
        <key>DefaultValue</key>
        <true/>
    </dict>
</array>

Applicationdelegate

+ (void)initialize {

NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *pListPath = [path stringByAppendingPathComponent:@"Settings.bundle/Root.plist"];

NSDictionary *pList = [NSDictionary dictionaryWithContentsOfFile:pListPath];

NSMutableArray *prefsArray = [pList objectForKey:@"PreferenceSpecifiers"];
NSMutableDictionary *regDictionary = [NSMutableDictionary dictionary];

for (NSDictionary *dict in prefsArray) {
    NSString *key = [dict objectForKey:@"Key"];
    if(key) {
        id value = [dict objectForKey:@"DefaultValue"];
        [regDictionary setObject:value forKey:key];
    }
}
[[NSUserDefaults standardUserDefaults] registerDefaults:regDictionary];
}
LuckyLuke
  • 47,771
  • 85
  • 270
  • 434

3 Answers3

1

The registerDefaults: method has been available since iOS 2.0 (See Documentation), so that shouldn't be the issue. The problem probably stems from the regDictionary object and how you are filling it.

Take a look at this previous question. The main answer has an excellent method to do what you are trying to accomplish. In fact the code is nearly identical except for how the settings bundle is accessed: Can you make the settings in Settings.bundle default even if you don't open the Settings App

Here is the code you want (Stolen directly from the linked question above from the answer by PCheese)

- (void)registerDefaultsFromSettingsBundle {
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    if(!settingsBundle) {
        NSLog(@"Could not find Settings.bundle");
        return;
    }

    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];

    NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
    for(NSDictionary *prefSpecification in preferences) {
        NSString *key = [prefSpecification objectForKey:@"Key"];
        if(key) {
            [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
        }
    }

    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    [defaultsToRegister release];
}

UPDATE: Now that I see your pList, Change your PSToggleSwitchSpecifier's default value from <true/> to <string>YES</string>

Community
  • 1
  • 1
theChrisKent
  • 15,029
  • 3
  • 61
  • 62
  • Yes you are right! It is something that has to do with my regDictionary. However I don't know what yet. Thanks for pointing me in the right direction, because error is gone if I fill it with dummy values. – LuckyLuke Jan 03 '11 at 20:38
  • I've updated my answer with code from @PCheese that should do the trick – theChrisKent Jan 03 '11 at 20:43
  • That's strange. Have you uninstalled the app from the problem device, cleaned the build and redeployed? – theChrisKent Jan 03 '11 at 20:52
  • Yes, did it now and no change. – LuckyLuke Jan 03 '11 at 20:55
  • Without having the project in front of me, I'm not seeing a solution. The problem is the dictionary. Have you tried stepping through your code and verifying the dictionary is setup correctly? Not sure what would be different between the iOS versions though, since all of that Dictionary logic should be supported on both versions. – theChrisKent Jan 03 '11 at 21:00
  • I agree with @theChrisKent. I think it's the regDictionary dictionary too. But, if you ran my answer below it would have taken the dictionary out of the picture. I'm not seeing a solution either. – Larry Hipp Jan 03 '11 at 21:06
  • I have now posted Root.plist and my appdelegate where I try to register. – LuckyLuke Jan 03 '11 at 21:08
  • I'm giving up. Sorry I couldn't help, I'll leave this answer in place since I think some of it would be helpful to others. Hopefully, someone else will come along and be able to provide you with an answer. But based on the posted code (which looks fine) and the posted plist (which also looks fine), I can't find the issue. This is especially difficult since it works on the latest iOS. Your best bet is to enable NSZombie and do some step by step debugging to figure out where things break in the creation of that dictionary object. – theChrisKent Jan 03 '11 at 22:13
  • Thank you for your help, I really appreciated it. I will have to try to figure it out. – LuckyLuke Jan 03 '11 at 22:20
0

Try moving the registerDefaults into the loop.

for (NSDictionary *dict in prefsArray) {
       NSString *key = [dict objectForKey:@"Key"];
       if(key) {
           id value = [dict objectForKey:@"DefaultValue"];
           [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; //<-change               
       }
}
Larry Hipp
  • 6,205
  • 3
  • 26
  • 31
  • It still give me a EXC_BAD_ACCESS ERROR :( – LuckyLuke Jan 03 '11 at 20:22
  • Did you remove the line from the bottom and just use it in the loop? Also, did you get an error when the line in the loop ran? – Larry Hipp Jan 03 '11 at 20:34
  • Yes I did remove the line from the bottom. I use setObject:value....the preference i try to register is a boolean value in the Settings.bundle just to mention that. – LuckyLuke Jan 03 '11 at 20:42
  • I see what you're trying to do, but this will overwrite the settings to their defaults every time. The registerDefaults: method, however, will only set the value to the default if it isn't currently set. – theChrisKent Jan 03 '11 at 21:08
  • please try saving the defaults immediately. i suspect there is something non retained by the standard defaults implementation then used later on when the defaults are auto saved. just try it please to save the defaults immediately after setting each value. – Moszi Jan 03 '11 at 21:14
0

The problem here isn't the difference between OSs, but the difference between device and simulator. Simulator uses Mac OS X file system, which isn't case-sensitive, but the file system on iOS is.

So you might want to double check @"Settings.bundle/Root.plist" and @"PreferenceSpecifiers" if their caps lock is correct.

tadejsv
  • 2,085
  • 1
  • 18
  • 20
  • Checked now, and they are correct. I may add that it works on iPhone 3GS with 4.0.1. The device I am trying to get my app working on now is iPhone(first gen.) 3.1.3 – LuckyLuke Jan 03 '11 at 20:27