iOS Swift Error: Execution was interrupted, reason : signal SIGABRT - ios

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

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")
}

Related

After adding element in NSMutableArray previous elements gets replaced

I'm working on app in which I want to create array with number of NSDictionary's. When i'm trying to add NSMutableDictionary in NSMutableArray, previously added elements of that array get replaced. I don't know what is happening. Code as follows:
var paynowArray = NSMutableArray()
let tempDict = NSMutableDictionary()
for i in 0...selectedEmenetsArray.count-1 {
tempDict.removeAllObjects()
tempDict.setValue(selectedIdAry[i], forKey: "serviceId")
tempDict.setValue(selectedAmountAry[i], forKey: "serviceAmount")
paynowArray.add(tempDict)
}
print(paynowArray)
While printing array last added NSMutableDictionary printed n times.
Thanks in advance.
Create tempDict inside the for loop. You should allocate dictionary for every element. Else you are replacing the same memory location value every times.
var paynowArray = NSMutableArray()
for i in 0...selectedEmenetsArray.count-1 {
var tempDict = NSMutableDictionary()
tempDict.setValue(selectedIdAry[i], forKey: "serviceId")
tempDict.setValue(selectedAmountAry[i], forKey: "serviceAmount")
paynowArray.add(tempDict)
}
print(paynowArray)
Should be inside the loop..
let tempDict = NSMutableDictionary()

Ambiguous use of 'mutableCopy()' Swift3

I tried to update Swift 3 and I got the following error :
Ambiguous use of 'mutableCopy()'
Before update to swift 3. It runs well.
Swift 2.3
NSUserDefaults.standardUserDefaults().objectForKey("listsavednews")?.mutableCopy() as! NSMutableArray
Swift 3.0
(UserDefaults.standard.object(forKey: "listsavednews")? as AnyObject).mutableCopy() as! NSMutableArray
I found that mutableCopy in Swift3 return Any that doesnt have method mutableCopy() so that it needs to cast to AnyObject.
Any helps thanks.
I dont know why I can't comment.
Thanks all, I'll be using :
UserDefaults.standard.mutableArrayValue(forKey: "listsavednews")
mutableCopy is an Objective-C method from NSObject. There's little reason to use it in Swift 3.
Since you are dealing with UserDefaults and mutableCopy, you must be dealing with either an array or dictionary. Or it could be a string.
The proper way to do this in Swift 3 is to use the proper UserDefaults method to get an array or dictionary. And assign the result to a var. That combination will give you a mutable array or mutable dictionary.
var someArray = UserDefaults.standard.array(forKey: "somekey")
or:
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey")
In the two above cases, you end up with an optional since there might not be any data for the given key. And you also get a non-specific array or dictionary which isn't ideal. It would be better to cast the result to the appropriate type.
Let's say you have an array of strings and you want an empty array if there is nothing currently in user defaults. You can then do:
var someArray = UserDefaults.standard.array(forKey: "somekey" as? [String]) ?? []
Adjust as necessary if the array contains something other than String.
If you actually have a dictionary, the code would be similar.
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey") as? [String:String] ?? [:]
If your original object is just a string, then you could do:
var someString = UserDefaults.standard.string(forKey: "somekey") ?? ""

Error : replaceObjectAtIndex:withObject:]: mutating method sent to immutable object

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
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"];
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];
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
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.
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

Swift NSMutableArray add one more array

The Problem is First time I get data from WebServices so I have show this data on TableView Then user scroller down tableview then again call WebSevices and add this data to again in array
but when I try to add data again in nsmutable type array app is crashing
Here is my code. Any solution?
1st time Data load is Working
var ary_mutable: NSMutableArray!
ary_mutable = NSMutableArray()
ary_mutable=jsonResult as AnyObject as! NSMutableArray
self.tbl_T.reloadData();
self.tbl_T.delegate=self;
self.tbl_T.dataSource=self;
2nd Time data load and add with old array not Working
var myArray :NSArray!
myArray = jsonResult as AnyObject as! NSArray
ary_mutable.addObject(myArray.objectAtIndex(0))
Got This Error
[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
I have Try this code also But Not Working
ary_mutable.addObject(myArray)
You should create a mutable array from immutable. This:
ary_mutable=jsonResult as AnyObject as! NSMutableArray
does not do it, it is just a static cast from one type to another. You have to construct a new NSMutableArray and then fill it with required values.
Change your code to
var ary_mutable = NSMutableArray()
// everytime you receive a new data
ary_mutable.addObjectsFromArray(jsonResult as! [AnyObject])
replace this code:
var myArray :NSArray!
myArray = jsonResult as AnyObject as! NSArray
ary_mutable.addObject(myArray.objectAtIndex(0))
with this code:
var myArray : NSMutableArray!
myArray = jsonResult as AnyObject as! NSMutableArray
ary_mutable.addObjectsFromArray(myArray as [AnyObject]);

Swift Array addObjects to NSMutableArray

I have a Swift Array and I want to add all the objects inside to NSMutableArray
let stringName: String = "Something"
let stringNameSeperated = Array(logoName)
let mutableStringName: NSMutableArray = NSMutableArray(array: stringNameSeperated)
How can I do that?
I'm not really sure what you wanted to archive, but if you just wanted a Swift.Character sequence array, here's a simpler way without even the Array() process: (Notice that the result was casted into String. If you want Character, you will have to modify the code a bit.)
let stringName: String = "Something"
let mutableStringName: NSMutableArray = NSMutableArray(array: map(stringName) { String($0) } )
And from my understanding, you no longer have to case between Swift Array and Objective-C Array, you can use them interchangeably. Also, you can pass a Swift Array to a parameter that expected to be NSArray without problem in Swift 1.x as well.

Resources