How to access key from [Any] using swift - ios

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..!

Related

Accessing Dictionary element for a tableview

I have passed a dictionary to a second view controller and assigned it to an array, I thought I could access the data easier this way:
var myAlerts: NSDictionary!
The dictionary has three elements for each: Id (which I don't care about), alertDate, and alertNote.
I'm trying to get these elements into a tableView but struggling with this.
I thought about just moving it into two arrays and accessing it that way, cumbersome but it at least gets me further down the road so to speak.
Here is the raw data from the dictionary AFTER it was past to the second controller:
{
alerts = (
{
alertDate = "2017-07-16";
alertNote = "Rob is the worlds greatest friend";
id = 2;
},
{
alertDate = "2017-07-17";
alertNote = "This is a test of the emergency system";
id = 1;
}
);
}
When I tried to move the values into two arrays with this:
func CreateArray() {
for i in 0...myAlerts.count {
alertsDate[i] = myAlerts["alerts"]["alertDate"]
alertsNote[i] = myAlerts["alerts"]["alertNote"]
}
}
I get the proverbial Type Any? has no subscript members.
Any help would be appreciated.
myAlerts with that data is now a dictionary containing an array of dictionaries. (so top level is a dictionary, with one key/value pair which is of type array of [String:Any] objects).
Since a dictionary value is of type Any, it can't infer in this case what the type of the value for the key alerts is. So you have to try cast it to a specific type first, in this case an array of dictionaries, i.e. [[String:Any]]
So this should get rid of your error:
func CreateArray() {
for i in 0...myAlerts.count {
let alertArray = myAlerts["alerts"] as! [[String:Any]]
alertsDate.append(alertArray[i]["alertDate"] as! String)
alertsNote.append(alertArray[i]["alertNote"] as! String)
}
}
Note: I had to change alertsDate and alertsNote arrays to using append as in my demo code i had no existing items in the array and using and index would have caused an error.

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

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!

Group TableView items from NSArray returned in JSON Response in Swift

I have a table view and I want to populate the table view with the values provided to me in a JSON response in the form of NSArray and I have used the code below to extract this NSArray:
dispatch_async(dispatch_get_main_queue(), {
print(json)
if let listDictionary = parseJSON["list"] as? NSArray {
print("LIST: \(listDictionary)")
}
})
In JSON response, I get the following array of two elements as shown below:
list = (
{
"is_cover" = 0;
"is_recommand" = 0;
name = "Helena's Signature Dish";
ord = 5;
price = "105.00";
remark = "Helena's special made dish is one of the most priced and delicious dishes in the whole world.";
thumb = "56c351887a0e0.jpg";
},
{
"is_cover" = 0;
"is_recommand" = 0;
name = "Pineapple Fried Rice";
ord = 6;
price = "110.00";
remark = "We have the most delicious pineapple rice in the whole world!";
thumb = "56c704e15da79.jpg";
}
);
Now I want to show the value "name", "price" and "remark" fields from each element in the array into a UITableView.
But I can't find a way to break the values for name, price and remark for each element and put them into an another array so they can be displayed in a table view somehow because each element contains a very long string and I only need to extract some values from this string. Can anyone please help me with this as I'm very new to Swift.
Thanks!
You don't need to make a second array, Only extarct particular json from array in cellForRowatIndexPath on dictinary by objectatindex method of array and now you can access.
You can achieve it by creating a model Class which contains only
those properties which you needed.
Once you get the response array from server , iterate though each
dictionary and create a Model Object.Add this model objects in the
Array.
Use this model object in the Array for applying data in your cell using the index
One more thing to add is always prefer using objects as it gives (.)dot syntax & autosuggestion, so there will be less chances of
making mistakes. As if you use Dictionary there will be more chances
of using incorrect key getting crash
I fixed this by putting values in "name", "price" and "remark" fields into another array using flatMap as shown below:
let nameArray = listArray.flatMap({ element in (element["name"] as? String)! })
And then I got something like:
Name's: (
"Helena's Special Dish",
"Pineapple Fried Rice"
)
and then in the tableView function for cellForRowAtIndexPath I grouped the values in tableview.

I'm having trouble fetching entities from core data based on relationships with predicates

Quick background: I have en ExamEntity, which is linked via a relationship to sections covered in the exam (SectionEntity), which is linked via a relationship to the subsections under each section (SubsectionEntity).
What I'm try to do is fetch the sections and related subsections which will be covered be a selected Exam, and store them in a dictionary which can hold multiple string values per key.
My code starts like this:
var sectionsDictionary = [String:[String]]()
//---Fetch Section Entity
let sectionPredicate = NSPredicate(format: "(exam = %#)", selectedExam)
let sectionsFetchRequest:NSFetchRequest = SectionEntity.MR_requestAllWithPredicate(sectionPredicate)
let fetchedSections:NSArray = SectionEntity.MR_executeFetchRequest(sectionsFetchRequest)
All good here. But then I try and fetch the subsections related to the selected sections and things go wrong.
following Code:
for section in fetchedSections {
let sectionName = section.valueForKey("name") as! String
// //error occurs on the line below
let subsectionPredicate = NSPredicate(format: "(section = %#)", section as! SectionEntity)
let subsectionsFetchRequest:NSFetchRequest = SubsectionEntity.MR_requestAllWithPredicate(subsectionPredicate)
let fetchedSubsections:NSArray = SubsectionEntity.MR_executeFetchRequest(subsectionsFetchRequest)
The error I get is:
Could not cast value of type 'NSManagedObject_SectionEntity_' (0x7fb363e18580) to 'MyApp.SectionEntity' (0x10c9213e0).
The next few lines are supposed to iterate through the fetched results, adding their names as values to the dictionary with section names as keys.
for subsection in fetchedSubsections{
let subsectionName = subsection.valueForKey("name") as! String
sectionsDictionary[sectionName] = [subsectionName]
}
}
thanks in advance.
You're not defining the type of the class for your record
Go to the Project.xcdatamodeld file, and select your SectionEntity
Check if the field Class is like this
If it is then write in the Class field "SectionEntity" and press Enter, it should be like this
Then try again
You need to make sure that the elements of the collection you enumerate are of the correct type.
Presumably, Magical Record will return an NSArray of NSManagedObject items. You need to make sure Swift knows what type section is.
for object in fetchedSections {
let section = object as! SectionEntity
// ...
}
Also, see my answer about the unsuccessful casts to NSManagedObject subclasses.

How to create and access a NSDictionary in Swift

I am busy converting to Swift and am trying to figure out how to do the following in Swift
NSArray arrayOfStrings1 = {#"Substring1", #"Substring2", nil};
Dictionary dict = {#"MainString1", arrayOfStrings1};
So in Swift I have the following:
var dictionary = [String: Array<String>]() // is this correct ??
var array: [String] = ["Substring1", "Substring2"]
dictionary["MainString1"] = ["Substring1.1", "Substring1.2"]
dictionary["MainString2"] = ["Substring2.1", "Substring2.2"]
Now in order to access the array I use
let array = dictionary["MainString1"]
let item0 = array[0]
but this fails with a compiler error which seems to indicate that array is in fact a String not an array of strings.
What am I missing here?
The issue is actually that a subscript lookup for a Dictionary in Swift returns an optional value:
This is a pretty great feature - you can't be guaranteed that the key you're looking for necessarily corresponds to a value. So Swift makes sure you know that you might not get a value from your lookup.
This differs a little bit from subscript behavior for an Array, which will always return a value. This is a semantically-driven decision - it's common in languages for dictionary lookups to return null if there is no key - but if you try to access an array index that does not exist (because it's out of bounds), an exception will be thrown. This is how Swift guarantees you'll get a value back from an array subscript: Either you'll get one, or you'll have to catch an exception. Dictionaries are a little more lenient - they're "used to" not having the value you're asking for.
As a result, you can use optional binding to only use the item if it actually has a value, like so:
if let theArray = dictionary["MainString1"] {
let item0 = theArray[0]
} else {
NSLog("There was no value for key 'MainString1'")
}

Resources