调用函数Swift后,变量被删除

时间:2017-10-08 06:34:59

标签: swift firebase firebase-realtime-database

我正在制作一个使用firebase的实时聊天应用。

在您进行身份验证的应用程序中,当您单击要在所需聊天窗口中的频道时,您将进入视频控制器,即频道列表。我的代码如下所示:

对于频道视图控制器:

import UIKit
import FirebaseAuth
import FirebaseDatabase

enum Section:Int {
   case createNewChannelSection = 0
   case currentChannelSection
}

class channelsTableViewController: UITableViewController {

    // MARK: - Properties
    var senderDisplayName: String? // 1
    var newChannelTextField: UITextField? // 2
    private var channels: [Channel] = []

    // MARK: - UITableViewDataSource
    // 1
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }

    // 2
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let currentSection: Section = Section(rawValue: section) {
            switch currentSection {
            case .createNewChannelSection:
                return 1
            case .currentChannelSection:
                return channels.count
            }
        } else {
            return 0
        }
    }

    // 3
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let reuseIdentifier = (indexPath as NSIndexPath).section == Section.createNewChannelSection.rawValue ? "NewChannel" : "ExistingChannel"
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)

        if (indexPath as NSIndexPath).section ==  Section.createNewChannelSection.rawValue {
            if let createNewChannelCell = cell as? CreateChannelCell {
                newChannelTextField = createNewChannelCell.newChannelNameField
            }
        } else if (indexPath as NSIndexPath).section == Section.currentChannelSection.rawValue {
            cell.textLabel?.text = channels[(indexPath as NSIndexPath).row].name
        }

        return cell
    }

    // MARK: - UITableViewDelegate
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.section == Section.currentChannelSection.rawValue {
            let channel = channels[(indexPath as NSIndexPath).row]
            print("perform segue")
            self.performSegue(withIdentifier: "ShowChannel", sender: channel)
        }
    }

    // MARK: - Firebase related methods
    private lazy var channelRef: DatabaseReference = Database.database().reference().child("channels")
    private var channelRefHandle: DatabaseHandle?
    func observeChannels() {
        channelRef.observe(.childAdded, with: { (snapshot) in // 1
            let channelData = snapshot.value as? [String: AnyObject] // 2
            let id = snapshot.key
            if let name = channelData?["name"] as! String!, name.characters.count > 0 { // 3
                self.channels.append(Channel(id: id, name: name))
                self.tableView.reloadData()
            } else {
                print("Error! Could not decode channel data")
            }
        })
    }

    // MARK: - View Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Channels"
        observeChannels()
    }

    // MARK: - Actions
    @IBAction func createChannel(_ sender: AnyObject) {
        if let name = newChannelTextField?.text {
            let newChannelRef = channelRef.childByAutoId()
            let channelItem = [
                "name" : name
            ]
            newChannelRef.setValue(channelItem)
        }
    }

    // MARK: - Navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        if let channel = sender as? Channel {
            let chatVC = segue.destination as! ChatViewController

            chatVC.channel = channel
            print("\(channel)")
            chatVC.channelRef = channelRef.child(channel.id)
            print("id: \(channel.id)")
            print("\(chatVC.channelRef)")
        }
    }
} 

对于我的聊天视图控制器:

import UIKit
import FirebaseDatabase

class ChatViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {

    // MARK: - Properties
    var channelRef: DatabaseReference?
    var channel: Channel? {
        didSet {
            title = channel?.name
        }
    }
    var messages = [Message]()
    @IBOutlet var TableView: UITableView!
    @IBOutlet var messageBox: UITextField!

    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        TableView.delegate = self
        TableView.dataSource = self
        self.messageBox.delegate = self
        print("chat key: \(String(describing: channelRef?.key))")
        observeMessages()
    }

    // MARK: - Hide text field

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.view.endEditing(true)
        return false
    }

    // MARK: - Source Data
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
        if messages.count > 0 {
            let message = messages[indexPath.row]
            cell.textLabel?.text = message.message
        }
        return cell
    }

    // MARK: - Firebase related methods
    private lazy var messageRef: DatabaseReference = self.channelRef!.child("messages")
    private var newMessageHandle: DatabaseHandle?
    func observeMessages() {
        print("observe called")
        messageRef = channelRef!.child("messages")// Error: force unwrapping nil value
        let messageQuery = messageRef.queryLimited(toLast:25)

       newMessageHandle = messageQuery.observe(.childAdded, with: { (snapshot) -> Void in
            // 3
            let messageData = snapshot.value as? [String:AnyObject]

            let text = Message()
            text.setValuesForKeys(messageData!)
            self.messages.insert(text, at: 0)

            DispatchQueue.main.async {
                self.TableView.reloadData()
            }
        })
    }

    // MARK: - Actions
    @IBAction func Post(_ sender: AnyObject) {
        let msg: [String: AnyObject] = ["message": messageBox.text as AnyObject]
        let dbRef = messageRef.childByAutoId()
        dbRef.setValue(msg)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

这是我的控制台输出:

perform segue
LearnFirebase.Channel // print("\(channel)")
id: -KvnLy92pj5czfGeA44p // print("id: \(channel.id)")
Optional(https://learnfirebase-2a4a6.firebaseio.com/channels/-KvnLy92pj5czfGeA44p) // print("\(chatVC.channelRef)")
chat key: nil // print("chat key: \(String(describing: channelRef?.key))") on the ChatViewController
observe called
fatal error: unexpectedly found nil while unwrapping an Optional value
2017-10-10 10:18:09.146968+0300 fatal error: unexpectedly found nil while unwrapping an Optional value

当然,会有一次崩溃,因为我强行打开一个零物体,但为什么它没有?我该如何解决这个问题?

感谢您的回答。

0 个答案:

没有答案