getting Swift._SwiftDeferredNSArray' (0x1096d26b8) to 'NSMutableArray in Core Data - ios

I'm working in Swift 3.0 and in which I'm using Core Data to store info. I'm getting user details in NSManagedObject and so in order to display data I want it to convert in NSMutableArray but it shows a run time error,yet it is working fine with NSArray
I'm working hard to find this error but not getting the exact issue.
Any kind of help will surely be appreciated!!!

We can perform all the operation using "Array" which NSMutableArray can do.
let strConstant = " Wolverine"
let birthDate = "17/5/91"
let birthYear = 1991
let currentyear = 2016
Suppose above are the values which we need to handle with "Array" and "NSMutableArray" in Swift3.0
So below I have create a basic operations which you can perform using Array and NSMutableArray both and in both the cases Output will be same.
You can Put the Coding part in any playground, and you can which line perform which task.
Handle operation with Swift Array :
var newRatingList = [Any]()
newRatingList.append(strConstant)
newRatingList.append(birthDate)
newRatingList.append((currentyear - birthYear))
newRatingList.last
newRatingList[1] = "18/5/91"
newRatingList
Handle operation with NSMutableArray :
var mutableArray = NSMutableArray()
mutableArray.add(strConstant)
mutableArray.add(birthDate)
mutableArray.add((currentyear - birthYear))
mutableArray.lastObject
mutableArray.replaceObject(at: 1, with: "18/05/91")
To understand how array works you can also refer the below link :
https://makeapppie.com/2016/06/23/how-to-use-arrays-in-swift-3-0/
Now related to your question consider this is a example
var locations = [Locations]() // Where Locations = your NSManaged Class
var fetchRequest = NSFetchRequest(entityName: "Locations")
locations = context.executeFetchRequest(fetchRequest, error: nil) as [Locations]
// Then you can use your properties.
for location in locations {
print(location.name)
}
In above example you will get a Swift Array of Locations. So by applying For-in loop you can get the Individual properties and if yo want to convert it into array then you can do something like this,
var a = NSMutableArray()
for location in locations {
var dictionary = [String:AnyObject]()
dictionary["name"] = location.name
dictionary["location"] = location.location
a.addObject(dictionary)
}
In the end, you will get "a" NSMutableArray which contain dictionaries.
Hope it helps!

Related

How to access key from [Any] using swift

Am developing a application using swift,in my am integrating cometchat following the link https://docs.cometchat.com/ios-sdk/quick-start/. So am fetching chat history from the server.
Now I got two(sender messages and receiver messages) nsmutablearray value from the server.
i.e., var firstArr = response!["history"]! as! NSMutableArray
var secondArr = response!["history"]! as! NSMutableArray
I merged two nsmuatblearray values and the result i got is:
[
{
from = 1;
id = 68;
localmessageid = "46A9A5E5-FEEC-4588-B7D6-18E88BA68393_2";
message = "ckeck messages";
"message_type" = 10;
old = 1;
self = 1;
sent = 1521185409000;
},
{
from = 2;
id = 69;
localmessageid = "46A9A5E5-FEEC-4588-B7D6-18E88BA68393_1";
message = "sent to thiyakarajan";
"message_type" = 10;
old = 1;
self = 1;
sent = 1521185410000;
}
]
In the responses key value sent is refered as timestamp.
using that sent key(timestamp) help me to sort array in ascending
order.
And also me to load message value in table view.
Thanks
You can access the Array in cellforrowatindexpath method of your TableView by using code like [[yourarray objectAtIndex:indexPath.row]objectForKey:#"message"]. By using this line you can access the value of message of the array at indexPath 0. Also for sorting the Array depending on timestamp please refer the below code:
NSSortDescriptor* sortOrder = [NSSortDescriptor sortDescriptorWithKey: #"sent" ascending: YES];
return [myArray sortedArrayUsingDescriptors: [NSArray arrayWithObject: sortOrder]];
We have used the same in our ReadyUI code. Please refer our ReadyUI source code and email us at support#cometchat.com if you need additional assistance.
It's a very bad practice working with network data like that. Especially if you want to use this data further inside of your app.
You need to parse the data received either in Dictionary or in your own data structure to work with it safely. There're plenty of ways to do that including JSONSerialization, Codable Protocol or even external libraries like SwiftyJSON
After parsing you will have your objects that you can work with without necessity of casting Any type to expected types, which brings a lot of optional checks. So let's say you have your structure called Message that contains all the data from JSON, after getting all the objects you'll have your neat [Message] array that you can pass around the application.
To sort array by some of the properties you simply use function sorted(by:) that is default for any collection. In your case: sortedArray = myArray.sorted(by: {$0.sent < $1.sent})
Now you can use this array as a dataSource for your tableView using UITableViewDataSource protocol
It's obvious that you're pretty new to iOS programming, so I'd recommend to look up for some tutorials on working with networking data. You can watch this video for example, it pretty much sums up everything mentioned above.
Do code like this
Save Swift Array
var firstArr : Array<Dictionary<String, Any>> = response!["history"]! as! Array<Dictionary<String, Any>>
Access valus
let strMessage : String = fistArr[index]["message"] as! String
Will works..!

NSMutableDictionary replicates the last inserted index in each inserted index instead of insert the new index

I've been googling for a while, trying to find a solution to my problem and ended here. I'm trying to create a dictionary of dictionaries to load all the data in tableViewCells.
So I need a key for "name", another key for "description", another key for "image name" and like this..
I'm doing an async call so I've created a global var, nsDict which is a NSMutableDictionary and in the async parseJson Function I've created another NSMutableDictionary named jsonValues.
I use jsonValues to store the data inside the loop. The data is stored with keys too :
jsonValues["name"] = Name
And at the end of the loop I store jsonValues inside nsDict, my NSMutableDictionary global variable.
nsDict.setObject(jsonValues, forKey: c)
c += 1
At this point there is already somebody that knows for sure my issue and my mistake. But I've been trying and reading a lot of stackoverflow and didn't find the way to do something that easy.
My dictionary, is getting filled by all the jsonValues, but instead of inserting diferent values, it's copying all of them. Which is, in the first round of the loop, it insert the first value (dictionary of values). In the second loop, it insert the second dictionary of values in the first and in the second index...
At the end I got 43 same dictionaries. All of them are the copy of the last one...
Does anybody know why? I've spent two hours with this issue. Some help would be very appreciated, thanks!
private func parseJson(json : NSMutableArray, tableView : UITableView){
var jsonValues = NSMutableDictionary()
nsDict.removeAllObjects()
nsDict = NSMutableDictionary.init(capacity: 10)
var c : Int = 0
for j in json {
var nsData : NSMutableDictionary
//clean array
// jsonValues.removeAll()
//Create main value
guard let value = j.valueForKey("value")?.valueForKey("value")! else{
return
}
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
return
}
jsonValues["name"] = Name
title = "Address: "
//Get Address
if let Address = value.valueForKey("Address")?.valueForKey("en") as? String{
jsonValues["Address"] = Address
}
title = "Country: "
//Get country
if let country = geoposition.valueForKey("country") as? String{
let fCountry = title+country
jsonValues["Country"] = fCountry
}else{}
nsDict.setObject(jsonValues, forKey: c)
c += 1
}
doTableRefresh(tableView);
}
just move your var jsonValues = NSMutableDictionary() inside cycle
You create an NSMutableDictionary and insert it repeatedly. The object is inserted, not its contents. Therefore each entry contains the same object. You need to insert a new object at each index.

iOS: how to convert NSUserDefaults stored AnyObject type to array

I have put an array into NSUserDefaults() like so:
NSUserDefaults.standardUserDefaults().setObject(users, forKey: "usersArray")
NSUserDefaults.standardUserDefaults().synchronize()
Then I pull it out like so:
fetchedUserArray = NSUserDefaults.standardUserDefaults().objectForKey("usersArray")
The problem I am facing is that once it is removed from NSUserDefaults it is of type NSArray, preventing me from manipulating it like a Swift array. I have tried this to convert the type, however the compiler does not recognize the variable "castedUsersArray" when it is used later in the code despite not raising any errors upon type casting:
var fetchedArray = NSUserDefaults.standardUserDefaults().objectForKey("usersArray") as? NSArray
var castedUsersArray = fetchedArray as AnyObject as [String]
I have spent a very long time on this with no success. The type constraints of Swift are driving me nuts.
Thank you,
Nick
You almost had it. Don't cast the objectForKey to an Array but rather an Array containing a certain type like you did with castedUsersArray. Don't throw away type information like you did with fetchedArray.
let users = ["Amy", "Bill", "Cindy"]
NSUserDefaults.standardUserDefaults().setObject(users, forKey: "usersArray")
NSUserDefaults.standardUserDefaults().synchronize()
let fetched = NSUserDefaults.standardUserDefaults().objectForKey("usersArray") as? [String] ?? []
The nil coalescing at the end of the line handles the empty NSUserDefaults case.
NSUserDefaults has a specific method to get your stored string arrays called stringArrayForKey:
let stringArray = ["Hello","playground"]
store your string array
NSUserDefaults.standardUserDefaults().setObject(stringArray, forKey: "stringArray")
load it when needed
if let loadedStringArray = NSUserDefaults.standardUserDefaults().stringArrayForKey("stringArray") {
print(loadedStringArray) // ["Hello", "playground"]
}

how to save and read dictionary of touples to NSUserDefaults?

I have an dictionary = String: ([(String)], [(Int)], NSDate, Bool, [(String)]) and I attempted to deconstruct it into seperate arrays when then app calls applicationWillTerminate
var codes = [(String)]()
var messages = [[String]]()
var senders = [[Int]]()
var dates = [(NSDate)]()
var bools = [(Bool)]()
var pairs = [[String]]()
for code in self.dictionary.keys {
codes.append(code)
messages.append(self.dictionary[code]!.0)
senders.append(self.dictionary[code]!.1)
dates.append(self.dictionary[code]!.2)
bools.append(self.dictionary[code]!.3)
pairs.append(self.dictionary[code]!.4)
}
self.userDefaultsMessages.setObject(codes, forKey: "userMessagesArrays")
self.userDefaultsSenders.setObject(messages, forKey: "userSentArrays")
self.userDefaultsDates.setObject(senders, forKey: "userDatesArray")
self.userDefaultsDeletedBool.setObject(dates, forKey: "userDeletedArrays")
self.userDefaultsPairs.setObject(bools, forKey: "userPairsArrays")
self.userDefaultsCodeKeys.setObject(pairs, forKey: "userCodesArrays")
self.userDefaultsCodeKeys.synchronize()
self.userDefaultsMessages.synchronize()
self.userDefaultsSenders.synchronize()
self.userDefaultsDates.synchronize()
self.userDefaultsDeletedBool.synchronize()
self.userDefaultsPairs.synchronize()
and then I attempt to pull it all back together when the app calls applicationDidBecomeActive
//read
if let savedCodesArray : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userCodesArrays") {
self.userCodes = savedCodesArray! as! [String]
if let savedMessagesArray : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userMessagesArrays") {
self.Usermessages = savedMessagesArray! as! [[String]]
if let savedSendersArray : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userSentArrays") {
self.Usersenders = savedSendersArray! as! [[Int]]
if let savedDatesArray : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userDatesArray") {
self.Userdates = savedDatesArray! as! [NSDate]
if let savedBools : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userDeletedArrays") {
self.Userbools = savedBools! as! [Bool]
if let savedPairs : AnyObject? = self.userDefaultsCodeKeys.objectForKey("userPairsArrays") {
self.Userpairs = savedPairs! as! [[String]]
var indexPath: Int = 0
for code in self.userCodes {
self.dictionary[code]! = [self.Usermessages[indexPath], self.Usermessages[indexPath], self.Userdates[indexPath], self.Userbools[indexPath], self.Userpairs[indexPath]]
}
}
}
}
}
}
}
I am fairly new to iOS development and could use help, how would i save the single dictionary = String: ([(String)], [(Int)], NSDate, Bool, [(String)]) to NSUserDefaults and then later read it.. the documentation was not very helpful since it only worked with simple dictionaries
the code looks incredibly cumbersome so I know I can't be doing it right. It should be a simple solution since I only have one variable to save to NSUserDefaults.
Short answer: You can't.
NSUserDefaults will only record "property list objects" (dictionaries, arrays, strings, numbers (integer and float), dates, binary data, and Boolean values).
You can't save any other types of data into NSUserDefaults, or into a property list. The only solution is to convert other data types into those types.
Tuples are not one of those types, so they can't be saved into user defaults.
First, your interaction with NSUserDefaults is completely wrong. You only need to interact with the shared NSUserDefaults.sharedUserDefaults() instance, not create separate instances, which seems to be what you're doing (i.e. userDefaultsMessages, userDefaultsSenders, etc.).
Second, you don't need to call synchronize() at all. There are very few conditions under which you need to call it manually, and this isn't one of them.
Third, the easiest way to store a particular tuple in NSUserDefaults is to convert it into an Array (or NSArray) and store the result. Of course, this assumes that the tuple contains only types that can be serialized, which your example seems to contain. Unfortunately there's no general solution to this, but creating an array from a tuple is straight forward, as you can just map the tuple indices to array indices.
Finally, such large tuples are usually the result of poor design somewhere along the line. Perhaps refactoring would help resolve your storage issue?

NSMutableArray with nested NSMutableDictionary or nested Subclasses

I'm writing an iOS App in Swift and I'm parsing XML data from a server through a Rest API on the server side using the NSXMLParser delegate.
I have the following data structure:
<alarm>
<rootcause> some properties... </rootcause>
<symptoms>
<symptom> some properties... </symptom>
<symptom> some properties... </symptom>
</symptoms>
</alarm>
Right now I'm parsing the data into an NSmutableArray that contains an NSDictionary for each alarm, that contains a nested dictionary for each RootCause and a NSMutableDictionary with symptoms that contains many instances of NSDictionary for each symptom.
1. NSMutableArray: alarms
2. NSmutableDictionary: alarm
3.NSMutabbleDictionary: rootcause
3.NSMutableDictionary: symptoms
4.NSMutableDictionary: symptom1
4. NSMutableDictionary: symptom2
....
Of course this is a little bit complicated data model, so my question is wether I should create Subclasses of NSObject that contain other nested classes and build my data model or I should keep my data structure of nested NSDictionaries.
Or what would be the best approach to manage changes in the data model in the future and better debugging, etc.
The best way is to create your own data structure, something like this:
class symptom
{
let yourValue = ""
let someOtherValue = 0
}
class alarm
{
var rootcause = ""
var symptoms:[symptom] = []
//or if you have just a string
var symptoms:[String] = []
}
Then all you do is:
var alarms:[alarm] = []
for al in allAramsXML
{
let tmp = alarm()
for sym in al.symptoms
{
let tmpSym = symptom()
tmpSym.yourValue = ""
tmp.symptoms.append(tmpSym)
}
alarms.append(tmp)
}
Converting it gives you compiler validation and you don't have to mess around with string keys to get to your data. So you should make model classes, yes.
An example could look like this:
struct Symptom {
let id : Int
let description : String
}
struct Cause {
let id : Int
}
struct Alarm {
let rootCause : Cause
let symptoms : [Symptom]
}
let alarms : [Alarm] = [Alarm(rootCause: Cause(id: 1), symptoms: [Symptom(id: 2, description: "some description")])]

Resources