【问题标题】:Firebase - iOs: How to pass data from Tableview to DetailsView?Firebase - iOs:如何将数据从 Tableview 传递到 DetailsView?
【发布时间】:2017-02-15 05:08:43
【问题描述】:

我有一个控制器“Feed”,它通过 Firebase 的表格(标题和图片)列出多个帖子。

点击按钮后,它会显示“Feed 详细信息”控制器,我希望在该控制器中显示先前单击的帖子(父级)中的数据(标题图像和标题)。 (见截图2)

在点击的那一刻,我只得到静态信息,没有从 Firebase 获取任何信息。但是,它们都在主屏幕中被正确调用。所以问题是当它继续到“DetailsController”时

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

目前这是我的提要控制器:

//
//  Feed.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: "FeedDetailsController") 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)
}
}

还有我的 Feed 详细信息:

//
//  FeedDetails.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 FeedDetailsController: 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!

var post: Post!

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


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

        self.posts = posts.reversed()
    }



}

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 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)
}
}

【问题讨论】:

  • 也许这个答案会帮助你指导如何使用prepare(for:sender:)stackoverflow.com/a/39930180/5327882
  • 我可以推荐你this视频。在描述中有链接,您可以在其中下载项目并查看如何传递数据。这是最简单的方法,但实际上我建议您代表。但这是更简单的方法

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

您需要在表格视图中实现prepare(for:sender:)UITableViewDelegate 方法)并将需要显示的数据添加到那里的详细视图控制器中。

【讨论】:

  • 嗨 Mundi,谢谢,我开始从事 ios 开发,你有任何例子,指导谁能帮助我吗?非常感谢
【解决方案2】:

好的,我尝试使用您的代码,但缺少的元素太多以至于它返回错误,所以我不知道这是否会编译但应该可以。

第一:

我假设两个类中的 private var posts = [Post]() 拥有相同的帖子值

第二:

您需要将UITableViewDelegate 添加到您的超类中

class FeedVC: UIViewController, UITableViewDataSource, UITableViewDelegate, ...

第三:

在您的FeedVC 中添加以下内容:

private var selectedIndexPath: Int = 0

这个在你的FeedDetailsController

var selectedIndexPath: Int = 0 // cannot be private to get accessed from FeedVC

FeedVC 中的这个 Delegate 函数:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        selectedIndexPath = indexPath.row
    }

以及在 FeedVC 中为 segue 做准备:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let newViewController = segue.destination as! FeedDetailsController

        newViewController.selectedIndexPath = selectedIndexPath
    }

最后,您现在可以在posts 中使用selectedIndexPath 来获取所选帖子

let post = posts[selectedIndexPath]

希望这会有所帮助!

【讨论】:

  • 嗨 Mentos,感谢您的所有时间,我正在尝试以下操作: override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "Action" { let FeedDetailsController = segue.destination 为! FeedDetailsController // 这些是您在类 FeedDetailsController.post = posts } 中预定义的变量,但我在 FeedDetailsController.post = posts 中出现错误说不能将值类型 [Post] 分配给类型“Post!”
  • 我也试过 FeedDetailsController.titleInputView = InputTextView!相反,我得到了相同类型的错误。 ..知道为什么吗?会很棒的,非常感谢!!
  • @tibewww,试试FeedDetailsController.post.insert(<newElement>, at: <Int>)
  • Hmmmmm 我有 ' 我在文件 feed.swift 的最后一个 } 之前添加了这段代码可以吗?
  • @tibewww 您需要将 更改为要添加到 post 变量中的元素,这需要在您为 segue 做准备中
猜你喜欢
  • 2013-09-12
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多