使用SwiftJSON展开值会导致iOS13出现错误

问题描述 投票:0回答:3

我有一个提供数据的外部api,我需要对其进行解码并将其分配给视图中的标签。

我在collectionView中使用以下内容,所以不要介意collectionView.tagindexPath.row

我也在使用SwiftyJson解析json值.string提供和可选值

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

现在,当我尝试将此值分配给标签时

cell.serviceName.text = value

我收到一个错误:

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

我在赋值时必须将值放在这样的东西内:

`"\(value)"`

这可以正常工作,但是在值附近有Optional文本。

我也试图:

  • 解开值cell.serviceName.text = value!给出相同的错误
  • 使用过的.stringValue,而不是.string,它给出了非可选的值,给出了相同的错误-使用.rawString而不是.string会出现相同的错误
  • 尝试以这种方式将其展开
if let value = servicesResponse["data"][collectionView.tag] 
   ["subcategories"][indexPath.row]["name"].string {
        cell.serviceName.text = value
}

相同错误

  • 并尝试给它提供默认值cell.serviceName.text = value ?? "default"同样的错误

我只是试图像这样检查所有响应:

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=========================")
                        }
                    }
                }
            }
        }

和所有通行证

原始JSON:

{
  "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": "የቤት ጽዳት"
    },
    {
      "_id": "id",
      "isActive": true,
      "subcategories": [
        {
          "_id": "id",
          "photo": "image/url/30973327066756228460065.png",
          "services": [
            {
              "_id": "id",
              "properties": [
                {
                  "_id": "id",
                  "isMultiSelect": false,
                  "responses": [
                    "Tap",
                    "Sink"
                  ],
                  "name": "Is it the tap or Sink?"
                }
              ],
              "name": "Taps and Sinks"
            }
          ],
          "name": "Taps and Sinks",
          "subcategory_label": "Taps and Sinks"
        },
        {
          "_id": "id",
          "photo": "image/url/30973327066756228460065.png",
          "services": [
            {
              "_id": "id",
              "properties": [
                {
                  "_id": "id",
                  "isMultiSelect": false,
                  "responses": [
                    "Yes",
                    "No"
                  ],
                  "name": "Can you send a photo?"
                }
              ],
              "name": "Drains"
            }
          ],
          "name": "Drains",
          "subcategory_label": "Drains"
        }
      ],
      "name": "Plumbing",
      "__v": 0
    },
    {
      "_id": "id",
      "isActive": true,
      "subcategories": [
        {
          "_id": "id",
          "photo": "image/url/30973327066756228460065.png",
          "services": [
            {
              "_id": "id",
              "properties": [
                {
                  "_id": "id",
                  "isMultiSelect": false,
                  "responses": [
                    "Yes",
                    "No"
                  ],
                  "name": "Do you have power?"
                }
              ],
              "name": "Electrical Faults"
            }
          ],
          "name": "Electrical Faults",
          "subcategory_label": "Electrical Faults"
        },
        {
          "_id": "id",
          "photo": "image/url/30973327066756228460065.png",
          "services": [
            {
              "_id": "id",
              "properties": [
                {
                  "_id": "id",
                  "isMultiSelect": false,
                  "responses": [
                    "Yes",
                    "No"
                  ],
                  "name": "Can you bring the appliance to a repair shop"
                }
              ],
              "name": "Electrical Appliances"
            }
          ],
          "name": "Electrical Appliances",
          "subcategory_label": "Electrical Appliances"
        }
      ],
      "name": "Electrical",
      "__v": 0
    },
    {
      "_id": "id",
      "isActive": true,
      "subcategories": [
        {
          "_id": "id",
          "photo": "image/url/30973327066756228460065.png",
          "services": [

          ],
          "other_name": "Painting",
          "name": "Painting",
          "other_subcategory_label": "Painting",
          "subcategory_label": "Painting"
        }
      ],
      "other_name": "Finishing",
      "name": "Finishing",
      "__v": 0
    }
  ]
}

我想知道是否有一种方法可以删除文本Optional,而该值仍然是可选的,或者是否有人知道此错误的含义以及发生的原因。

仅在iOS13上发生错误。在早期版本上可以正常工作

谢谢。

ios swift string swifty-json
3个回答
1
投票

value变量是一个可选字符串,这就是为什么在打印时显示Optional()的原因。

要打开可选的包装,您可以执行以下操作:

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

或者,如果您愿意,也可以使用nil合并运算符在一行中完成:

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

0
投票

这是因为您的值是可选的。

尝试这种方式

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

0
投票

错误显示使用nil参数初始化字符串,因此json数据或解码方式不太正确。

为什么不分阶段而不是一个班轮地展开。当您处理未知错误时,最好将流程分解成小块,然后逐一检查。当您发现问题出在哪里时,您可以随时应用所学的知识,回到原来的状态。

这是我想出(并经过测试)来说明在JSON逐步解码过程中进行调试的一种方法。

给出原始的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":"የቤት ጽዳት"}]}
"""

我们可以逐渐解码,验证并在最后解开名称值。

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
}
© www.soinside.com 2019 - 2024. All rights reserved.