如何在Swift中从数组的第一项中获取Dictionary项的值?

时间:2019-03-28 06:35:30

标签: swift xcode

我在下面定义了 Dictionary in an Array 对象:

var dataList : [[String:Any]]?

然后我已经在其中加载了一些数据。这是我在下面运行此代码时的输出:

print("DATA LIST:\n \(myRecordList)")

输出:

Optional([["itemCode": 0, "itemText": please select city], ["itemCode": 1, "itemText": City A], ["itemCode": 2, "itemText": City B], ["itemCode": 3, "itemText": City C], ["itemCode": 4, "itemText": City D], ["itemCode": 5, "itemText": City E], ["itemCode": 6, "itemText": City F]])

我想从数组的第一项开始获得字典的值:

如您所知,这是数组中的第一项:

[“ itemCode”:0,“ itemText”:请选择城市]

这是上面字典中的值:

“ itemText”:请选择城市

此后,如果dataList计数不为零,我想将上面的文本(“ 请选择城市”)设置为按钮标题:

if dataList?.count != 0
{
    **//need help in here!!!**
    {
        self.btnSelectMarkaOutlet.setTitle(tempBtnTitle, for: .normal)
    }
}

我尝试了以下范围。但它粉碎了:

    if let newTry = dataList![0]["itemText"] as? [String]
{
    print("here is the output:: \(newTry[0])")
}

这是错误:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

let tempBtnTitle =必须为“请选择城市” 我想这样做。

让我共享整个视图控制器文件。因为dataList为nil。

import UIKit

class SinyalSeviyesineGoreAramaYapViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var btnSelectMarkaOutlet: UIButton!
    @IBOutlet weak var pickerViewOutlet: UIPickerView!

    var dataList : [[String:Any]]?

    override func viewDidLoad() {
        print("viewDidLoad")
        super.viewDidLoad()

        self.pickerViewOutlet.delegate = self
        self.pickerViewOutlet.dataSource = self

        self.loadSayacRecordsForTheUIPickerView()

        print("Is the data list nil? : \(self.dataList)")
        if let newTry = self.dataList![0]["itemText"] as? String
        {
            print("here is the output:: \(newTry)")
        }

        //I WANTED TO SET BUTTON TITLE !!
        let tempButtonTitle = ""
        self.btnSelectMarkaOutlet.setTitle(tempButtonTitle, for: .normal)
    }


    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let recordName = self.dataList![row]
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        //return self.cityList![row]

        let info = self.dataList![row]

        if let name = info["itemCode"] as? String,
            let code = info["itemText"] as? String
        {
            let text = "\(name) - \(code)"
            //print("am i here? \(text)")
            return text
        }

        return nil
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.dataList == nil ? 0 : self.dataList!.count
    }

    func loadSayacRecordsForTheUIPickerView()
    {
        print("loadSayacRecordsForTheUIPickerView method is called")

        ServiceManager.oServiceManager.loadSayacRecords()
            {
                (result) in

                if let sayacRecords = try? JSONSerialization.jsonObject(with: result!, options: .mutableContainers) as? [String:Any]
                {
                    if let resultCodeFromWebApi = sayacRecords?["resultCode"] as? String
                    {
                        DispatchQueue.main.async
                            {
                                print("loadSayacRecordsForTheUIPickerView resultCode: \(resultCodeFromWebApi)")

                                if resultCodeFromWebApi == "999"
                                {
                                    if let myRecordList = sayacRecords?["recordList"] as? [[String:Any]]
                                    {
                                        //DispatchQueue.main.async
                                        //{
                                        self.dataList = myRecordList
                                        print("DATA LIST:\n \(self.dataList)")
                                        self.pickerViewOutlet.reloadAllComponents()
                                        //}
                                    }
                                } // resultCodeFromWebApi == 999 ENDS
                                else
                                {
                                    if let resultMessageFromWebApi = sayacRecords?["resultMessage"] as? String
                                    {
                                        print("resultMessage: \(resultMessageFromWebApi)")
                                    }
                                }
                        } // DispatchQueue.main.async ENDS
                    }
                    else
                    {
                        print("cant parse it")
                    } // if let resultCodeFromWebApi = loginResult?["resultCode"] as? Int ENDS
                }
        }
    } // loadSayacRecordsForTheUIPickerView ENDS

} // class SinyalSeviyesineGoreAramaYapViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource ENDS

2 个答案:

答案 0 :(得分:1)

问题出在实现的逻辑上:dataList是异步加载的,这意味着您不知道何时可以使用它,但是您却像永远可用那样使用它。

此错误的示例在viewDidLoad中:

self.loadSayacRecordsForTheUIPickerView()

print("Is the data list nil? : \(self.dataList)")
if let newTry = self.dataList![0]["itemText"] as? String
{
    print("here is the output:: \(newTry)")
}

在第一行中,您开始加载dataList,但是在for循环中,您正在强制展开,这意味着您在说“嗨,我100%肯定它将可用” -这是不正确的。

您可能遇到的问题的解决方案是将dataList!转换为dataList?,因此,如果未加载它,则什么也不会发生,并且您的应用程序不会崩溃。

一个更好,更快的解决方案是为dataList设置一个默认值,因此,如果未加载默认值,您将只对一个空数据模型做出反应:

var dataList : [[String:Any]] = [[String:Any]]()

答案 1 :(得分:0)

一个原因可能是array为nil,并且您也正在使用[String]展开它是String,这可能会给出nil。 请尝试以下操作以避免崩溃。

if dataList?.isEmpty == false,let firstDic = dataList?.first, let neededString = firstDic["itemText"] as? String   {
}