无法将'NSNull'(0×106a4f520)类型的值转换为'NSDictionary'

时间:2017-11-01 19:15:21

标签: ios swift firebase-realtime-database

这是我在github上的项目: https://github.com/alshfu86/Recipes

我有一个问题。如果我从Firebase数据库中删除了某些内容,则会出现此错误:

  

无法将'NSNull'(0×106a4f520)类型的值转换为'NSDictionary'(0×106a4ef58)。

方法中的

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell", for:indexPath) as! CategoryTableViewCell
    let rowData = self.data[indexPath.row] as! NSDictionary
    let title = rowData["title"] as! String
    cell.recipeLabel.text = title.uppercased()
    let imageUrl = rowData["youtubeID"] as! String
    let imageQuality = rowData["imageQuality"] as! String
    let urlPath = youtubeBaseImageURL + imageUrl + "/" + imageQuality + ".jpg"
    let url = URL(string: urlPath)
    cell.recipeImageView.kf.setImage(with: url)
    print("uString(describing: rl )path = \(String(describing: url))")
    return cell
}

这里是全班:

import UIKit
import Kingfisher

class CategoryViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
    var data = [Any]()
    var categoryTitle = ""

    let youtubeBaseImageURL = "http://img.youtube.com/vi/"

    @IBOutlet weak var tableView: UITableView!

    //is the device landscape or portrait
    var isPortraid = true

    override func viewDidLoad() {
        super.viewDidLoad()

        let backButton = UIBarButtonItem(image: UIImage(named:"chevron"), style: UIBarButtonItemStyle.plain, target: self, action: #selector(back))

        self.navigationItem.leftBarButtonItem = backButton
        self.tableView.delegate = self
        self.title = categoryTitle

        print("data: \(self.data)")

        //  loadAdmobBanner()

        NotificationCenter.default.addObserver(self, selector: #selector(MainViewController.orientationChanged), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

        if UIDevice.current.orientation.isLandscape {
            isPortraid = false
        }
    }

    func orientationChanged(){
        if UIDevice.current.orientation.isLandscape {
            isPortraid = false
        } else {
            isPortraid = true
        }

        tableView.reloadData()
    }

    @objc func back(){
        self.navigationController?.popViewController(animated: true)
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell", for:indexPath) as! CategoryTableViewCell
        let rowData = self.data[indexPath.row] as! NSDictionary
        let title = rowData["title"] as! String
        cell.recipeLabel.text = title.uppercased()
        let imageUrl = rowData["youtubeID"] as! String
        let imageQuality = rowData["imageQuality"] as! String
        let urlPath = youtubeBaseImageURL + imageUrl + "/" + imageQuality + ".jpg"
        let url = URL(string: urlPath)
        cell.recipeImageView.kf.setImage(with: url)
        print("uString(describing: rl )path = \(String(describing: url))")
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let playerViewController = storyboard.instantiateViewController(withIdentifier: "PlayerViewController") as! PlayerViewController
        let rowData = self.data[indexPath.row] as! NSDictionary
        let youtubeUrl = rowData["youtubeID"] as! String
        playerViewController.urlPath = youtubeUrl
        let ingredients = rowData["ingredients"] as! String
        playerViewController.about = ingredients

        self.navigationController?.pushViewController(playerViewController, animated: true)
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if isPortraid {return UIScreen.main.bounds.height/5
        } else {
            return UIScreen.main.bounds.height/5.2
        }
    }

    @IBAction func unwindToCategory(sender: UIStoryboardSegue){
    }

1 个答案:

答案 0 :(得分:0)

错误必须在这一行:

let rowData = self.data[indexPath.row] as! NSDictionary

错误是数组包含一些空值(表示为NSNull)。你应该做一个有条件的演员,即:

if let rowData = self.data[indexPath.row] as? NSDictionary { 
    // do stuff here
}

或者,将data声明为字典数组:

var data = [NSDictionary]() 

然后在将它们分配给data之前过滤掉空值:

self.data = yourdatasource.filter { $0 is NSDictionary }

然后只需检索元素:

let rowData = self.data[indexPath.row]  // do stuff here