Reputation: 835
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:
cell.serviceName.text = value!
gives the same error.stringValue
instead of .string
which gives the non-optional value gives the same error
-used .rawString
instead of .string
gives the same errorif let value = servicesResponse["data"][collectionView.tag]
["subcategories"][indexPath.row]["name"].string {
cell.serviceName.text = value
}
same error
cell.serviceName.text = value ?? "default"
same errori 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.
Upvotes: 0
Views: 241
Reputation: 2543
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
}
Upvotes: 0
Reputation: 448
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
}
Upvotes: 0
Reputation: 11
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"
Upvotes: 1