I have a .plist created at the application launch with the following code (MyAppTableViewController):
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:@"Settings.plist"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:finalPath];
if (!fileExists) {
NSLog(@"Creating file");
NSDictionary *plistDict = [[NSDictionary alloc]initWithObjectsAndKeys:@"1",@"Fade out",@"1",@"Enable Gestures",@"1",@"Proximity Sensor",@"1",@"Keep screen ON",nil];
NSString *error = nil;
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if(plistDict) {
[plistData writeToFile:finalPath atomically:YES];
} else {
NSLog(@"Error: %@", error);
[error release];
}
}
This works fine and the file is created with keys and values. I then have a table with four switches with a function toggle: as the selector.
The code inside -(void)toggle:(id)sender takes the switch’s value along with the row of the indexPath and modifies the plist accordingly:
-(void)toggle:(id)sender {
UISwitch *aSwitch = (UISwitch *)sender;
UITableViewCell *cell = (UITableViewCell *)aSwitch.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:@"Settings.plist"];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:finalPath];
if (indexPath.section == 0 && indexPath.row == 0) {
[dictionary setObject:[NSNumber numberWithBool:aSwitch.on] forKey:@"Fade out"];
}
//There are further (similar) else if statements, but I'll leave them out.
NSString *error = nil;
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if(dictionary) {
[plistData writeToFile:finalPath atomically:YES];
} else {
NSLog(@"Error: %@", error);
[error release];
}
}
This is also working fine and modifies the plist successfully. My issue arises when I try to to retrieve the data with the following code:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:@"Settings.plist"];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:finalPath];
fadeOut = [[NSString stringWithFormat:[dictionary objectForKey:@"Fade out"]]boolValue];
proximitySensor = [[NSString stringWithFormat:[dictionary objectForKey:@"Proximity Sensor"]]boolValue];
enableGestures = [[NSString stringWithFormat:[dictionary objectForKey:@"Enable Gestures"]]boolValue];
keepScreenOn = [[NSString stringWithFormat:[dictionary objectForKey:@"Keep screen ON"]]boolValue];
In the declaration file, I have defined BOOL fadeOut,proximitySensor,enableGestures,keepScreenOn;. Grabbing the information works fine, but it’s when I change the BOOL values, the application crashes. I can’t quite understand what the problem is. Perhaps I’m missing the bigger picture or a simple but important mistake with Boolean values.
If I remove the above code, everything works fine. But If I leave it there, the app crashes with the following message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFBoolean length]: unrecognized selector sent to instance 0x3f39a9f0'
Help is much appreciated!
If you look at this line
You’re initializing a string from an
NSNumber(you stored youBOOLin aNSNumber). That’s invalid by itself.If you need an bool value of an
NSNumber, use simply boolValue on it.That’s true for all the time you’re retrieving the boolean value.