I am using the following code to get data from an API:
typealias JSONdic = [String: AnyObject]
if let json = json as? JSONdic, history = json["history"] as? JSONdic, hour = history["hour"] as? String {
println(hour)
}
However, Xcode tells me that "json" is not a recognized identifier. I believe this can be solved with NSURLConnection, but I have no idea how to use that. Can anyone provide any examples of this protocol in use?
You're declaring a variable by setting it to itself, which doesn't make any sense. In order to use a variable on the right hand side of an assignment, it needs to have already been declared. So let's give json a value outside of the casting statements and it works fine.
typealias JSONdic = [String: AnyObject]
let json: AnyObject = ["greeting": "Hello"]
if let json = json as? JSONdic, history = json["history"] as? JSONdic, hour = history["hour"] as? String {
println(hour)
}
Related
Having this code:
let object = json as? [Any] {
if let questionari=object["questionnarie"] as? [Dictionary<String, AnyObject>]{
}
Compiler (of course) says to me that I can't use a String's index while it's [Any]: I can't find the proper why to cast it as String.
You should be casting your json object as so:
if let object = json as? [String:Any] {
...
Try this code-
if let object = json as? [String:Any] {
if let questionari=object["questionnarie"] as? [Dictionary<String, AnyObject>]{
}
you can make componentsJoined string with "," from any array.
like one line code see bellow example:
let yourStringVar = NSArray(array:ANY_ARRAY_NAME).componentsJoined(by: ",")
Everything works swimmingly except for when I do a random string like "fds", how would I correctly and efficiently use a guard to protect from this sort of error?
init(weatherData: [String: AnyObject]) {
city = weatherData["name"] as! String
let weatherDict = weatherData["weather"]![0] as! [String: AnyObject]
description = weatherDict["description"] as! String
icon = weatherDict["icon"] as! String
let mainDict = weatherData["main"] as! [String: AnyObject]
currentTemp = mainDict["temp"] as! Double
humidity = mainDict["humidity"] as! Int
let windDict = weatherData["wind"] as! [String: AnyObject]
windSpeed = windDict["speed"] as! Double
}
how would I correctly and efficiently use a guard to protect from this sort of error?
Why would you want to? If the caller does not hand you a dictionary whose "name" key is present and is a string, you are dead in the water because you cannot initialize city. You want to crash.
If you would like to escape from this situation without actually crashing, then make this a failable initializer and fail (return nil) if the dictionary doesn't contain the needed data. This effectively pushes the danger of crashing onto the caller, because the result will be an Optional that might be nil, and the caller must check for that.
init?(weatherData: [String: AnyObject]) {
guard let city = weatherData["name"] as? String else {return nil}
self.city = city
// ... and so on ...
}
But what I would do is none of those things. I would rewrite the initializer as init(city:description:icon:currentTemp:humidity:windSpeed:) and force the caller to parse the dictionary into the needed data. That way, if the data is not there, we don't even try to initialize this class in the first place. My argument would be that it is the caller's job to parse the dictionary; this class should have no knowledge of the structure of some complex dictionary pulled off the Internet (or whatever the source is).
So I am currently working on a personal project to help understand API's and how they work..so I am still a little new to iOS Development. I have already connected to the URL and gotten the data however now I am trying to make the results a little bit more clear cut.
Below is the code for the class (when the button is clicked it prints all this information)
First part of code
Second part of code
The error I get is Type 'Any' has no subscript members. Any idea as to why? Or how this can be fixed?
you can set their types like this then you can print values.
if let main = json["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
let temp_max = main["temp_max"] as? Double
print("temp\(temp_max!)")
let temp_min = main["temp_min"] as? Double
print("temp\(temp_min!)")
}
let items = json["weather"] as! [AnyObject]
let main = items[0]["main"] as! String
print(main)
let description = items[0]["description"] as! String
print(description)
let icon = items[0]["icon"] as! String
print(icon)
let name = json["name"] as! String
print("name\(name)")
This code works fine in Swift 2:
guard let userData = responseData["UserProfile"] as? [String : AnyObject] else { return }
var userProfileFieldsDict = [String: String]()
if let profileUsername = userData["Username"] as? NSString {
userProfileFieldsDict["username"] = String(profileUsername)
}
if let profileReputationpoints = userData["ReputationPoints"] as? NSNumber {
userProfileFieldsDict["reputation"] = String(profileReputationpoints)
}
But, in Swift 3 it throws an error on userProfileFieldsDict["reputation"] saying
init has been renamed to init(describing:)
My question is why does it trigger on that line and not on the userProfileFieldsDict["username"] assignment line, and how to go about fixing it? I'm assuming it's because I'm casting a NSNumber to a String, but I can't really understand why that matters.
NSNumber is a very generic class. It can be anything from a bool to a long to even a char. So the compiler is really not sure of the exact data type hence it's not able to call the right String constructor.
Instead use the String(describing: ) constructor as shown below
userProfileFieldsDict["reputation"] = String(describing: profileReputationpoints)
Here's more info about it.
You need to drop your use of Objective-C types. This was always a bad habit, and now the chickens have come home to roost. Don't cast to NSString and NSNumber. Cast to String and to the actual numeric type. Example:
if let profileUsername = userData["Username"] as? String {
userProfileFieldsDict["username"] = profileUsername
}
if let profileReputationpoints = userData["ReputationPoints"] as? Int { // or whatever
userProfileFieldsDict["reputation"] = String(profileReputationpoints)
}
I have a lot of issues in my code with this error. Hopefully if someone can help me here than I can figure out the rest of the problems. I have updated to xcode 7.3 and running swift 2.2.
I have read that the compiler has been "more restrictive", and I have to tell it what the "intermediary" objects are. This is causing me some confusion and would love further explanation.
func getMessage(dictionary:NSDictionary)->String{
var message = String()
if let dict = dictionary["aps"] {
if let message:String = dict["alert"] as? String {
return message
}
else{
message = ""
}
}
return message
}
Another example:
for object in objects {
let getDriver = object.objectForKey("driver")
if let picture = getDriver!["thumbnailImage"] as? PFFile {
self.profilePictures.append(picture)
}
self.requestsArray.append(object.objectId as String!)
}
The type of a dictionary value is always AnyObject. Cast the type to something more specific for example
if let dict = dictionary["aps"] as? [String:AnyObject] {
then the compiler knows that key subscripting is valid and possible
The second example is similar: object is a dictionary and the compiler needs to know that the value for key driver is also a dictionary
if let getDriver = object.objectForKey("driver") as? [String:AnyObject] {
if let picture = getDriver["thumbnailImage"] as? PFFile {
...