1

My applicaiton crashes with the exception mentioned in the title. Please find below my explanation :

tried to store array values using NSUserDefaults in my TableViewController as under :

func didDismissContentViewController(controller:ContentViewController,pageIndex:Int) { //You're passed in the contentViewController here, use relevant data to update your model. NSLog("Inside delegate method ..\n") var currentIdx = pageIndex

    NSLog("Value of index edited \(pageIndex)")
    NSLog("Current edited value is : \(controller.myTextView.text)")

    **pageContent.replaceObjectAtIndex(pageIndex, withObject: controller.myTextView.text)**

**//pageCotent is defined as an NSMutableArray only...**

    NSUserDefaults.standardUserDefaults().setObject(pageContent as NSMutableArray, forKey: "PageValues")
    NSUserDefaults.standardUserDefaults().synchronize()
}
Retrieval is done as under : if var storedPageContent = NSUserDefaults.standardUserDefaults().objectForKey("PageValues") as? NSMutableArray{ pageContent = storedPageContent

While I am able to store, retrieve and display the updated page values in their respective pages, subsequent transition back and forth between the tableviewcontroller and content view controller throws the below error:

015-12-21 00:51:46.592 PageApp[3943:203948] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray replaceObjectAtIndex:withObject:]: mutating method sent to immutable object' * First throw call stack:

I tried commenting out the store to NSUserDefault, and the applicaiton does not crash, whereas using the NSUserDefault to store values, causes this to happen, So the error appears when I store it in NSUserDefaults and then retrieve it and assign it to array.

any help on this will be appreciated.Exchange data between uitah

Community
  • 1
  • 1
Raghu
  • 49
  • 4

5 Answers5

1

I think the issue is even though you are assigning values retrieved from NSUserDefaults to a NSMutableArray, it is not actually creating a NSMutableArray as you expected. Can you try initialising a new NSMutableArray with the objects fetched from NSUserDefaults? In Objective-C, it will be like

NSMutableArray *pageContent = [[NSMutableArray alloc] initWithObjects:object1,nil];

where object1 is the value fetched from NSUserDefaults. Sorry I did not know Swift

Arun
  • 1,391
  • 1
  • 10
  • 29
1

The arrays returned from NSUserDefaults are immutable, so you will need to make a mutable copy of the array and then re-set the array in NSUserDefaults, once you've modified it.

I don't know Swift well enough to give you a code example, but this is how it would be done in Objective-C:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefauts];
NSMutableArray *pageContent = [[userDefaults objectForKey:@"PageValues"] mutableCopy];
[pageContent replaceObjectAtIndex:pageIndex withObject:controller.myTextView.text];
[userDefaults setObject:pageContent forKey:@"PageValues"];
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
1

I ran into exactly the same problem yesterday. Apparently if you get an array object using NSUserDefaults it acts like an NSArray even if you specify it to be NSMutableArray.

So the way I solved this problem was using this way (Objective-C). Once I had passed it to another NSMutableArray I was able to add / remove objects from it.

NSArray *favArrayTemp = [[NSUserDefaults standardUserDefaults] objectForKey:@"MyFavServers"];
NSMutableArray favArray = [[NSMutableArray alloc] initWithArray:favArrayTemp];
Sam B
  • 27,273
  • 15
  • 84
  • 121
1

Use Swift native types.

Cast the type retrieved from NSUserDefaults to a native Swift collection type as var then it's mutable.

var pageContent = [String]()
...

let userDefaults = NSUserDefaults.standardUserDefauts()
pageContent = userDefaults["PageValues"] as! [String]

Replacing is pretty easy, too.

pageContent[pageIndex] = controller.myTextView.text

Side note: The forced unwrapping while reading the value from NSUserDefaults assumes that the key/value pair has been registered properly. Then the unwrapping is safe.

vadian
  • 274,689
  • 30
  • 353
  • 361
0

Thank you for the response. I made changes as suggested by you and it worked. Let me share it below:

// As mentioned by you, since NSUserDefault always expects an NS Array, I did the storing as under :

NSLog("I am inside the bactktomonths ..\n")

//Defined an NS Array to copy the Mutable array to Immutable array var storedArray = NSArray()

    storedArray     = pageArray!

    NSUserDefaults.standardUserDefaults().setObject(storedArray , forKey:    "PageValues")
    NSUserDefaults.standardUserDefaults().synchronize()
}

// Retrieval.

if (NSUserDefaults.standardUserDefaults().objectForKey("PageValues") != nil){

        pageContent = NSUserDefaults.standardUserDefaults().objectForKey("PageValues")?.mutableCopy() as NSMutableArray

// I am not sure If I need to execute the below code, but I have left it as suggested and it works currently ! NSUserDefaults.standardUserDefaults().setObject(pageContent, forKey: "PageValues")

Thanks

Raghu
  • 49
  • 4