展开一个Optional值时意外发现nil,得到这样的错误

时间:2019-02-28 05:18:37

标签: ios swift4

我的要求:我将在表视图中显示聊天详细信息列表。在表视图顶部,将使用文本字段进行搜索。基于用户的唯一ID,应完成搜索。不是用户输入的具有唯一ID的聊天,那么它必须重定向到另一个称为chatcreatepage的屏幕。每当我们搜索聊天时,我们都会使用一个名为FIND API的API,并且在该FIND API中有一个聊天字典,如果为null,则将调用create chat。如果该聊天字典不为nil,则需要显示聊天列表视图中的聊天详细信息。当加载聊天列表页面时,我们将调用聊天列表Api。当我们通过在文本字段中输入唯一ID进行搜索时,我们将获取输入的唯一ID和我们拥有的唯一ID详细信息在表格视图中显示。

这是任务,我已经完成,直到表中显示聊天列表。FINDAPI集成也已完成。当我用搜索结果重新加载数据(找到api响应)时,出现致命错误,例如“意外在“ var recepient = dict [“ recipient”] as![String:Any]“行中解开可选值时发现nil。如果有人帮助我解决问题,那就太好了。谢谢您。我在下面提供了代码。

    import UIKit
        import Alamofire
        import SwiftyJSON
        import SDWebImage
        class ChatlistViewController: UIViewController{
             var pro = [[String:Any]]()
             var dict:[String:Any]!
             var idd = ""
             var id = ""
            var chatt:Dictionary = [String:Any]()
            var searchActive : Bool = false
            var filtered:[String] = []
            var data:[String] = []

            @IBOutlet weak var searchtext: UITextField!
            @IBOutlet weak var chatlisttable: UITableView!
            override func viewDidLoad() {
                super.viewDidLoad()

                       apicall()

            }



            func apicall(){

                let acce:String = UserDefaults.standard.string(forKey: "access-tokenn")!
                        print(acce)

                        let headers:HTTPHeaders = ["Authorization":"Bearer \(acce)","Content-Type":"application/X-Access-Token"]

                Alamofire.request(Constants.Chatlist, method: .get, encoding: URLEncoding.default, headers: headers).responseJSON {  response in
                    switch response.result {
                    case .success:
                        print(response)
                        if response.result.value != nil{
                            var maindictionary = NSDictionary()
                            maindictionary = response.result.value as! NSDictionary
                            print(maindictionary)

                            var userdata = NSDictionary()
                            userdata = maindictionary.value(forKey: "data") as! NSDictionary

                            var productsdetails = [[String:Any]]()
                            productsdetails = userdata.value(forKey: "chat") as! [[String:Any]]
                            self.pro = productsdetails
                                 print(self.pro)
                                   self.chatlisttable.reloadData()

                        }else{
                            let Alertcontroller = UIAlertController(title: "Alert", message: "No data found ", preferredStyle: .alert)
                            let CancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
                            Alertcontroller.addAction(CancelAction)
                            self.present(Alertcontroller, animated: true, completion: nil)
                        }
                                break
                            case .failure(let error):

                                print(error)
                            }
                        }


            }

            func searchapicall(){
                idd = searchtext.text!
               let acce:String = UserDefaults.standard.string(forKey: "access-tokenn")!
                print(acce)

                let headers:HTTPHeaders = ["Authorization":"Bearer \(acce)","Content-Type":"application/X-Access-Token"]
                print((Constants.Chatlistsearch)+(idd))
                Alamofire.request((Constants.Chatlistsearch+idd), method: .get, encoding: URLEncoding.default, headers: headers).responseJSON {  response in
                    switch response.result {
                    case .success:
                        //print(response)
                        if response.result.value != nil{
                            var maindictionary = NSDictionary()
                            maindictionary = response.result.value as! NSDictionary

                            var chat:Dictionary = maindictionary.value(forKey: "data") as! [String:Any]

                            var chattt:Dictionary = chat["chat"] as! [String:Any]

                            if (chattt != nil) {

                               // print("Find Action")

                                self.chatt = chat["user"] as! [String:Any]
                                print(self.chatt)
                                self.pro = [self.chatt]
                               // print(self.pro)
                             self.chatlisttable.reloadData()

                            }else{
                                let viewc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ChatViewController") as? ChatViewController
                                self.navigationController?.pushViewController(viewc!, animated: true)
                            }

                        }else{
                            let Alertcontroller = UIAlertController(title: "Alert", message: "No data found on this unique id", preferredStyle: .alert)
                            let CancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
                            Alertcontroller.addAction(CancelAction)
                            self.present(Alertcontroller, animated: true, completion: nil)
                        }
                        break
                    case .failure(let error):

                        print(error)
                    }
                }

            }




        }


        extension ChatlistViewController: UITextFieldDelegate{

            func textFieldShouldReturn(_ textField: UITextField) -> Bool {

                self.searchapicall()

                return true
            }

        }

        extension ChatlistViewController: UITableViewDataSource,UITableViewDelegate {

            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                if (searchActive == false){
                return self.pro.count
                }else{
                    return 1
                }
            }

            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

                var cell = chatlisttable.dequeueReusableCell(withIdentifier: "ChatlistTableViewCell", for: indexPath) as! ChatlistTableViewCell

                if (searchActive == false){

                dict = pro[indexPath.row]
                var recepient = dict["recipient"] as! [String:Any]
                print(recepient)

                var name = recepient["name"] as! String
                print(name)
                id = recepient["unique_id"] as! String
                print(id)
                var image = recepient["avatar"] as! String
                print(image)
                cell.namelbl.text = name
                cell.idlbl.text = id
                cell.imageView!.sd_setImage(with: URL(string:image), placeholderImage: UIImage(named: "Mahi.png"))

                }else{

                    cell.namelbl.text = chatt["name"] as! String
                    cell.idlbl.text = chatt["unique_id"] as! String
                }

                return cell
               self.chatlisttable.reloadData()

            }

        }

    //Response format

    {
        "success": 1,
        "status": 200,
        "data": {
            "user": {
                "id": 3,
                "unique_id": "10002",
                "name": "nani",
                "avatar": "https://www.planetzoom.co.in/storage/user/avatar/AkgcUFF3QIejMhZuLF4OXnSFHjxNAOo4FuXV3Mgi.jpeg"
            },
            "chat": null
        }
    }


//Response with chat dictionary data

{
    "success": 1,
    "status": 200,
    "data": {
        "user": {
            "id": 8,
            "unique_id": "10007",
            "name": "Mahitha",
            "avatar": "https://www.planetzoom.co.in/storage/user/avatar/cZt9yQlBzIEewOdQ1lYZhl3dFiOv2k3bxG7HLOzR.jpeg"
        },
        "chat": {
            "id": 4,
            "status": 0,
            "created_at": "2019-02-27 12:26:24",
            "updated_at": "2019-02-27 12:26:24"
        }
    }
}

3 个答案:

答案 0 :(得分:1)

由于我在回复中看到chat为零,因此您应该更新代码以获取聊天详细信息

if var productsdetails = userdata.value(forKey: "chat") as? [[String:Any]] {
    // Code to display chat
} else {
    // Code to display nil error
}

我希望这能解决您的问题。

答案 1 :(得分:1)

根据您的回复聊天为空。因此,productsdetails = userdata.value(forKey: "chat") as! [[String:Any]]就是这样,您已经在键'chat'的userdefaults中设置了一个空值,并且正在以[[String : Any]]

的形式获取空值。

所以您必须使用代码块

进行检查
if let productsdetails = userdata.value(forKey: "chat") as? [[String:Any]] {
    // write code that for chat
} else {
    // write code for chat is null 
}

这称为Optional Chaining,您可能会发现此link

  

可选链接是一个查询和调用可选当前可能为零的属性,方法和下标的过程。如果可选包含值,则属性,方法或下标调用成功;否则,调用成功。如果可选值为nil,则属性,方法或下标调用将返回nil。可以将多个查询链接在一起,如果链中的任何链接为nil,整个链都会正常失败。

或者您可以使用guard语句

解决
guard let productsdetails = userdata.value(forKey: "chat") as? [[String:Any]] else {
    // write code for chat is null 
    return 
}

\\ write code that for chat
\\ you can use productsdetails variable here

答案 2 :(得分:0)

我想向您提供两个反馈:

  1. 请尝试养成避免forced castingforced unwrap成为可能的习惯。

  2. 使用驼峰式命名约定

因此,您可以更改

var recepient = dict["recipient"] as! [String:Any]

 guard let recepient = dict["recipient"] as? [String:Any] else {return cell}

以类似的方式可以在加载tableView之前具有条件

if let productsDetails = userdata.value(forKey: "chat") as? [[String:Any]] {
    // write code 
} else {
    // write code to handle else
}