ios Firebase - 在 "details post" Controller 中继续数据

标签 ios swift database firebase

这是我的情况:

我有一个“Feed” Controller ,它通过 Firebase 中的表格(标题和图像)列出多个帖子。

enter image description here

按一下按钮,它就会进入“提要详细信息” Controller ,我希望在其中显示先前单击的帖子(父级)中的数据(标题图像和标题)。 (见截图2)

enter image description here

目前,当我到达提要详细信息 Controller 时,没有任何内容被获取......

如何从之前点击的项目中获取详细信息?

目前这是我的提要 Controller :

 //
//  FeedVC.swift
//  MobileAppDemo
//
//  Created by Mikko Hilpinen on 31.10.2016.
//  Copyright © 2016 Mikkomario. All rights reserved.
//

import UIKit
import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage
import SwiftKeychainWrapper
import SwiftyJSON

class FeedVC: UIViewController, UITableViewDataSource,      UIImagePickerControllerDelegate, UINavigationControllerDelegate
{
@IBOutlet weak var addImageView: UIImageView!
@IBOutlet weak var feedTableView: UITableView!
@IBOutlet weak var titleInputView: InputTextView!

@IBOutlet weak var captionInputView: InputTextView!


private var posts = [Post]()
private var imagePicker = UIImagePickerController()
private var imageSelected = false

private var readPosts: ObserveTask?

override func viewDidLoad()
{
    super.viewDidLoad()

    imagePicker.delegate = self
    imagePicker.allowsEditing = true

    feedTableView.dataSource = self

    feedTableView.rowHeight = UITableViewAutomaticDimension
    feedTableView.estimatedRowHeight = 320

    readPosts = Post.observeList(from: Post.parentReference.queryOrdered(byChild: Post.PROPERTY_CREATED))
    {
        posts in

        self.posts = posts.reversed()
        self.feedTableView.reloadData()
    }
}

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

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    if let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as? MessageCell
    {
        let post = posts[indexPath.row]
        cell.configureCell(tableView: tableView, post: post)
        return cell
    }
    else
    {
        fatalError()
    }
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage
    {
        addImageView.image = image
        imageSelected = true
    }
    picker.dismiss(animated: true, completion: nil)
}

@IBAction func selectImagePressed(_ sender: AnyObject)
{
    present(imagePicker, animated: true, completion: nil)
}

@IBAction func postButtonPressed(_ sender: AnyObject)
{
    guard let caption = captionInputView.text, !caption.isEmpty else
    {
        // TODO: Inform the user
        print("POST: Caption must be entered")
        return
    }

    guard let title = titleInputView.text, !title.isEmpty else
    {
        // TODO: Inform the user
        print("POST: title must be entered")
        return
    }

    guard let image = addImageView.image, imageSelected else
    {
        print("POST: Image must be selected")
        return
    }

    guard let currentUserId = User.currentUserId else
    {
        print("POST: Can't post before logging in")
        return
    }

    imageSelected = false
    addImageView.image = UIImage(named: "add-image")
    captionInputView.text = nil
    titleInputView.text = nil

    // Uploads the image
    if let imageData = UIImageJPEGRepresentation(image, 0.2)
    {
        let imageUid = NSUUID().uuidString
        let metadata = FIRStorageMetadata()
        metadata.contentType = "image/jpeg"

        Storage.REF_POST_IMAGES.child(imageUid).put(imageData, metadata: metadata)
        {
            (metadata, error) in

            if let error = error
            {
                print("STORAGE: Failed to upload image to storage \(error)")
            }

            if let downloadURL = metadata?.downloadURL()?.absoluteString
            {
                // Caches the image for faster display
                Storage.imageCache.setObject(image, forKey: downloadURL as NSString)

                print("STORAGE: Successfully uploaded image to storage")
                _ = Post.post(caption: caption, title: title, imageUrl: downloadURL, creatorId: currentUserId)
            }
        }
    }
}

@IBAction func signOutButtonPressed(_ sender: AnyObject)
{
    // Doesn't listen to posts anymore
    readPosts?.stop()

    try! FIRAuth.auth()?.signOut()
    User.currentUserId = nil
    dismiss(animated: true, completion: nil)
}
}

我正在使用 feeddetails 的代码 - 这当然不支持数据

我的数据库结构如下所示:

enter image description here

如何获取详细信息 View 中的数据?如果有人能向我解释这个过程,那就太棒了!

感谢您的所有时间和帮助!!

-----编辑:--------

感谢 Retterdesdialogs,我已经更新了代码并启动了应用程序,但是当我单击按钮 linkbutton 时什么也没有发生并且应用程序崩溃了:

控制台显示: 无法将“UIViewController”类型的值 (0x1087f6758) 转换为“MobileAppDemo.FeedDetailsController”(0x104bc34a0)。

我现在有代码:

feedVC.swift(列出了所有帖子):

 //
 //  FeedVC.swift
 //  MobileAppDemo
 //
//  Created by Mikko Hilpinen on 31.10.2016.
//  Copyright © 2016 Mikkomario. All rights reserved.
//

 import UIKit
 import FirebaseAuth
 import FirebaseDatabase
 import FirebaseStorage
 import SwiftKeychainWrapper
 import SwiftyJSON

  class FeedVC: UIViewController, UITableViewDataSource,     UIImagePickerControllerDelegate, UINavigationControllerDelegate
{
 @IBOutlet weak var addImageView: UIImageView!
@IBOutlet weak var feedTableView: UITableView!
@IBOutlet weak var titleInputView: InputTextView!
@IBOutlet weak var linkbutton: UIButton!

@IBOutlet weak var captionInputView: InputTextView!


private var posts = [Post]()
private var imagePicker = UIImagePickerController()
private var imageSelected = false

private var readPosts: ObserveTask?

override func viewDidLoad()
{
    super.viewDidLoad()

    imagePicker.delegate = self
    imagePicker.allowsEditing = true

    feedTableView.dataSource = self

    feedTableView.rowHeight = UITableViewAutomaticDimension
    feedTableView.estimatedRowHeight = 320

    readPosts = Post.observeList(from: Post.parentReference.queryOrdered(byChild: Post.PROPERTY_CREATED))
    {
        posts in

        self.posts = posts.reversed()
        self.feedTableView.reloadData()
    }



}

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

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

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


// here you need to add
{


    if let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as? MessageCell
    {

        let post = posts[indexPath.row]
        cell.configureCell(tableView: tableView, post: post)
        cell.linkbutton.tag = indexPath.row
        cell.linkbutton.addTarget(self, action: #selector(FeedVC.toFeedDetailAction(_:)), for: .touchUpInside)
        return cell

    }
    else
    {
        fatalError()
    }
}

func toFeedDetailAction(_ sender: UIButton) {

    let FeedDetailsController = self.storyboard?.instantiateViewController(withIdentifier: "FeedDetailsIdentifier") as! FeedDetailsController
    FeedDetailsController.post = posts[sender.tag]
    self.navigationController?.pushViewController(FeedDetailsController, animated: true)
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage
    {
        addImageView.image = image
        imageSelected = true
    }
    picker.dismiss(animated: true, completion: nil)
}

@IBAction func selectImagePressed(_ sender: AnyObject)
{
    present(imagePicker, animated: true, completion: nil)
}

@IBAction func postButtonPressed(_ sender: AnyObject)
{
    guard let caption = captionInputView.text, !caption.isEmpty else
    {
        // TODO: Inform the user
        print("POST: Caption must be entered")
        return
    }

    guard let title = titleInputView.text, !title.isEmpty else
    {
        // TODO: Inform the user
        print("POST: title must be entered")
        return
    }

    guard let image = addImageView.image, imageSelected else
    {
        print("POST: Image must be selected")
        return
    }

    guard let currentUserId = User.currentUserId else
    {
        print("POST: Can't post before logging in")
        return
    }

    imageSelected = false
    addImageView.image = UIImage(named: "add-image")
    captionInputView.text = nil
    titleInputView.text = nil

    // Uploads the image
    if let imageData = UIImageJPEGRepresentation(image, 0.2)
    {
        let imageUid = NSUUID().uuidString
        let metadata = FIRStorageMetadata()
        metadata.contentType = "image/jpeg"

        Storage.REF_POST_IMAGES.child(imageUid).put(imageData, metadata: metadata)
        {
            (metadata, error) in

            if let error = error
            {
                print("STORAGE: Failed to upload image to storage \(error)")
            }

            if let downloadURL = metadata?.downloadURL()?.absoluteString
            {
                // Caches the image for faster display
                Storage.imageCache.setObject(image, forKey: downloadURL as NSString)

                print("STORAGE: Successfully uploaded image to storage")
                _ = Post.post(caption: caption, title: title, imageUrl: downloadURL, creatorId: currentUserId)
            }
        }
    }
}

@IBAction func signOutButtonPressed(_ sender: AnyObject)
{
    // Doesn't listen to posts anymore
    readPosts?.stop()

    try! FIRAuth.auth()?.signOut()
    User.currentUserId = nil
    dismiss(animated: true, completion: nil)
}
 }

和 FeedDetails.swift (单击按钮后会列出详细信息,按钮具有来自 viewVC Controller 的类:linkbutton:

  //
 //  FeedDetailsController.swift
 //  MobileAppDemo
 //
 //  Created by Mikko Hilpinen on 27.10.2016.
 //  Copyright © 2016 Mikkomario. All rights reserved.
 //

 import UIKit
 import FBSDKCoreKit
 import FBSDKLoginKit
 import Firebase
 import FirebaseAuth
 import SwiftKeychainWrapper



 fileprivate struct RegisterInfo
 {
 let email: String
 let password: String
 }


 class FeedDetailsController: UIViewController
 {
 @IBOutlet weak var emailField: UITextField!
 @IBOutlet weak var passwordField: UITextField!

var post: Post!


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

override func viewDidAppear(_ animated: Bool)
{
    if User.currentUserId != nil
    {
        print("AUTH: USING EXISTING KEYCHAIN")
        User.startTrackingCurrentUser()
        performSegue(withIdentifier: "ToFeed", sender: nil)
    }
    else
    {
        print("AUTH: NO EXSTING KEYCHAIN")
    }
}

override func didReceiveMemoryWarning()
{
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
    print("AUTH: Preparing for segue \(segue.identifier)")

    if let registrationVC = segue.destination as? RegisterVC
    {
        print("AUTH: Found registration VC")

        if let info = sender as? RegisterInfo
        {
            print("AUTH: Sending email (\(info.email)) and password (\(info.password.characters.count) chars) information: ")
            registrationVC.setBaseInfo(email: info.email, password: info.password)
        }
    }
}

@IBAction func signInButtonPressed(_ sender: UIButton)
{
    if let email = emailField.text, let password = passwordField.text
    {
        FIRAuth.auth()?.signIn(withEmail: email, password: password)
        {
            (user, error) in

            if let error = error
            {
                // TODO: Handle other errors here as well
                switch FIRAuthErrorCode(rawValue: error._code)!
                {
                case .errorCodeUserNotFound:
                    print("AUTH: USER NOT FOUND -> CREATING NEW USER")
                    print("AUTH: Sending email \(email) and password \(password.characters.count) characters")
                    self.performSegue(withIdentifier: "RegisterUser", sender: RegisterInfo(email: email, password: password))
                default: print("AUTH: ERROR IN EMAIL LOGIN \(error)") // TODO: Inform user
                }
            }
            else
            {
                print("AUTH: EMAIL AUTH SUCCESSFUL")
                User.currentUserId = user?.uid
                User.startTrackingCurrentUser()
                self.performSegue(withIdentifier: "ToFeed", sender: nil)
            }
        }
    }
    // TODO: Inform user that the field contents are missing
}

@IBAction func facebookButtonPressed(_ sender: UIButton)
{
    // (Already logged in to FB)
    if let fbAccessToken = FBSDKAccessToken.current()
    {
        print("AUTH: Already logged in to FB")
        firebaseAuth(with: FIRFacebookAuthProvider.credential(withAccessToken: fbAccessToken.tokenString))
    }
    else
    {
        let facebookLogin = FBSDKLoginManager()
        facebookLogin.logIn(withReadPermissions: ["public_profile", "email"], from: self)
        {
            (result, error) in

            if let error = error
            {
                print("AUTH: UNABLE TO AUTHENTICATE WITH FACEBOOK")
                print("AUTH: \(error)")
            }
            else if let result = result
            {
                if result.isCancelled
                {
                    print("AUTH: USER CANCELLED FACEBOOK AUTH")
                }
                else
                {
                    print("AUTH: FACEBOOK AUTH SUCCESS")
                    let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
                    self.firebaseAuth(with: credential)
                }
            }
        }
    }
}

fileprivate func firebaseAuth(with credential: FIRAuthCredential)
{
    if FIRAuth.auth() == nil
    {
        print("AUTH: NO AUTH SERVICE AVAILABLE")
    }

    FIRAuth.auth()?.signIn(with: credential)
    {
        (user, error) in

        if let error = error
        {
            print("AUTH: UNABLE TO AUTHENTICATE TO FIREBASE")
            print("AUTH: \(error)")
        }
        else
        {
            if let user = user
            {
                print("AUTH: SUCCESSFULLY AUTHENTICATED WITH FIREBASE")

                // Updates current user data
                var userName = "User"
                var image: UIImage?

                if let retrievedName = user.displayName
                {
                    userName = retrievedName
                }
                if let retrievedImageUrl = user.photoURL
                {
                    if let data = try? Data(contentsOf: retrievedImageUrl)
                    {
                        image = UIImage(data: data)
                    }
                }

                User.post(uid: user.uid, provider: user.providerID, userName: userName, image: image)
                {
                    user in

                    User.currentUser = user
                    User.startTrackingCurrentUser()

                    self.performSegue(withIdentifier: "ToFeed", sender: nil)
                }
            }
        }
    }
}
 }

最佳答案

1) 您需要能够通过 IBOutlet 或以编程方式访问该按钮

2)将按钮设置为单元格indexPath.row并向其添加操作

let post = posts[indexPath.row]
cell.configureCell(tableView: tableView, post: post)
// here you need to add
cell.yourButton.tag = indexPath.row
cell.yourButton.addTarget(self, action: #selector(FeedViewController.toFeedDetailAction(_:)), for: .touchUpInside)
return cell

3) 当您按下按钮时,您可以识别您的提要,因为您有按钮标签,因此您可以从帖子数组中知道提要

func toFeedDetailAction(_ sender: UIButton) {

    let feedDetailsViewController = self.storyboard?.instantiateViewController(withIdentifier: "FeedDetailsIdentifier") as! FeedDetailsViewController
    feedDetailsViewController.post = posts[sender.tag]
    self.navigationController?.pushViewController(feedDetailsViewController, animated: true)  
}

4) 在您的 FeedDetailsViewController 添加

var post: Post!

5) 在 FeedDetailsViewController 中对帖子执行您想要的操作

希望这有帮助:)

关于ios Firebase - 在 "details post" Controller 中继续数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42025159/

相关文章:

iOS 应用程序 - 非公共(public) API 使用 - 应用程序引用非公共(public)选择器 : cancelButtonClicked, setResult:

ios - 将我的 uipickerview 当前选择的内容打印到控制台?

swift - SKSpriteNode 导致场景变灰

Swift - UITextField 搜索以同时向 UITableView 添加行

swift - 列出 Vapor 中的所有路由

mysql - 如何选择在什么属性上创建什么外键?

mysql - MySQLWorkbench 是否包含 MySQL 服务器?

ios - 如何将UIButton的名称保存在字符串中?

php - 哪个更快? 100万行数组还是数据库?

ios - 上传的图片以其他方式旋转