ios - 为什么我的代码不起作用? - setObject ForKey : key cannot be nil

标签 ios database swift uitableview firebase

开发一个应用程序,我将数据存储在 Firebase 上并将数据加载到我的 TableView 中。不得不从我发现的教程中稍微更改(旧)代码,所以我希望有人能发现我犯的错误。用户可以添加带有以下内容的事件:名称、日期、描述(所有字符串)和图像。此数据加载到 TableView 中的三个“标签”和顶部的图像上。

import UIKit
import Firebase
import FirebaseDatabaseUI

class EventViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    //outlets for text & image
    @IBOutlet weak var photoImageView: UIImageView!

    @IBOutlet weak var eventName: UITextField!
    @IBOutlet weak var eventDate: UITextField!
    @IBOutlet weak var eventDes: UITextView!

    //Database connection
    let rootref = FIRDatabase().reference()
    var imagePicker: UIImagePickerController = UIImagePickerController()



    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func submitEvent(sender: AnyObject) {

        let name = eventName.text
        let date = eventDate.text
        let text = eventDes.text
        var data: NSData = NSData()

        if let image = photoImageView.image {
            data = UIImageJPEGRepresentation(image,0.1)!
        }

        let base64String = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)

        let user: NSDictionary = ["name":name!, "date":date!, "text":text!, "photoBase64":base64String]

        //Add firebase child node
        let event = FIRDatabase().reference().child(name!)

        // Write data to Firebase
        event.setValue(user)

        navigationController?.popViewControllerAnimated(true)
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        view.endEditing(true)
        super.touchesBegan(touches, withEvent: event)
    }

    //UIImagePickerControllerDelegate methods

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        imagePicker.dismissViewControllerAnimated(true, completion: nil)
        photoImageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
    }

    func imagePickerControllerDidCancel(picker: UIImagePickerController) {
        dismissViewControllerAnimated(true, completion: nil)
    }

    @IBAction func addPicture(sender: AnyObject) {
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) {
            imagePicker =  UIImagePickerController()
            imagePicker.delegate = self
            imagePicker.sourceType = .Camera

            presentViewController(imagePicker, animated: true, completion: nil)
        } else {
            imagePicker.allowsEditing = false
            imagePicker.sourceType = .PhotoLibrary
            imagePicker.delegate = self
            presentViewController(imagePicker, animated: true, completion:nil)
        }
    }
}

我的 TABLEVIEWCONTROLLER

import UIKit
import Firebase

class EventTableViewController: UITableViewController {

    @IBOutlet weak var eventImage: UIImageView!
    @IBOutlet weak var eventName: UILabel!
    @IBOutlet weak var eventDate: UILabel!
    @IBOutlet weak var eventText: UITextView!

    let rootref = FIRDatabase().reference()
    var items = [NSDictionary]()


    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        items = [NSDictionary]()

        FIRDatabase.load()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    //TableView Data
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

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

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

        configureCell(cell, indexPath: indexPath)

        return cell
    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {

            let dict = items[indexPath.row]
            let name = dict["name"] as! String

            // delete data from firebase

            let event = FIRDatabase().reference().child(name)
            event.removeValue()
        }
    }

    // MARK:- Configure Cell

    func configureCell(cell: UITableViewCell, indexPath: NSIndexPath) {
        let dict = items[indexPath.row]

        eventName.text = dict["name"] as? String
        eventDate.text = dict["name"] as? String
        eventText.text = dict["name"] as? String

        let base64String = dict["photoBase64"] as! String
        populateImage(cell, imageString: base64String)
    }

    func populateImage(cell:UITableViewCell, imageString: String) {

        let decodedData = NSData(base64EncodedString: imageString, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)

        let decodedImage = UIImage(data: decodedData!)

        cell.imageView!.image = decodedImage
    }

    //load data from Firebase
    func loadDataFromFirebase() {

        UIApplication.sharedApplication().networkActivityIndicatorVisible = true


            rootref.observeEventType(.Value, withBlock: { snapshot in
                var tempItems = [NSDictionary]()


            for item in snapshot.children {
                let child = item as! FIRDataSnapshot
                let dict = child.value as! NSDictionary
                tempItems.append(dict)
            }

            self.items = tempItems
            self.tableView.reloadData()
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        })
    }
}

通过图像了解我的工作

My app so far

最佳答案

看这一行:

let user: NSDictionary = ["name":name!, "date":date!, "text":text!, "photoBase64":base64String]

你在这里做了很多强制解包。事实上,你在几个地方做了很多强制解包。当您这样做时,您是在说“我 100% 确定这里总会有一个值”。避免这几乎所有的费用。该行应如下所示。

if let unwrappedName = name , unwrappedDate = date, unwrappedText = text{
    let user: NSDictionary = ["name":unwrappedName, "date":unwrappedDate, "text":unwrappedText, "photoBase64":base64String]
}

像这样展开可选值可以防止您的应用程序崩溃。您应该在此处放置一个断点以查看什么值为 nil。每次使用 !你应该非常仔细地考虑一下。

关于ios - 为什么我的代码不起作用? - setObject ForKey : key cannot be nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38063268/

相关文章:

swift - TableView header 内的编程 UIView

ios - 应用程序 :didReceiveLocalNotification never called on ios 8

ios - NSSortDescriptor 不按字母顺序排序

ios - 通过网络代理工具下载或查看作为多部分请求(PNG、PDF)发送的文件?

ios - SpriteKit GameScene 旋转错误

ios - 如何在 Swift 中创建安全的 Array 子集?

ios - 在 moreNavigationController navigationBar ios 5 中更改图像背景

php - 多种数据类型 - 一张表与多个表

oracle - 是否可以使用 liquibase 更新数据库中的现有行?

python - SQLite 还是纯文本文件?