简体   繁体   中英

Unwrapping a value using SwiftJSON results in an error on iOS13

I have an external api providing the data, which I need to decode and assign to a label in my view.

I am using the following in a collectionView so don't mind the collectionView.tag and indexPath.row

I am also using SwiftyJson to parse json values .string providing and optional value

let value = servicesResponse["data"][collectionView.tag]["subcategories"][indexPath.row]["name"].string

Now when I try to assign this value to a label

cell.serviceName.text = value

I get an error:

'NSInvalidArgumentException', reason: '*** -[NSPlaceholderString initWithString:]: nil argument'

I had to put the value inside something like this when assigning:

`"\(value)"`

This works fine but it has the Optional text around the values.

I also tried to:

  • unwrap the value cell.serviceName.text = value! gives the same error
  • used .stringValue instead of .string which gives the non-optional value gives the same error -used .rawString instead of .string gives the same error
  • tried unwrapping it this way
if let value = servicesResponse["data"][collectionView.tag] 
   ["subcategories"][indexPath.row]["name"].string {
        cell.serviceName.text = value
}

same error

  • and tried giving it a default value cell.serviceName.text = value ?? "default" cell.serviceName.text = value ?? "default" same error

i just tried to check all the response on by one like this:

if servicesResponse["data"] != JSON.null{
            if servicesResponse["data"][collectionView.tag] != JSON.null{
                if servicesResponse["data"][collectionView.tag]["subcategories"] != JSON.null{
                    if servicesResponse["data"][collectionView.tag]["subcategories"][indexPath.row] != JSON.null{
                        if servicesResponse["data"][collectionView.tag]["subcategories"][indexPath.row]["name"] != JSON.null{
                            print("ALL PASS=========================")
                        }
                    }
                }
            }
        }

and all of the pass

I'd like to know if there is a way to remove the text Optional while the value is still optional or if anyone knows what this error means and why it happens.

The error only occurs on iOS13 . works fine on earlier versions

Thanks.

The value variable is an Optional string, that's why it shows the Optional() when you print it.

To unwrap the optional you can do something like this:

if let unwrappedValue = value {
    cell.serviceName.text = unwrappedValue
}

Or if you prefer, you can do it in one line with the nil coalescing operator:

cell.serviceName.text = value ?? "Text in case of nil"

It's because your value is an optional.

Try through this way

if let value = servicesResponse["data"][collectionView.tag]["subcategories"][indexPath.row]["name"] {
    cell.serviceName.text = value.stringValue
}

The error shows a string being initialized with a nil argument so there something not quite right with the json data, or the way it's being decoded.

Why don't you do the unwrapping in stages, rather than a one liner. When you're dealing with an unknown error it is always better to breakdown the process into small chunks and then examine each individually. When you discover where your problem is, you can always go back to the one liner, applying what you've learned.

This is what I came up with (and tested) to illustrate a one way to debug in a gradual JSON decoding process.

Given a raw json string:

let rawString = """
{"statusCode":200,"message":"Success","data":[{"_id":"someid","isActive":true,"subcategories":[{"_id":"id","photo":"image/url/30973327066756228460065.png","services":[{"_id":"id","properties":[{"_id":"id","isMultiSelect":false,"responses":["1","2","3","4","5"],"other_name":"የክፍሎች ቁጥር","name":"Number of rooms"}],"other_name":"ጽዳት","name":"Cleaning"}],"other_name":"ጽዳት","name":"Cleaning","other_subcategory_label":"ጽዳት","subcategory_label":"Cleaning"}],"name":"Home Cleaning","__v":0,"other_name":"የቤት ጽዳት"}]}
"""

We can gradually decode, validate and then unwrap the name value at the end.

let parsedJson = JSON.init(parseJSON: rawString)

let verifiedDataJson = parsedJson["data"]
guard verifiedDataJson != JSON.null else {
    return
}

let verifiedCollectionViewTagJson = verifiedDataJson[0]
guard verifiedCollectionViewTagJson != JSON.null else {
    return
}

let verifiedSubCategoriesJson = verifiedCollectionViewTagJson["subcategories"]
guard verifiedSubCategoriesJson != JSON.null else {
    return
}

let verifiedIndexPathRowJson = verifiedSubCategoriesJson[0]
guard verifiedIndexPathRowJson != JSON.null else {
    return
}

guard let unwrappedNameValue = verifiedIndexPathRowJson["name"].string as String? else {
    return
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM