简体   繁体   English

在 iOS13 上使用 SwiftJSON 解包一个值会导致错误

[英]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.我有一个提供数据的外部 api,我需要在我的视图中解码并分配给一个标签。

I am using the following in a collectionView so don't mind the collectionView.tag and indexPath.row我在 collectionView 中使用以下内容,所以不要介意collectionView.tagindexPath.row

I am also using SwiftyJson to parse json values .string providing and optional value我也使用SwiftyJson来解析 json 值.string提供和可选值

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.这工作正常,但它在值周围有Optional文本。

I also tried to:我也尝试过:

  • unwrap the value cell.serviceName.text = 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使用.stringValue而不是.string给出了非可选值给出了相同的错误 -used .rawString而不是.string给出了相同的错误
  • 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" cell.serviceName.text = value ?? "default" same error cell.serviceName.text = value ?? "default"相同的错误

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.我想知道是否有办法删除文本Optional而该值仍然是可选的,或者是否有人知道此错误的含义及其发生的原因。

The error only occurs on iOS13 .该错误仅发生在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. value变量是一个 Optional 字符串,这就是它在打印时显示Optional()的原因。

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:或者,如果您愿意,可以使用 nil 合并运算符在一行中完成:

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.该错误显示一个字符串被初始化为 nil 参数,因此 json 数据或解码方式不太正确。

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.这就是我想出(并测试)来说明在渐进式 JSON 解码过程中进行调试的一种方法的方法。

Given a raw json string:给定一个原始的 json 字符串:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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