I am getting a dictionary as JSON response from server.From that dictionary there is a key "error" now i want to get the value of "error" key.I know that error always will be either 0 or 1.So i tried to get it as boolean but it did not work for me.Please suggest how can i convert its value to boolean.
let error=jsonResult.objectForKey("error")
//this does not work for me
if(!error)
{
//proceed ahead
}
Bool does not contain an initializer that can convert Int to Bool. So, to convert Int into Bool, you can create an extension, i.e.
extension Bool
{
init(_ intValue: Int)
{
switch intValue
{
case 0:
self.init(false)
default:
self.init(true)
}
}
}
Now you can get the value of key error using:
if let error = jsonResult["error"] as? Int, Bool(error)
{
// error is true
}
else
{
// error does not exist/ false.
}
Very Simple Way: [Updated Swift 5]
Create a function:
func getBoolFromAny(paramAny: Any)->Bool {
let result = "\(paramAny)"
return result == "1"
}
Use the function:
if let anyData = jsonResult["error"] {
if getBoolFromAny(anyData) {
// error is true
} else {
// error is false
}
}
Also, if you want one line condition, then above function can be reduced like:
if let anyData = jsonResult["error"], getBoolFromAny(anyData) {
// error is true
} else {
// error is false
}
Updated
Considering jsonResult as NSDictionary and error value is Bool. you can check it by following way.
guard let error = jsonResult.object(forKey: "error") as? Bool else{
// error key does not exist / as boolean
return
}
if !error {
// not error
}
else {
// error
}
Your error is neither 0 or 1. It is an optional object. It is nil if there was no key "error" in your JSON, otherwise it's probably an NSNumber.
It is most likely that nil means "no error" and if it's not nil and contains a zero it means "no error" and if it's not nil and contains a one it means "error" and if it's not nil and contains anything else then something is badly wrong with your json.
Try this:
let errorObject = jsonResult ["error"]
if errorObject == nil or errorObject as? NSInteger == 0
When I say "try", I mean "try". You're the responsible developer here. Check if it works as wanted with a dictionary containing no error, with a dictionary containing an error 0 or 1, and a dictionary containing for example error = "This is bad".
Check equality between error and 0 instead:
let error = jsonResult.objectForKey("error")
if error == 0 {
// proceed
}
Another Important point here is, you're using Swift and parsing the repsonse as NSDictionary. I can say that because you're using objectForKey method. Best practice would be to parse it as Swift Dictionary.
It may look like Dictionary<String:AnyObject> or [String:AnyObject]
Then you can check for the error as :
if let error = jsonResult["error"] where error == 0 {
//your code
}
Below code worked for me
if let error = jsonResult["error"] as? Int where Bool(error)
{
// error is true
print("error is true")
}
else
{
// error does not exist/ false.
print("error is false")
}
Related
I have this function
func pickAttraction(attractionType: Array<Attraction>) -> Attraction {
let randAttr = attractionType[5]
if favoritesNames.contains(randAttr.attractionName) {
return pickAttraction(attractionType: attractionType)
} else {
return randAttr
}
}
and my program crashes (sometimes) on the line starting with "if favoritesNames". On the last time it crashed, the array favoritesNames had 1 string inside, and randAttr.attractionName had a different string. I expected it to return randAttr, but it crashed instead. Does anyone have any idea why?
I also tried
if favoritesNames.contains(randAttr.attractionName) || favoritesNames[0] == randAttr.attractionName {
and I got the same error
I've also tried
func pickAttraction(from attractions: [Attraction]) -> Attraction? {
attractions.filter { !favoritesNames.contains($0.attractionName) }
.randomElement()
}
instead of the other function and I still get the same error
Thank you
I believe let randAttr = attractionType[5] is accessing an index that doesn't exist. Can you verify that there is available data if you access the array at [5]?
I am using Parse and PFUser in a Swift iOS app, and find myself in a case where PFUser.current() does not do exactly what I want, due to synchronisation issues.
For that reason I am trying to use: PFUser.getCurrentUserInBackground().
I got started with the code below, inspired from what can be found here: https://github.com/BoltsFramework/Bolts-ObjC.
But this document probably being a bit outdated, it does not quite work.
let userCheckTask = PFUser.getCurrentUserInBackground()
userCheckTask.continueWith {
(task: BFTask!) -> BFTask<AnyObject> in
if task.isCancelled() { // Error-1.
// the save was cancelled.
} else if task.error != nil {
// the save failed.
} else {
// the object was saved successfully.
var object = task.result() as PFObject // Error-2.
}
}
The compiler gives me two errors, this one on the line marked "Error-1"
Cannot invoke 'isCancelled' with no arguments
And this other one on the line marked "Error-2"
Expression type 'PFUser?' is ambiguous without more context
I have no idea what kind of argument 'isCancelled' is expecting.
Does anyone know how to fix those?
let userCheckTask = PFUser.getCurrentUserInBackground()
userCheckTask.continueWith {
(task: BFTask) -> BFTask<AnyObject> in
if let e = task.error {
return BFTask(error: e)
} else {
return BFTask(result: task.result)
}
}
I have a service class that offers several methods that make calls to the backend, and a common theme for those methods is that I can pass callbacks for the success and error cases:
func makeCall(onSuccess: #escaping APIResponse, onError: #escaping APIError)
The type APIError is defined like so:
typealias APIError = (Error) -> Void
Furthermore I have an enum APICallError like this:
enum APICallError: Error {
case insufficientCredentials
case malformedResponse
case forbidden
}
So in my service methods I can call onError(response.result.error!) if the result contained an error object (the force unwrap is just for brevity, I'm not really doing that) and also pass my own enum value if the HTTP result is not specific enough, like onError(APICallError.insufficientCredentials).
This works fine.
The problem is, I can't figure out how to evaluate in my client code whether the error parameter that's coming in is of type APICallError and which one of those specifically. If I do:
if let callError = error as? APICallError {
if callError == .forbidden {
// ...
}
}
execution doesn't make it past the typecast. if error is APICallError also does not seem to work.
How can I cast the error parameter to my APICallError enum value that I know is in there, because when I print(error) it gives me myapp.APICallError.forbidden?
I tried to simulate what you have posted in your question in Playground, and what you are already doing should work fine for you.
if error is APICallError is also working. One possibility why the if let condition fails might be due to the error being nil. Check if that is the case by using breakpoints.
typealias APIError = (Error) -> Void
//The error type used in your question
enum APICallError: Error {
case insufficientCredentials
case malformedResponse
case forbidden
}
//A different error type for comparison
enum AnotherError: Error {
case error1
case error2
case error3
}
let apiCallError: Error = APICallError.insufficientCredentials
let anotherError: AnotherError = AnotherError.error1
//Closure definition
var onError: APIError? = { inputError in
if let apiError = inputError as? APICallError {
print("APICallError")
}
if let anotherError = inputError as? AnotherError {
print("AnotherError")
}
}
//Above defined closure is called here below...
onError?(apiCallError)
onError?(anotherError)
Console Output (Works as expected):
APICallError
AnotherError
You need to use the enum rawValue constructor.
if let callError = APICallError(rawValue: error) {
if callError == .forbidden {
...
}
} else {
// was not an APICallError value
}
https://github.com/daltoniam/JSONJoy-Swift
For example :
JSON1 = {
"message": "Sorry! Password does not match.",
"code": "4"
}
JOSN2 = {
"data": {
"id": 21
},
"message": "Signup Successful.",
"code": "1"
},
Here json key “data” is optional. Then how I can handle both response using the same model object??
JSONJoy natively sets not found elements to nil, you just have to declare them optional and then check for nil before using them.
From the docs
This also has automatic optional validation like most Swift JSON libraries.
//some randomly incorrect key. This will work fine and the property
will just be nil.
firstName = decoder[5]["wrongKey"]["MoreWrong"].string
//firstName is nil, but no crashing!
Here is my example that my be illustrative. I have a complex object set where my top level object (UserPrefs) has arrays of secondary objects (SmartNetworkNotification and SmartNotificationTime).
Note that notifications and times are both declared as optional. What I do is check for nil after attempting to parse the secondary object arrays. Without the nil check the attempt to iterate on the parsed list fails since its nil. With the nil check it just moves past it if its empty.
This works for me but isn't deeply tested yet. YMMV! Curious how others are handling it.
struct UserPrefs: JSONJoy {
var notifications: [SmartNetworkNotification]?
var times: [SmartNotificationTime]?
init(_ decoder: JSONDecoder) throws {
// Extract notifications
let notificationsJson = try decoder["notifications"].array
if(notificationsJson != nil){
var collectNotifications = [SmartNetworkNotification]()
for notificationDecoder in notificationsJson! {
do {
try collectNotifications.append(SmartNetworkNotification(notificationDecoder))
} catch let error {
print("Error.. on notifications decoder")
print(error)
}
}
notifications = collectNotifications
}
// Extract time of day settings
let timesJson = try decoder["times"].array
if(timesJson != nil){
var collectTimes = [SmartNotificationTime]()
for timesDecoder in timesJson! {
do {
try collectTimes.append(SmartNotificationTime(timesDecoder))
} catch let error {
print("Error.. on timesJson decoder")
print(error)
}
}
times = collectTimes
}
}
Hey stackoverflow members,
I work really hard on getting better on Swift, now I have a trivial problem. I'm a former C# developer so Error Handling until now was try {}... catch {}... Message... Done!
Now I'm developing an App which uses some JSON APIs. It's all working, downloading JSON Data, pack them into my Objects but there is one problem. The proper Error Handling..
I have the following code to download & parse JSON:
//Download & Parse JSON
func getJSON(urlToRequest: String) -> NSDictionary {
var url: NSURL = NSURL(string: urlToRequest)
var jsonRequest: NSURLRequest = NSURLRequest(URL: url)
var jsonResponse: AutoreleasingUnsafePointer<NSURLResponse?> = nil
var error: NSError?
var dataValue: NSData = NSURLConnection.sendSynchronousRequest(jsonRequest, returningResponse: jsonResponse, error:&error)
if error.description.isEmpty {
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataValue, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
if error.description.isEmpty {
return jsonResult
}
else {
return NSDictionary(object: "Error: Something with parsing went wrong :(", forKey: "error")
}
}
else {
return NSDictionary(object: "Error: There was an error with your connection :(", forKey: "error")
}
}
The error part is just temporary, the problem is my ViewController just calls one function to get the whole data for the week (days, matchups and so on)
I call it this way:
var rWrapper = RiotWrapper()
let lcsWeek: Week = rWrapper.getWeek("2014-07-07")
My getWeek method calls 3-4 functions which all parse JSON data in relation to the previous responses.
Ok, long story short question: I want to abort all Tasks if JSON or HTTP fails and fill my TableView just with an error message, how can I achieve this?
Something like: if error occurred -> Stop whatever you are doing -> return for example a null erm.. nil for week -> print error
Can someone help me? If someone have some lecture according this topic it will be fine also :D
Thanks in advance!
Btw: sorry for my "bad" english
All of your JSON parsing methods including getWeek should return a tuple with an optional return value and an error. If at any point you get an error in one of your methods from the JSON parsing, just immediately return the error with nil for the return value. Each method up the chain should check for an error from the previous methods and immediately return the error if it finds one:
func getWeek(string : String) -> (Week?, NSError) {
let (result, error) = self.otherMethod()
if error {
return (nil, error)
}
// continue happily ...
}
I would suggest having your function return an optional. It is easy to test and functions can be chained and shortcut.
func getWeek(string : String) -> Week? {
...
if error {
return nil
}
}
This can be quickly evaluated like this:
if let week = getWeek("2014-07-07") {
// handle success case
} else {
// handle nil
}
and check here for how to string together a number of functions that return optional:
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html