0

I have a simple messaging app, and I'm keeping a dictionary of BOOL:user in the NSUserDefaults which simply represents if something "new" has happened in that conversation. {YES:12343} for example, means there is a new message with user 123432, otherwise NO.

When users interact with each other, I update that dictionary and my view accordingly. And when I leave the app, save the dictionary to the NSUserDefaults. When I come back, I simply load it. Everything works smoothly, expect one thing.

When I tap on a conversation to open it, I set that boolean to NO (because I assume the user has read the message) and save that modified dictionary into the NSUserDefaults again.

Debug shows the dictionary is up to date when saved, but when I tap the "back" button, the view reloads the dictionary from the NSUserDefaults and that dictionary is NOT up to date. So my view is showing the conversation as unread, obviously.

Now the tricky parts comes into play. If I do it again, (sometimes once, sometimes twice), the dictionary will eventually show the conversation as read (because the dictionary will finally be up to date).

This tells me some things :

  • The dictionary is readable and everything is set "as it should/when it should"
  • What I get from the NSUserDefaults isn't updated quick enough/at the right time.

What I fail to understand is : when should I save that dictionary and how? I'm loading it in viewWillAppear, and saving it in didSelect. Isn't that the right thing to do ?

Some code :

My didSelect : pushDict is an NSMutableDictionary object and is never nil at that point

if (pushDict != nil){
                [pushDict setObject:[NSNumber numberWithBool:NO] forKey:_friendship.objectId];
                [[NSUserDefaults standardUserDefaults]setObject:pushDict forKey:@"pushDict"];

            }

And the dictionary loading :

if([[NSUserDefaults standardUserDefaults]dictionaryForKey:@"pushDict"]){
        pushDict = [[NSMutableDictionary alloc]initWithDictionary:[[NSUserDefaults standardUserDefaults]dictionaryForKey:@"pushDict"]];
    }else{  
        pushDictFeel  = [NSMutableDictionary alloc]init];
    }
Gil Sand
  • 5,802
  • 5
  • 36
  • 78

2 Answers2

2

First of all NSUserDefaults shouldn't be the place where you save information like this. Try to setup a good data model for this. However your error could occure because you are missing this line:

[[NSUserDefaults standardUserDefaults] synchronize];

From your code I can see that you are trying to save a NSMutableDictionary. This will not work since the returned object from the NSUserDefaults is immutable. Have a look at this: NSMutableDictionary in NSUserDefaults

Community
  • 1
  • 1
dehlen
  • 7,325
  • 4
  • 43
  • 71
  • I tried synchronizing right after setting the object but that didn't change anything :(. What do you suggest for saving information like that? I thought NSUserDefaults where exactly made simple primitives values like that. – Gil Sand Feb 20 '15 at 12:12
  • `NSUserDefaults` is read as a whole. So for large amounts of data you will be doing a lot of unneccessary IO. Create a data model like ConversationItem which holds a `BOOL` "read". You should always synchronize when setting a new object to your `NSUserDefaults`, so add the line to your code again. – dehlen Feb 20 '15 at 12:15
  • If this doesn't help you like you stated above please try and provide some of your code so we can dig deeper into your problem. – dehlen Feb 20 '15 at 12:19
  • `-synchronize` should never be necessary (and help) inside the app, when `NSUserDefaults` are used in a proper way. – Amin Negm-Awad Feb 20 '15 at 12:29
  • Well I ended up cheating my way around by passing the dictionary and saving it in the next controller's `viewDidLoad`, and it's all working fine. I edited to show some code for the sake of the argument but I genuinly don't understand what's the difference between saving "here" and "there". – Gil Sand Feb 20 '15 at 13:06
  • Now that you provided some code I can see why it was not working for you all the time. Have a look at my edited answer. – dehlen Feb 20 '15 at 13:58
0

You need to call synchronize for [NSUserDefaults standardUserDefaults]

if (pushDict != nil){
   [pushDict setObject:[NSNumber numberWithBool:NO] forKey:_friendship.objectId];
   [[NSUserDefaults standardUserDefaults]setObject:pushDict forKey:@"pushDict"];
   [[NSUserDefaults standardUserDefaults] synchronize];
}
LLIAJLbHOu
  • 1,313
  • 12
  • 17
  • As I said to @dehlen, it didn't change anything. And according to the documentation I think `synchronize` is really only when you plan to leave the app ; otherwise its should be available. I tried it, it did not work. But in the other answer I said how i went around the problem – Gil Sand Feb 20 '15 at 13:38