NSUserDefaults setObject forKey causing exception in ios7 - iphone

I was trying to save a NSString to NSUserDefaults. Its working fine in iOS6,iOS5 versions. But in iOS7 its crashing with a message
[NSUserDefaults setObject:forKey:]: attempt to insert non-property
list object
NSUserDefaults *missedValues=[NSUserDefaults standardUserDefaults];
NSMutableDictionary *temp=[[NSMutableDictionary alloc]init];
[temp setObject:name forKey:#"missedName"] ;
[missedValues setObject:temp forKey:#"missed"];
[missedValues synchronize];
An exception is thrown when setObject method is called. How can this be fixed ? The issue is only with iOS7.

Related

Way to persist MPMediaItemCollection objects? (selected from iPod)

I am making an app in which the user can select a song in a settings tab and have this played in a different view on demand. I want it so that this item can be stored if the user is to shut the app and reopen it another time.
I have managed to allow the user to select and store a song in with:
-(IBAction)showMediaPicker:(id)sender{
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAny];
mediaPicker.delegate = self;
mediaPicker.allowsPickingMultipleItems = NO;
mediaPicker.prompt = #"Select Alarm Sound";
[self presentModalViewController:mediaPicker animated:YES];
}
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection {
[self dismissModalViewControllerAnimated: YES];
settingsData.selectedSong = mediaItemCollection;//Object of type MPMediaItemCollection
but I want the user to have to do this every time they use the app.
I have tried using NSUserDefaults:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:settingsData.selectedSong forKey:#"alarmSoundKey"];
[defaults synchronize];
but get the error:
* -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '' of class 'MPMediaItemCollection'. Note that dictionaries and arrays in property lists must also contain only property values.
What are my options please? Not really sure how to tackle this one...
SOLUTION -
I can't answer my own questions yet so I'll put it up here:
I HAVE FOUND MY OWN SOLUTION TO THIS:
First convert/encode the MPMediaItemCollection to an NSData Object and slam store it using NSUserDefaults using:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:mediaItemCollection];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:data forKey:#"someKey"];
[defaults synchronize];
From there, you can decode and use anywhere else in your app....
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:#"someKey"];
MPMediaItemCollection *mediaItemCollection = [NSKeyedUnarchiver unarchiveObjectWithData:data]
Hope that is some help to someone. Spread the word, this hasn't been covered enough. Have literally been working on this problem for about 4 hours...
You can only store property list values in NSUserDefaults. Since MPMediaItemCollection conforms to NSCoding you could use an NSKeyedArchiver to store it instead.
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSKeyedArchiver_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003672
You then use NSKeyedUnarchiver to read it back out of the file later.
You can also use the MPMediaItemPropertyPersistentID property. You can form a query to retrieve the item from the iPod library when your application next launches, and gracefully handle things like when the user decides to remove the song from their library.

NSUrl is not stored as absolutestring in NSUserDefault

I am referring Previous Post for storing NSURL of iPod Library in NSUserDefault. But it is not stored in NSUserDefault after application is closed.
I am using other NSStrings to store in NSUserDefaults which is perfectly done, But when i store NSUrl as absolute string.. it does not stores the value.
What could be the reason??
EDIT
Following code i am using to save NSUserDefault Value:
currentItem = [collection.items objectAtIndex:songCount];
songURL = [currentItem valueForProperty:MPMediaItemPropertyAssetURL];
[[NSUserDefaults standardUserDefaults] setObject:[currentItem valueForProperty:MPMediaItemPropertyTitle] forKey:#"songTitle"];
[[NSUserDefaults standardUserDefaults] setObject:[songURL absoluteString] forKey:#"songURL"];
avPlayer = [[AVPlayer alloc] initWithURL:songURL];
NSLog(#"songTitle: %# songURL : %#",[[NSUserDefaults standardUserDefaults]objectForKey:#"songTitle"], songURL);
Following error comes when i try to save the NSURL:
2011-09-13 18:47:23.258 Tabata Timer[933:707] songURL : ipod-library://item/item.mp3?id=-3715406019015217536
2011-09-13 18:47:23.258 Tabata Timer[933:707] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value 'ipod-library://item/item.mp3?id=-3715406019015217536' of class 'NSURL'.
2011-09-13 18:47:23.260 Tabata Timer[933:707] songTitle : Ghajini
2011-09-13 18:47:24.860 Tabata Timer[933:707] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value 'ipod-library://item/item.mp3?id=-3715406019015217536' of class 'NSURL'.
2011-09-13 18:47:24.963 Tabata Timer[933:707] songURL : ipod-library://item/item.mp3?id=-3715406019015217536
warning: Unable to read symbols for /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.3.5 (8L1)/Symbols/Developer/usr/lib/libXcodeDebuggerSupport.dylib (file not found).
If you want to store NSURL then why are you converting it into string and saving it as string. It will increase your work effort.
You can try this:
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setURL:[NSURL URLWithString:#"http://www.google.com"] forKey:#"urlValue"];
[defaults synchronize];
NSURL *url=[defaults URLForKey:#"urlValue"];
NSLog(#"%#",url);
The only thing I can think of that would explain it is that the URL is at least partially randomly generated and thus fails to load after you app removes reference to it. What do you mean, "closed"? Backgrounded? Or really terminated?
It could also be that you should be saving it as a string:yourURLString forKey:#"URL" instead of an object. It could be confusing the app. Try NSLog to output the URL string and see what you get. Let me know what it is. That will clarify things.
your string should have property declared...then try to store it in NSUserDefaults

strange issue with NSUserDefaults

I have an array in my app delegate.In some other class I am adding few dictionaries in this app delegate array.
There only I set this appdelegate array for a key in NSUserDefaults.Later on when I check NSUserDefaults value for key for which I saved the appdelegate array, always shows zero object.
I am using
[[NSUserDefaults standardUserDefaults] setObject:app.testArray forKey:#"theKey"];
You can try this code. I am very sure that it will work for you.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:yourArray forKey:#"init_val"];
[defaults synchronize];
For Retrieving Data You Should Use The Following Code :
NSMutableArray *newArray=[[[NSUserDefaults alloc] objectForKey:#"init_val"] mutableCopy];
Hope this helps you.
Try this for retrieving data
NSMutableArray *newArray=[[NSUserDefaults standardUserDefaults] objectForKey:#"init_val"];
Use object for key instead of valueforkey eg: [userdefaults objectForKey:#"init_val"];

Cannot set NSUserDefaults field

I have the following code in my initialization (first time) of my app:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *uid=#"1";
[defaults setObject:uid forKey:#"init_val"];
[defaults synchronize];
Much later in the code (in response to a button press) I check the value using:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *initVal=[defaults objectForKey:#"init_val"];
initVal is always nil. I have checked and init_val is set up exactly the same in my settings bundle as another field that I can set and read from without issue (they are both set up with a single field named "Key".
#mlewis54:
You can try this code. I am very sure that it will work for you.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *uid=#"1";
[defaults setObject:uid forKey:#"init_val"];
[defaults synchronize];
For Retrieving Data You Should Use The Following Code :
NSString *initVal=[[NSUserDefaults standardUserDefaults] valueForKey:#"init_val"];
OR
NSString *initVal=[[NSUserDefaults standardUserDefaults] objectForKey:#"init_val"];
EDIT:
If still it gives nil, then you can use the following code:
NSString *initVal=[NSString stringWithFormat:#"%#",[[NSUserDefaults standardUserDefaults] valueForKey:#"init_val"]];
OR
NSString *initVal=[NSString stringWithFormat:#"%#",[[NSUserDefaults standardUserDefaults] objectForKey:#"init_val"]];
Hope this helps you.
Decelare this at an event on click of button ...
NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];
[savedData setObject:userEmailTextField.text forKey:#"userid"];
and on load load the data and check the value you have entered is showing or not...
userEmailTextField.text =[[NSUserDefaults standardUserDefaults]objectForKey:#"userid"];
You need to use the line
NSString *initVal = [defaults stringForKey:#"init_val"];
- since it's a String you must use stringForKey. You can similarly use boolForKey to get a boolean value.
There's nothing wrong in your code, i tried to copy it in my project and it worked good,
so your error could be probably when you check initVal...
what's the code you use to see if initVal is nil?
and are you sure that when/where you check initVal, that var/oblect is still visible ?
try to insert this immediately after your reading code:
NSLog(#"____text read in pref: %#", initVal);
it writes this in my console window -> __text read in pref: 1
of course it's an NSString, i hope you keep it in mind it's not an int or a NSNumber when you check it...
luca
It might be that the initialisation isn't happening. Put an NSLog in there to check it's executed.
It works fine for me with the same code:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *uid=#"1";
[defaults setObject:uid forKey:#"init_val"];
[defaults synchronize];
NSUserDefaults *defaultss = [NSUserDefaults standardUserDefaults];
NSString *initVal=[defaultss objectForKey:#"init_val"];
NSLog(#"Value of initVal: %#",initVal);
O/P on console: Value of initVal: 1
So try to do it with the same code with print on console.
Are you sure you properly initialize NSUserDefaults? When I initialize, in my app delegate, I always create the default user defaults by creating a dictionary of the default values then:
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
Where appDefaults is the dictionary. Then you should be able to access them correctly.

Problem with NSUserDefaults and deallocated Instance

I'm having a problem with NSUserDefaults. I've followed the steps in the books as closely as I can for my app, but still get the same problem.
I am getting a
*** -[NSUserDefaults integerForKey:]: message sent to deallocated instance 0x3b375a0
error when I try and load in the settings. Here is the code that I have, it is in the App Delegate class.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
recordingController = [[RecordingTableViewController alloc] initWithStyle:UITableViewStylePlain];
[recordingController retain];
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
[self loadSettings];
}
-(void)loadSettings
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber loop = [defaults objectForKey:#"loop_preference"];
NSNumber play = [defaults objectForKey:#"play_me_preference"];
NSNumber volume = [defaults objectForKey:#"volume_preference"];
}
As you can see I am not trying to do anything with the values yet, but I get the error on the line reading in the loop preference. I also get it if I try and read an NSString.
Any suggestions would be greatly appreciated.
Thanks
Peter
Since NSNumber is an object, it seems likely to me that you want:
NSNumber *loop = [defaults objectForKey:#"loop_preference"];
NSNumber *play = [defaults objectForKey:#"play_me_preference"];
NSNumber *volume = [defaults objectForKey:#"volume_preference"];
(Add asterisks * after NSNumber and before the variable names.) Though this does not seem directly related to your error message, it's the only apparent quirk in your code.