how to access Array with key in swift4 - arrays

I am very new to swift, I used to code in objective C, but Now I am facing alot of problems while development in Swift. Right now I have json file imported in project
let file = Bundle.main.url(forResource: "test", withExtension: "json")
do {
let data = try Data(contentsOf: file!)
//let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
let json:NSArray = try (JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.mutableContainers) as? NSArray)!
print(json[0])
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
It gives output like
{
Correct = 1;
EA = "50 Days ";
EB = "40 days";
EC = "90 days";
ED = "30 days";
}
And i Need to access only Content with key "EA".
previously with objective C, I used to access it like
[[json objectAtIndex:0] objectForKey:#"EA"]
Now when I am trying to access it like
json[0].objectForKey("EA") as? String
it says
Value of type 'Any' has no member 'objectForKey'
What should I do?

Swift 2
(json[0] as! NSDictionary).objectForKey("EA") as? String
Swift 3 & 4
(json[0] as! NSDictionary).object(forKey: "EA") as? String

Related

Swift 4: Filtering Array

i am new to swift, currently practicing
here i have a plist file, which has an Array Of Dictionaries, each dictionary has one string, the plist has 3 records, it looks like this
item 0:
kurdi: Googlee
item 1:
kurdi: Yahooe
item 2:
kurdi: Binge
here's a image for the plist;
Screenshot 11:52AM
okay so the point is, when a user searches for oo for example two of the records contain oo, such as google and yahoo, i want to return an array of results,
for that case i used:
let path = Bundle.main.path(forResource:"hello", ofType: "plist")
let plistData = NSArray(contentsOfFile: path!)
let objCArray = NSMutableArray(array: plistData!)
if let swiftArray = objCArray as NSArray as? [String] {
let matchingTerms = swiftArray.filter({
$0.range(of: "oo", options: .caseInsensitive) != nil // here
})
print(matchingTerms)
}
but unfortunately, when i print matchingTerms it returns nil
..
thanks
If you are new to Swift please learn first not to use NSMutable... Foundation collection types in Swift at all. (The type dance NSArray -> NSMutableArray -> NSArray -> Array is awful). Use Swift native types. And instead of NSArray(contentsOfFile use PropertyListSerialization and the URL related API of Bundle.
All exclamation marks are intended as the file is required to exist in the bundle and the structure is well-known.
let url = Bundle.main.url(forResource:"hello", withExtension: "plist")!
let plistData = try! Data(contentsOf: url)
let swiftArray = try! PropertyListSerialization.propertyList(from: plistData, format: nil) as! [[String:String]]
let matchingTerms = swiftArray.filter({ $0["kurdi"]!.range(of: "oo", options: .caseInsensitive) != nil })
print(matchingTerms)
Cast swift array to [[String:Any]] not [String]. And in filter you need to check the value of the key kurdi. Try this.
if let swiftArray = objCArray as? [[String:Any]] {
let matchingTerms = swiftArray.filter { (($0["kurdi"] as? String) ?? "").range(of: "oo", options: .caseInsensitive) != nil }
print(matchingTerms)
}

How to access nested JSON in brackets in Swift?

I have a JSON response which is in brackets and I struggle to access the inner fields e.g. display_name with Swift. How can I do that?
Optional(["result": {
user = {
"display_name" = "Max Test";
email = "test.max#gmail.com";
"fb_id" = 10209982554704497;
roles = (
stu
);
schools = "<null>";
};
}])
The code I used to access the JSON:
self.restApi.getProfileDetails() {responseObject, error in
//parse down the first layer of array
let response = responseObject as? [String:AnyObject]
print("response object when MyDetailsController opened")
print(response)
let result = response!["result"] as? [AnyObject]
print("result object")
print(result)
//parse down the second layer of JSON object
if let result = response!["result"] as? [AnyObject] {
print("result object when MyDetailsController opened")
// work with the content of "result", for example:
if let user = result[0] as? [String:AnyObject]{
print(user)
let displayName = user["display_name"]
print("displayName")
print(displayName)
}
}
It seems that I address the result in the wrong way as it is always nil:
The console output:
result object
nil
In response result is dictionary not array, try to get like this
let result = response!["result"] as? [String:AnyObject]
1-Get the result object from response
2-Get the user object from result object
3-Get the user info as String from user object .
let response = responseObject as? [String: AnyObject]
let result = response!["result"] as? [String: AnyObject]
if let user = result!["user"] as? [String: AnyObject] {
let displayName = user["display_name"] as? String
let email = user["email"] as? String
}

How we can find an element from [AnyObject] type array in swift

I have [AnyObject] array
var updatedPos = [AnyObject]()
I am setting data in that according to my requirement like!
let para:NSMutableDictionary = NSMutableDictionary()
para.setValue(posId, forKey: "id")
para.setValue(posName, forKey: "job")
let jsonData = try! NSJSONSerialization.dataWithJSONObject(para, options: NSJSONWritingOptions())
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) as! String
self.updatedPos.append(jsonString)
Now in my code i have some requirement to remove the object from this array where id getting matched according to requirement Here is the code which i am trying to implement
for var i = 0; i < updatedPos.count; i++
{
let posItem = updatedPos[i]
print("Id=\(posItem)")
let pId = posItem["id"] as? String
print("secRId=\(pId)")
if removeId! == pId!
{
updatedPos.removeAtIndex(i)
}
}
Here print("Id=\(posItem)") give me output asId={"id":"51","job":"Programmer"} but here i am not able to access id from this object. here print("secRId=\(pId)") give me nil
First of all use native Swift collection types.
Second of all use types as specific as possible.
For example your [AnyObject] array can be also declared as an array of dictionaries [[String:AnyObject]]
var updatedPos = [[String:AnyObject]]()
Now create the dictionaries and add them to the array (in your example the dictionary is actually [String:String] but I keep the AnyObject values).
let para1 : [String:AnyObject] = ["id" : "51", "job" : "Programmer"]
let para2 : [String:AnyObject] = ["id" : "12", "job" : "Designer"]
updatedPos.append(para1)
updatedPos.append(para2)
If you want to remove an item by id use the filter function
let removeId = "12"
updatedPos = updatedPos.filter { $0["id"] as? String != removeId }
or alternatively
if let indexToDelete = updatedPos.indexOf{ $0["id"] as? String == removeId} {
updatedPos.removeAtIndex(indexToDelete)
}
The JSON serialization is not needed for the code you provided.
PS: Never write valueForKey: and setValue:forKey: unless you know exactly what it's doing.
After some little bit stuffs I have found the very easy and best solution for my question. And I want to do special thanks to #vadian. Because he teach me new thing here. Hey Thank you very much #vadian
Finally the answer is I had covert posItem in json Format for finding the id from Id={"id":"51","job":"Programmer"} this string
And the way is
let data = posItem.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
if let dict = json as? [String: AnyObject] {
let id = dict["id"]
if removeId! == id! as! String
{
updatedLoc.removeAtIndex(i)
}
}
}
catch {
print(error)
}

Parsing JSON into swift predefined array

I am trying to get items from an api (JSON) and to parse it into a predefined swift array. I have searched and looked for hours but due to my lack of skills I wasn't able to find anything suitable my case.
My predefined array looks like this:
init?(participants: String, photoguest: UIImage?, photohome: UIImage?, time: String, stadium: String, channel: String)
the JSON structure is like this(entire json file):
{"gameId":"255","gameWeek":"17","gameDate":"2016-01-03","awayTeam":"SEA","homeTeam":"ARI","gameTimeET":"4:25 PM","tvStation":"FOX","winner":"SEA"}
My current code looks like this (Games is the class where I connect variables from array with table cell items):
var gameplan = [Games]()
func loadNFLgames(){
let apiURL = NSURL(string: "http://www.fantasyfootballnerd.com/service/schedule/json/test/")
let data: AnyObject? = NSData(contentsOfURL: apiURL!)
let homeTeam = (data as! NSDictionary)["homeTeam"] as! String
let awayTeam = (data as! NSDictionary)["awayTeam"] as! String
let gameDate = (data as! NSDictionary)["gameDate"] as! String
let gameTimeET = (data as! NSDictionary)["gameTimeET"] as! String
let tvStation = (data as! NSDictionary)["tvStation"] as! String
/*
for schleife mit API daten:
for gameWeek = currentWeek{ //every game where gameWeek matches currentWeek
*/
// create variables from api calls
let api_guest = awayTeam
let api_home = homeTeam
let api_tvhost = tvStation
let api_time = gameDate + ", " + gameTimeET + " ET" // convert gameDate to day e.g. SUN
let api_stadion = "N/A"
// prepare data for array
let gamedata = Games(participants: api_guest+" # "+api_home, photoguest: UIImage(named: api_guest), photohome: UIImage(named: api_home), time: api_time, stadium: api_stadion, channel: api_tvhost)!
// add data to array
gameplan.append(gamedata)
}
I am getting the following error:
Could not cast value of type '_NSInlineData' (0x1a0cfd428) to
'NSDictionary' (0x1a0cf3380).
EDIT: The error is being thrown here:
let homeTeam = (data as! NSDictionary)["homeTeam"] as! String
Your help is highly appreciated.
Thanks in advance!
hello your data variable doesn't contain the Json you r looking for. so you have to serialize it to json like alexander suggested but NSJSONSerialization can throw an error so we have tu put in in try
so your code will be something like this (i suggest always using dispatch_async to make it in background thread than use the completion closure to get your result)-->
func loadNFLgames(completionClosure: (result : [Games]) ->()){
let queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {
let URL = "http://www.fantasyfootballnerd.com/service/schedule/json/test/"
print(URL)
if let data = NSData(contentsOfURL: NSURL(string: URL)!){
if let JsonObject = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSMutableDictionary{
print(JsonObject)
//here you can loop through the JsonObject to get the data you are looking for
//when you get your array of Games just pass it the the completion closure like this
completionClosure(result: gameplan)
}
}
})
}
PS: please let me know if you need more help.
Your data variable is NSData type (not NSDictionary). You have to convert it in order to use it. Try something like that:
let decodedJson = NSJSONSerialization.JSONObjectWithData(data, options: nil) as! NSDictionary
And than you can use it like standard dictionary
let homeTeam = decodedJson["homeTeam"] as! String

Compiling Swift source files hangs on large array reduce-combine + expressions

In my tests I'm used to write Strings in arrays in different lines like
let jsonString = ["{"
,"\"url\": \"http://localhost:8090/rest/api/3\","
, "\"id\": \"3\","
, "\"description\": \"A test that needs to be done.\","
, "\"name\": \"Test\","
, "\"subtest\": false,"
, "\"avatar\": 1"
,"}"].reduce("", combine: +)
That works fine, still my array get 145 lines for a large test json string.
With 145 lines (or maybe less, didn't tried it line by line) the build task hangs while "Compiling Swift source files".
First, that is a bit crazy. 30 lines are ok, 145 not? What?
Second, what is a better solution to write a String in multiple lines in Swift? - I don't want to load a json and parse it from an external file.
This is probably because of type inference.
Try giving an explicit [String] type to an array variable to help the compiler figure it out, then apply reduce to the variable.
let arrayOfStrings: [String] = ["{"
,"\"url\": \"http://localhost:8090/rest/api/3\","
, "\"id\": \"3\","
, "\"description\": \"A test that needs to be done.\","
, "\"name\": \"Test\","
, "\"subtest\": false,"
, "\"avatar\": 1"
,"}"] // etc
let jsonString = arrayOfStrings.reduce("", combine: +)
Anyway, to create JSON you should make a dictionary then serialize it with NSJSONSerialization, this is less error prone:
Swift 2
do {
// Create a dictionary.
let dict = ["url": "http://localhost:8090/rest/api/3", "id": "3"] // etc
// Encode it to JSON data.
let jsonData = try NSJSONSerialization.dataWithJSONObject(dict, options: [])
// Get the object back.
if let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as? [String:String] {
print(jsonObject)
}
// Get it as a String.
if let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding) {
print(jsonString)
}
} catch let error as NSError {
print(error)
}
Swift 3
do {
// Create a dictionary.
let dict = ["url": "http://localhost:8090/rest/api/3", "id": "3"] // etc
// Encode it to JSON data.
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [])
// Get the object back.
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String:String] {
print(jsonObject)
}
// Get it as a String.
if let jsonString = String(data: jsonData, encoding: String.Encoding.utf8) {
print(jsonString)
}
} catch let error as NSError {
print(error)
}

Resources