1

I am trying to execute the following code in a playground. Fairly, I am treating both variables bm and ul equally but error shows only at ul

import UIKit

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject([], forKey: "bookmarks")
defaults.setObject([], forKey: "urls")

var bm : NSMutableArray = defaults.valueForKey("bookmarks") as NSMutableArray
var ul : NSMutableArray = defaults.valueForKey("urls") as NSMutableArray

bm.addObject("Google")                 //--->Works
ul.addObject("http://google.com")      //--->Oops, No
tika
  • 7,135
  • 3
  • 51
  • 82
  • 1
    That just blew my mind. ;) – user3581203 Mar 04 '15 at 20:09
  • This really is odd. Here's the error: `Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'`. – AstroCB Mar 04 '15 at 20:18

1 Answers1

4

I can't tell you why the first works and the second doesn't - it is probably just a quirk of playgrounds, timing and a delay in persisting NSUserDefaults to disk.

Your problem, however, is that valueForKey (and you should use objectForKey) returns immutable objects - so bm and ul will actually be NSArray instances and you can't simply cast them to NSMutableArray. You get a crash when you try to do so and mutate the object.

You need to create a mutable copy of your array.

 var bm=defaults.objectForKey("bookmarks") as NSArray?

 if bm != nil {
    var bmCopy=bm!.mutableCopy() as NSMutableArray
    bmCopy.addObject("Google")
    defaults.setObject(bmCopy, forKey:"bookmarks")
 }
Community
  • 1
  • 1
Paulw11
  • 108,386
  • 14
  • 159
  • 186