Swift:从Firebase检索数据并在表格视图中显示

时间:2018-06-27 09:15:24

标签: swift xcode firebase firebase-realtime-database

我正在制作一个具有新闻图片供稿(HomeViewController)的应用程序。用户可以点击与 SiteViewController 相连的每个图像,该图像具有一个空数据的表格视图,以及一个按钮,单击该按钮可以查询到 ContextSheetViewController ,用户可以在其中上传数据他们在新闻Feed中单击的图像。然后,用户按下上载按钮,该数据( siteCodeTextView ,areaCodeTextView,trenchTextView)将保存到Firebase中,然后退回到SiteViewController。然后,我想检索刚在SiteViewController的表格视图中上载图像的 siteCodeTextView 的数据值。但是,当我在ContextSheetViewController中按上载时,发生错误:在展开可选值时意外发现nil 。我的 sheetId 在SiteViewController中显示nil,所以我不确定如何正确检索它?有什么帮助吗?

这是我有关视图控制器的故事板:

enter image description here

SiteViewController的代码:

class SiteViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!


    var sheets = [Sheet]()
    var users = [User]()
    var sheetId: String!

    var postId: String!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        loadSheets()

        print(postId)
        print(sheetId)
    }
    func loadSheets() {
        Api.Sheet.REF_SHEETS.child(self.postId!).observe(.childAdded, with: {
            snapshot in
            Api.Sheet.observeSheets(withSheetId: snapshot.key, completion: {
                sheet in
//                self.fetchUser(uid: sheet.uid!, completed: {
                    print("sheet id: \(sheet.id)")
                    print("sheet uid: \(sheet.uid)")
                self.sheets.append(sheet)
                self.tableView.reloadData()
//                })
            })
        })
    }

    func fetchUser(uid: String, completed:  @escaping () -> Void ) {

        Api.User.observeUser(withId: uid, completion: {
            user in
            self.users.append(user)
            completed()
        })
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SheetSegue" {
            let sheetVC = segue.destination as! SheetViewController
            let sheetId = sender as! String
            sheetVC.sheetId = sheetId

        }
    }
}

extension SiteViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sheets.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SheetCell", for: indexPath) as! SiteTableViewCell
        let sheet = sheets[indexPath.row]

        print("sheet id: \(sheet.id)")
        print("sheet uid: \(sheet.uid)")
//        let user = users[indexPath.row]
//        cell.user = user
        cell.sheet = sheet
        cell.delegate = self
        return cell
    }
}

extension SiteViewController: SiteTableViewCellDelegate {
    func goToSheetVC(sheetId: String) {
        performSegue(withIdentifier: "SheetSegue", sender: sheetId)

    }
}

ContextSheetViewController的代码:

class ContextSheetViewController: UIViewController {


    @IBOutlet weak var siteCodeTextView: UITextField!
    @IBOutlet weak var areaCodeTextView: UITextField!
    @IBOutlet weak var trenchTextView: UITextField!
    @IBOutlet weak var uploadArtefactImage: UIImageView!

    @IBOutlet weak var artefactImageView: UIImageView!

    var selectedImage: UIImage?
    var postId: String!
    override func viewDidLoad() {
        super.viewDidLoad()
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleSelectPhoto))
        uploadArtefactImage.addGestureRecognizer(tapGesture)
        uploadArtefactImage.isUserInteractionEnabled = true

    }

    @objc func handleSelectPhoto() {
        let pickerController = UIImagePickerController()
        pickerController.delegate = self
        present(pickerController, animated: true, completion: nil)
    }

    @IBAction func uploadButton_TouchUpInside(_sender: Any) {

        if let profileImg = self.artefactImageView.image, let imageData = UIImageJPEGRepresentation(profileImg, 0.1) {
            let photoIdString = NSUUID().uuidString
            print(photoIdString)
            let storageRef = Storage.storage().reference(forURL: Config.STORAGE_ROOF_REF).child("sheets").child(photoIdString)
            storageRef.putData(imageData, metadata: nil, completion: { (metadata, error) in
                if error != nil {
                    ProgressHUD.showError(error!.localizedDescription)
                    return
                }
                let photoUrl = metadata?.downloadURL()?.absoluteString
                self.sendDataToDatabase(photoUrl: photoUrl!)
            })
        } else {
            ProgressHUD.showError("Sheet Image can not be empty!")
        }
    }

    func sendDataToDatabase(photoUrl: String) {
//        let ref = Database.database().reference()
        let sheetsReference = Api.Sheet.REF_SHEETS
//        let sheetsReference = ref.child("sheets")
        let newSheetId = sheetsReference.childByAutoId().key
        let newSheetReference = sheetsReference.child(newSheetId)
        guard let currentUser = Auth.auth().currentUser else {
            return
        }
        let currentUserId = currentUser.uid
        newSheetReference.setValue(["uid": currentUserId, "photoUrl": photoUrl, "siteCodeTextView": siteCodeTextView.text!, "areaCodeTextView": areaCodeTextView.text!, "trenchTextView": trenchTextView.text!], withCompletionBlock: {
            (error, ref) in
            if error != nil {
                ProgressHUD.showError(error!.localizedDescription)
                return
        }
            let postSheetRef = Api.Sheet.REF_SHEETS.child(self.postId!).child(newSheetId)
//            let postSheetRef = Api.Sheet.REF_SHEETS.child("post-sheets").child(self.postId).child(newSheetId)
            postSheetRef.setValue(true, withCompletionBlock: { (error, ref) in
                if error != nil {
                    ProgressHUD.showError(error!.localizedDescription)
                    return
                }
            })


            ProgressHUD.showSuccess("Success")
            self.clean()
            self.navigationController?.popViewController(animated: true)
        })
    }

    func clean() {
        self.siteCodeTextView.text = ""
        self.uploadArtefactImage.image = UIImage(named: "upload")
        self.artefactImageView.image = UIImage(named: "image")
    }
}

extension ContextSheetViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        print("did Finish Picking Media")
        if let image = info["UIImagePickerControllerOriginalImage"] as? UIImage{
            artefactImageView.image = image
//            selectedImage = image
//            uploadArtefactImage.image = image
        }
        dismiss(animated: true, completion: nil)
    }
}

SiteTableViewCell的代码:

protocol SiteTableViewCellDelegate {
    func goToSheetVC(sheetId: String)

}

class SiteTableViewCell: UITableViewCell {


    @IBOutlet weak var profileImageView: UIImageView!
    @IBOutlet weak var siteSheetLabel: UILabel!
    @IBOutlet weak var nameLabel: UILabel!

    var delegate: SiteTableViewCellDelegate?

    var sheet: Sheet? {
        didSet {
            updateView()
        }
    }

    var user: User? {
        didSet {
            setupUserInfo()
        }
    }

    func updateView() {
        siteSheetLabel.text = sheet?.siteCodeTextView

    }


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    func setupUserInfo() {
        nameLabel.text = user?.username
        if let photoUrlString = user?.profileImageUrl {
            let photoUrl = URL(string: photoUrlString)
            profileImageView.sd_setImage(with: photoUrl, placeholderImage: UIImage(named: "placeholderImg"))
        }
    }


    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.siteSheetLabel_TouchUpInside))
        siteSheetLabel.addGestureRecognizer(tapGesture)
        siteSheetLabel.isUserInteractionEnabled = true
    }

    @objc func siteSheetLabel_TouchUpInside() {

        print(sheet?.id)

        if let id = sheet?.id{
            delegate?.goToSheetVC(sheetId: id)
        }
    }
    override func prepareForReuse() {
        super.prepareForReuse()
        profileImageView.image = UIImage(named: "placeholderImg")
    }

}

enter image description here

1 个答案:

答案 0 :(得分:1)

根据显示的罪魁祸首是postId,您正在使用它来从Firebase中获取数据,但尚未显示其价值所在。当用户点击图像时,postId不会传输到SiteViewController

SiteViewController中,删除!并将其替换为?,放入一个初始化器,该初始化器将postID作为参数。

var postId:String?

func initPost(forImage postId: String) {
    self.postId=postId
}

seguedidSelectForRow内部的上一个新闻提要VC中(我不知道您用于过渡的内容,请初始化SiteViewController,因此在显示它时它知道哪个为其检索数据的ID。

需要提及的另一件事是您正在使用observe,但没有删除观察者。

编辑:此答案基于我,但我不知道您的HomeVC是什么样。

     if segue.identifier == "SiteSegue" {
        let siteVC = segue.destination as! SiteViewController
        let postId = sender as! String
        siteVC.postId = postId

    }