0

I'm using Swift 5.

Why does an NSInvalidArgumentException occur when responseValues["CustomerID"] == '<null>'?

Obviously the if responseValues["CustomerID"] is NSNull is not doing the trick. What check should be in place to avoid the NSInvalidArgumentException

self.api.getCustomerId(callback: { getIDResult in
  if let responseValues = getIDResult["ResponseValues"] {

    print("GET CUSTOMER ID RESULT")
    print(responseValues)

    if responseValues["CustomerID"] is NSNull { // <---- crashes here when null
        print("CustomerID is null")
    }
    else{
        print("CustomerID is NOT null")
    }
  }
})

Succesful result

GET CUSTOMER ID RESULT
{
    CustomerID = 403254;
}
CustomerID is NOT null

Crashing result when encountering a null customer id

GET CUSTOMER ID RESULT
{
    CustomerID = "<null>";
}

crashes with the following

019-11-21 12:13:16.819033-0500 MyApp[29412:4207932] -[NSNull _fastCStringContents:]: unrecognized selector sent to instance 0x7fff80615710
2019-11-21 12:13:16.820557-0500 MyApp[29412:4207932] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull _fastCStringContents:]: unrecognized selector sent to instance 0x7fff80615710'

Someone was questioning whether the value was actually null, here's some debug info on that dictionary:

enter image description here

Sam Luther
  • 1,170
  • 3
  • 18
  • 38
  • Drop `SwiftyJSON` and use `Decodable`. It maps `` values implicitly to `nil`. However actually this code must not crash. – vadian Nov 21 '19 at 17:30
  • your api delivers the wrong format. customerID is not nil or NULL it is a string "" -> Api should fix this or you have to use a ugly string check to solve your problem in the first step – Thomas G. Nov 21 '19 at 19:19
  • You are wrong about that smarty pants, the api is fine, it is null, NSNull to be more precise : ) – Sam Luther Nov 21 '19 at 19:23
  • :) btw. the api do not know anything about NSNull. It is a different between customerID: "null" and customerID: null – Thomas G. Nov 21 '19 at 19:29
  • Yeah im aware the api doesnt know anything about NSNull. My problem is dealing with NSNull and NOT the string "null", to be more precise my problem is a NSInvalidArgumentException which results from this value being null – Sam Luther Nov 21 '19 at 19:32
  • I do not get your point. You have to be clear. Maybe you could post a real json or show us your api layer implementation. Otherwise it is hard to follow up – Thomas G. Nov 21 '19 at 19:40
  • it would be hard for me to be more clear. I'm showing the real json in my question – Sam Luther Nov 21 '19 at 19:49
  • That may be a bug of SwiftyJSON. Avoid using such fossil-like framework. – OOPer Nov 22 '19 at 11:24
  • I have the exact same problem as you! – Gomino Apr 16 '20 at 10:56

1 Answers1

0

if responseValues is a dictionary, you can do this

if let customerId = responseValues["CustomerID"] as? String
{
   print(customerId)
}
else
{
   print("customer id isn't available")
}

if you want to know if is null, you have to change to Codable

Andres Gomez
  • 458
  • 3
  • 12
  • what kind of data is getIDResult? – Andres Gomez Nov 21 '19 at 17:40
  • its a dictionary { CustomerID = ""; } – Sam Luther Nov 21 '19 at 17:51
  • well, can you check if the key is nill? with this code you can do it `let keyExists = responseValues["CustomerID"] != nil if keyExists{ print("The key is present in the dictionary") } else { print("The key is not present in the dictionary") }` – Andres Gomez Nov 21 '19 at 17:55
  • no need to do that, I already know the key exists. null id RESULT in my question shows the dict being returned with the null value – Sam Luther Nov 21 '19 at 18:04
  • ok, if your dictionary come from an api request, and the key exists, try this `var result = responseValues["CustomerID"] as! Any switch result{ case Optional.none: print("nil") default: print("not nil") }` – Andres Gomez Nov 21 '19 at 18:16
  • na, that also craps out with the same error. I've tried just about every cast and check and everyone fails – Sam Luther Nov 21 '19 at 18:20