将变量从 customCell.xib 的按钮传递到另一个 UIViewController

Posted

技术标签:

【中文标题】将变量从 customCell.xib 的按钮传递到另一个 UIViewController【英文标题】:Passing a variable from a customCell.xib's button to another UIViewController 【发布时间】:2018-02-10 21:23:54 【问题描述】:

我的自定义单元格有一个按钮,单击该按钮时,用户可以转到另一个 ViewControler。该按钮有一个带有用户 ID 字符串的 titleLabel。我想要做的是将用户带到一个新的 UIViewController,将单击按钮的 titleLabel(用户 ID)传递给新 View Controller 上的变量。这样,我可以使用该变量(用户 ID)从 firebase 获取更多信息并将其显示在 UI 视图控制器上。

在自定义单元格的 .xib 上,我打印 UID 以确保每个按钮都打印对应的 ID,它确实如此。我想不出办法将该 ID 传递给新的 ViewController。

我尝试在网上进行研究,发现您无法在 customCell.xib 上做 prepare(for segue) 或 performegue(WithIdentifier)。

我尝试过做委托,然后做协议,但仍然无法让它发挥作用。我是 Swift 的新手。任何帮助都会很棒,谢谢!

这是 customCell.Xib 的 Swift 文件:

class CustomCellTableViewCell: UITableViewCell 

@IBOutlet weak var postImage: UIImageView!
@IBOutlet weak var nameLbl: UILabel!
@IBOutlet weak var descriptionLbl: UITextView!
@IBOutlet weak var profileImageBtn: UIButton!
@IBOutlet weak var profileImage: UIImageView!

@IBOutlet weak var view: UIView!

var btnSelected : Bool = false
var vcInstance: ProfilesTableVC?

override func awakeFromNib() 
    super.awakeFromNib()
    // Initialization code
    view.clipsToBounds = true
    view.layer.cornerRadius = view.frame.size.width / 2
    profileImage.layer.cornerRadius = profileImage.frame.size.width / 2
    descriptionLbl.alpha = 0.7


override func setSelected(_ selected: Bool, animated: Bool) 
    super.setSelected(selected, animated: animated)






@IBAction func profileBtnPressed(_ sender: Any) 
    let passValue = UserProfileVC()
    let profileTvC = ProfilesTableVC()
    print (profileImageBtn.titleLabel!.text!)
    var id = (profileImageBtn.titleLabel!.text!)

    profileTvC.didSelectProfileBtn(senderID: id)


这是 tableViewController,我加载了所有内容(不是我想要传递值的地方)。我尝试在此处传递值,然后执行 prepareForSegue 将值传递给新的 UIViewController 但在 segue 发生后该值变为 nil。我只是包含 .xib 从表视图调用函数的代码。

class ProfilesTableVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate,UINavigationControllerDelegate,  UIImagePickerControllerDelegate

let cell = CustomCellTableViewCell()
func didSelectProfileBtn(senderID: String) 

    senderIDArray.append(senderID)
    var index = senderIDArray.count - 1
    selectedCellUserID = senderIDArray[index]
    performSegue(withIdentifier: "showSendersProfile", sender: Any?.self)



这是 UIViewController,我想在其中传递变量并使用该 ID 从 Firebase 显示更多信息

import UIKit
import Firebase

class UserProfileVC: UIViewController  

    let customCell = CustomCellTableViewCell()
    let profileTvC = ProfilesTableVC()

    @IBOutlet weak var profileImage: UIImageView!
    @IBOutlet weak var nameLbl: UILabel!

    var delegate : Any?

    var getName = String()
    var getsenderID = String()

    let userDataRef = Database.database().reference().child("Users")

    override func viewDidLoad() 
        super.viewDidLoad()
        print("ID is: \(profileTvC.selectedCellUserID)")
        let sender = getsenderID
        print(sender)
    

【问题讨论】:

【参考方案1】:

如果您不想使用协议,可以在 tableView - cellForRowAt 方法中向按钮添加目标,也可以在该方法中将标记设置为行索引值。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let profileCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! MoviewReviewCell
    reviewCell.profileImageBtn.tag = indexPath.row
    reviewCell.profileImageBtn.addTarget(self, action: #selector(tappedOnXibCellButton), for: .touchUpInside)
    return reviewCell


@objc func tappedOnXibCellButton(sender: UIButton) 
    print(sender.tag)
    performSegue(withIdentifier: reviewListToDetails, sender: sender.tag)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    let identifier = segue.identifier
    if identifier == "segueName" 
        let destViewController = segue.destination as! DestinationClassViewController
        let selectedIndex = sender as! Int
        let profileId = profilesList[selectedIndex].id
        destViewController.profileId = profileId
    

【讨论】:

谢谢!起初它给了我一个错误,它不能转换类型为“UINavigationController”的值。我查找了错误并对以下代码进行了必要的更改: override func prepare(for segue: UIStoryboardSegue, sender: Any?) let identifier = segue.identifier if identifier == "showSendersProfile" let nav = segue.destination as! UINavigationController 让 destViewController : UserProfileVC = nav.topViewController 为! UserProfileVC 让 selectedIndex = sender as! int let profileId = profileArray[selectedIndex].userID destViewController.getsenderID = profileId 我认为这可能会造成“重用”问题,tableView.dequeueReusableCell(withIdentifier:) 将重用单元格,这意味着您第一次创建它(当您调用 dequeReusableCell 时),然后您 addTarget ,第二行可能有reused,然后你添加其他目标。这使得第二行的按钮有两个目标将依次执行,这意味着 TWO 发生在不同的发送者身上。在添加新的之前考虑使用.removeTarget(target:action:for:)【参考方案2】:

您似乎创建了一个NEW ProfilesTableVC,并尝试继续执行segue。新创建的不在您的视图堆栈中,也不在您的情节提要中。

您可以在返回 cellForRowAt 时添加它(当然是在 ProfilesTableVC

 cell.vcInstance = self

然后在按钮中点击

@IBAction func profileBtnPressed(_ sender: Any) 
    print (profileImageBtn.titleLabel!.text!)
    var id = (profileImageBtn.titleLabel!.text!)

    vcInstance?.didSelectProfileBtn(senderID: id)




您可以使用协议/委托来做到这一点。我认为您尝试了,但您的试用有问题。

定义一个回调委托:

protocol CustomCellDelegate: AnyObject 
    func customCell(didSelectButton name: String)

您会注意到扩展 AnyObject。这是为了允许weak引用,尝试阅读Swift ARC

然后,在你的牢房里:

weak var delegate: CustomCellDelegate?

然后在profileBtnPressed(_ sender: Any)

@IBAction func profileBtnPressed(_ sender: Any) 
    var id = (profileImageBtn.titleLabel!.text!)

    delegate?.customCell(didSelectButton: id)

当单元格出队时:

(cell as? CustomCellTableViewCell)?.delegate = self

【讨论】:

以上是关于将变量从 customCell.xib 的按钮传递到另一个 UIViewController的主要内容,如果未能解决你的问题,请参考以下文章

如何将 SwipeCellKit 的自定义滑动功能用于从 .xib 文件创建的自定义单元格?

自定义 UICollectionViewCell 的 UILabel 为 nil

将变量从 MainWindow 传递到新窗口

将php数据/变量传递给模态

将变量从访问表单传递到访问表单

如何将变量从 Activity 传递到 Fragment,并将其传回?