ios - 如何将数据作为参数发送到 UIButton 选择器方法
问题描述
因此,我正在构建一个类似于 Tinder 的应用程序,其中有一个卡片“甲板”(在此代码中称为 cardsDeckView),其中充满了 UIView(在此代码中称为 cardView)。这些“卡片”中的每一个都显示用户信息,例如个人资料图像(您可以循环浏览)、姓名、年龄和职业。他们还有一个按钮,按下该按钮后,将转到显示有关该用户的更多信息的用户信息屏幕。这是我遇到麻烦的地方。我想当用户加载到甲板上时,我可以将每个用户的 id 传递给每个相应的“卡片”,并在按下时通过按钮目标传递这些数据,但我在 Stack Overflow 上没有找到任何关于将参数传递给按钮选择器的信息迅速。这是我的代码,它实质上为现有用户加载了一些过滤器,
import UIKit
import SDWebImage
import SLCarouselView
import JGProgressHUD
class DeckVC: UIViewController {
let headerView = UIView()
let cardsDeckView = SLCarouselView(coder: NSCoder.empty())
let menuView = BottomNavigationStackView()
var users: [User] = []
var userId: String?
let hud = JGProgressHUD(style: .extraLight)
override func viewDidLoad() {
super.viewDidLoad()
hud.textLabel.text = "Loading nearby users..."
hud.layer.zPosition = 50
hud.show(in: view)
headerView.heightAnchor.constraint(equalToConstant: 70).isActive = true
menuView.heightAnchor.constraint(equalToConstant: 70).isActive = true
let stackView = UIStackView(arrangedSubviews: [headerView, cardsDeckView!, menuView])
stackView.axis = .vertical
view.addSubview(stackView)
stackView.frame = .init(x: 0, y: 0, width: 300, height: 200)
stackView.fillSuperview()
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = .init(top: 0, left: 12, bottom: 0, right: 12)
stackView.bringSubviewToFront(cardsDeckView!)
menuView.settingsButton.addTarget(self, action: #selector(handleSettings), for: .touchUpInside)
menuView.messagesButton.addTarget(self, action: #selector(handleMessages), for: .touchUpInside)
setupUI()
}
func setupUI() {
observeUsers { (user) in
API.User.observeCurrentUser(completion: { (currentUser) in
if (user.id != API.User.CURRENT_USER?.uid) && (currentUser.preferedGender == user.gender) && (currentUser.minAge!...currentUser.maxAge! ~= user.age!) {
self.users.append(user)
DispatchQueue.main.async {
self.setupCards()
}
} else if (user.id != API.User.CURRENT_USER?.uid) && (currentUser.preferedGender == "Both") && (currentUser.minAge!...currentUser.maxAge! ~= user.age!) {
self.users.append(user)
DispatchQueue.main.async {
self.setupCards()
}
}
})
}
}
func observeUsers(completion: @escaping (User) -> Void) {
API.User.REF_USERS.observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String : Any] {
let user = User.transformUser(dict: dict, key: snapshot.key)
completion(user)
}
}
}
@objc func handleSettings() {
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromLeft
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let profileVC = storyboard.instantiateViewController(withIdentifier: "ProfileVC")
self.present(profileVC, animated: true, completion: nil)
}
@objc func handleMessages() {
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let messagesVC = storyboard.instantiateViewController(withIdentifier: "MessagesVC")
self.present(messagesVC, animated: true, completion: nil)
}
@objc func moreInfoTapped() {
let userDetailsController = UserDetailsVC()
userDetailsController.userId = userId
present(userDetailsController, animated: true, completion: nil)
}
@objc func messageUserTapped() {
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let messagesVC = storyboard.instantiateViewController(withIdentifier: "MessagesVC")
let m = MessagesVC()
m.userId = userId
self.present(messagesVC, animated: true, completion: nil)
// go to specific user chat after this transition
}
func setupCards() {
for user in users {
let gradientView = GlympsGradientView()
let barsStackView = UIStackView()
let moreInfoButton = UIButton(type: .system)
moreInfoButton.setImage(#imageLiteral(resourceName: "info_icon").withRenderingMode(.alwaysOriginal), for: .normal)
moreInfoButton.isUserInteractionEnabled = true
moreInfoButton.addTarget(self, action: #selector(moreInfoTapped), for: .touchUpInside)
let messageUserButton = UIButton(type: .system)
messageUserButton.setImage(#imageLiteral(resourceName: "message-icon2").withRenderingMode(.alwaysOriginal), for: .normal)
messageUserButton.isUserInteractionEnabled = true
messageUserButton.addTarget(self, action: #selector(messageUserTapped), for: .touchUpInside)
gradientView.layer.opacity = 0.5
let cardView = CardView(frame: .zero)
cardView.userId = user.id
userId = user.id
cardView.images = user.profileImages
if let photoUrlString = user.profileImages {
let photoUrl = URL(string: photoUrlString[0])
cardView.imageView.sd_setImage(with: photoUrl)
}
(0..<user.profileImages!.count).forEach { (_) in
let barView = UIView()
barView.backgroundColor = UIColor(white: 0, alpha: 0.1)
barView.layer.cornerRadius = barView.frame.size.height / 2
barsStackView.addArrangedSubview(barView)
barsStackView.arrangedSubviews.first?.backgroundColor = .white
}
let nametraits = [UIFontDescriptor.TraitKey.weight: UIFont.Weight.semibold]
var nameFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptor.AttributeName.family: "Avenir Next"])
nameFontDescriptor = nameFontDescriptor.addingAttributes([UIFontDescriptor.AttributeName.traits: nametraits])
let agetraits = [UIFontDescriptor.TraitKey.weight: UIFont.Weight.light]
var ageFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptor.AttributeName.family: "Avenir Next"])
ageFontDescriptor = ageFontDescriptor.addingAttributes([UIFontDescriptor.AttributeName.traits: agetraits])
let jobtraits = [UIFontDescriptor.TraitKey.weight: UIFont.Weight.light]
var jobFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptor.AttributeName.family: "Avenir Next"])
jobFontDescriptor = jobFontDescriptor.addingAttributes([UIFontDescriptor.AttributeName.traits: jobtraits])
let attributedText = NSMutableAttributedString(string: user.name!, attributes: [.font: UIFont(descriptor: nameFontDescriptor, size: 30)])
attributedText.append(NSAttributedString(string: " \(user.age!)", attributes: [.font: UIFont(descriptor: ageFontDescriptor, size: 24)]))
if user.profession != "" && user.company != "" {
attributedText.append(NSAttributedString(string: "\n\(user.profession!) @ \(user.company!)", attributes: [.font: UIFont(descriptor: jobFontDescriptor, size: 20)]))
}
cardView.informationLabel.attributedText = attributedText
// cardsDeckView.addSubview(cardView)
cardView.addSubview(gradientView)
cardView.addSubview(barsStackView)
cardView.addSubview(moreInfoButton)
cardView.addSubview(messageUserButton)
cardView.moreInfoButton = moreInfoButton
cardView.messageUserButton = messageUserButton
cardView.stackView = barsStackView
moreInfoButton.anchor(top: nil, leading: nil, bottom: cardView.bottomAnchor, trailing: cardView.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 20, right: 20), size: .init(width: 50, height: 50))
messageUserButton.anchor(top: cardView.topAnchor, leading: nil, bottom: nil, trailing: cardView.trailingAnchor, padding: .init(top: 25, left: 0, bottom: 0, right: 25), size: .init(width: 44, height: 44))
barsStackView.anchor(top: cardView.topAnchor, leading: cardView.leadingAnchor, bottom: nil, trailing: cardView.trailingAnchor, padding: .init(top: 8, left: 8, bottom: 0, right: 8), size: .init(width: 0, height: 4))
barsStackView.spacing = 4
barsStackView.distribution = .fillEqually
cardView.fillSuperview()
gradientView.fillSuperview()
hud.textLabel.text = "All done! \u{1F389}"
hud.dismiss(afterDelay: 0.0)
self.cardsDeckView?.appendContent(view: cardView)
}
}
}
extension NSCoder {
class func empty() -> NSCoder {
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.finishEncoding()
return NSKeyedUnarchiver(forReadingWith: data as Data)
}
}
extension Array {
public mutating func appendDistinct<S>(contentsOf newElements: S, where condition:@escaping (Element, Element) -> Bool) where S : Sequence, Element == S.Element {
newElements.forEach { (item) in
if !(self.contains(where: { (selfItem) -> Bool in
return !condition(selfItem, item)
})) {
self.append(item)
}
}
}
}
请参阅 setupUsers(),并查看如何使用按钮创建 cardView。按下 moreInfo 按钮后,如何从 cardViews 获取这些 userId 并将它们传递给 UserDetails ViewController?我可以将目标/选择器添加到 cardView 中的这些按钮吗?任何建议都会有所帮助!谢谢!
解决方案
您不会将参数发送到按钮选择器。方法有一个固定的方法签名IBAction
。
这IBAction
是目标(通常是视图控制器)的方法。目标应保存您决定做什么所需的额外状态数据。
您发布了很多代码而没有太多解释,而我没有时间浏览该代码并弄清楚。
我收集到您在一个视图控制器上有一个按钮操作,需要链接到另一个视图控制器。第一个视图控制器应该知道它需要发送到另一个视图控制器的用户 ID。第一个视图控制器应该具有实例变量,使其能够访问该信息。您的IBAction
方法可以访问实现这些IBAction
s 的对象的实例变量。
推荐阅读
- excel - 如何复制和粘贴单元格,然后使用 excel VBA 以特定方式删除某些行?
- html - 如何使用 CSS 中另一个文件夹中的其他文件?
- c# - Open XML SDK 在我的 Excel 电子表格中读取连续整数而不是实际值
- r - 时间或内存使用情况能否说明循环中增长对象的危险?
- c# - Unity 中移动平台的奇怪输出
- javascript - Vue 使用来自 Vue() 的模板和脚本定义组件
- html - 使用变量的 ADA 可访问性错误空标题
- rest - 在 REST 中使用“createModel”是一个好习惯吗?
- c# - 编译期间显示的用户控制错误消息
- google-cloud-platform - Biqquery:某些行属于不同的分区而不是目标分区