JSON 解析有时会崩溃 Swift

JSON Parsing sometimes crashes Swift

我正在我的 iOS 应用程序中解析 JSON,有时当网络连接较弱但没有消失时,应用程序会在尝试解析 JSON 时崩溃,因为它说在强制展开 nil 时出错。

我使用的代码在这里。

//
//  MessageModel.swift
//  truthordare
//
//  Created by Dustin Palmatier on 11/2/19.
//  Copyright © 2019 Hexham Network. All rights reserved.
//

import UIKit

protocol MessageModelProtocol: class {
    func itemsDownloaded(items: NSArray)
}

class MessageModel: NSObject, URLSessionDataDelegate {
    //properties

    weak var delegate: MessageModelProtocol!

    let urlPath = "Redacted" //this will be changed to the path where service.php lives

    let deleteUrl = "REDACTED"

    func downloadItems(TYPE: String, IDENTIFIER: String) {
        let url: URL = URL(string: urlPath)!

        var request = URLRequest(url: url)

        request.httpMethod = "POST"
        let postString = "type=\(TYPE)&identifier=\(IDENTIFIER)";
        request.httpBody = postString.data(using: String.Encoding.utf8);

        let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)

        let task = defaultSession.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

            if error != nil {
                print("Failed to download data")
            }else {
                print("Data downloaded")
                self.parseJSON(data!)
            }

        }

        task.resume()
    }

    func deleteItems(TYPE: String, SKU: String) {
        let myUrl = URL(string: "https://truthordare.hexhamnetwork.com/api/92fFDd93D/erase.php");

        var request = URLRequest(url:myUrl!)

        request.httpMethod = "POST"// Compose a query string

        let postString = "type=\(TYPE)&sku=\(SKU)";

        request.httpBody = postString.data(using: String.Encoding.utf8);

        let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

            if error != nil
            {
                print("error=\(error ?? "Empty" as! Error)")
                return
            }
        }
        task.resume()
    }

    func parseJSON(_ data:Data) {

        var jsonResult = NSArray()

        do{
            jsonResult = try JSONSerialization.jsonObject(with: data, options: [.allowFragments, .mutableContainers]) as! NSArray

        } catch let error as NSError {
            print(error)

        }

        var jsonElement = NSDictionary()
        let tables = NSMutableArray()

        for i in 0 ..< jsonResult.count
        {

            jsonElement = jsonResult[i] as! NSDictionary

            let table = TableModel()

            //the following insures none of the JsonElement values are nil through optional binding
            if let sku = jsonElement["SKU"] as? String,
                let message = jsonElement["MESSAGE"] as? String
            {

                table.sku = sku
                table.message = message

            }

            tables.add(table)

        }

        DispatchQueue.main.async(execute: { () -> Void in

            self.delegate.itemsDownloaded(items: tables)

        })
    }
}

一旦达到

它就会崩溃
self.delegate.itemsDownloaded(items: tables)

它说它在强制展开时收到了一个 nil

为了初始化委托,我在调用它的 类 中调用了它。

messageModel.delegate = self

为避免崩溃可靠地将 delegate 声明为常规可选

weak var delegate: MessageModelProtocol?

并称之为

self.delegate?.itemsDownloaded(items: tables)

在 Swift 4+ 中,强烈建议使用 Codable 协议,在任何 Swift 版本中,强烈建议使用完成处理程序而不是协议/委托。


并且根本不要在 Swift 中使用 NS... 集合类型。使用本机类型。如果预期类型是集合类型,则 .mutableContainers / .allowFragments 在 Swift 中毫无意义。省略参数。