我创建了一个自定义按钮,以在按钮中包含我需要的信息:
class CustomButton: UIButton {
var urlString: String?
var documentType: String?
var requestEntity: String?
var requestSortBy: [NSSortDescriptor]?
var requestPredicate: NSPredicate?
}
当我在collectionView中创建单元格时(嵌入在tableView中),我将信息包含在名为documentTypeButton
的自定义按钮中。也是执行功能HomeTableViewController.documentTypeButtonTapped(_:)
以执行segue的目标。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let languageSelected = UserDefaults().value(forKey: "language") as! String
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)
return cell
}
在HomeTableViewController
中,我具有在触摸按钮内部时要执行的功能:
@objc func documentTypeButtonTapped(_ sender: CustomButton) {
performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
print(sender.documentType)
print(sender.requestEntity)
}
func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {
let languageSelected = UserDefaults().value(forKey: "language") as! String
if let destination = segue.destination as? DocumentListTableViewController {
destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
destination.requestedEntity = sender.requestEntity
destination.requestedSortBy = sender.requestSortBy
destination.requestedPredicate = sender.requestPredicate
}
}
上面的打印语句可以很好地工作并打印信息。然后segue转到DocumentListTableViewController
。
在viewDidLoad
的{{1}}中,添加了以下内容:
DocumentListTableViewController
两个打印语句将打印override func viewDidLoad() {
super.viewDidLoad()
print(titlePassed)
print(requestedEntity)
}
。
我想问题应该出在nil
上,也许是发件人……我不知道。
任何帮助将不胜感激。
答案 0 :(得分:3)
尝试像这样在sender
方法中传递performSegue()
参数:
@objc func documentTypeButtonTapped(_ sender: CustomButton) {
performSegue(withIdentifier: "goToDocumentList", sender: sender)
print(sender.documentType)
print(sender.requestEntity)
}
问题在于您正在实例化CustomButton()类型的新对象,而不是传递sender
。
答案 1 :(得分:2)
问题是您在CustomButton
调用中传递了performSegue
的新(空)实例,而不是在动作的sender
中传递了
但是创建数据按钮作为数据容器的自定义按钮的设计仍然很糟糕。 不要这样做。太可怕了。
有一个更简单,更有效的解决方案:
在AllDocumentsCollectionViewCell
中创建回调闭包
var callback : (()->Void)?
和一个IBAction
并将其连接到按钮,点击按钮时将调用回调。
@IBAction func documentTypeButtonTapped(_ sender: UIButton) {
callback?()
}
在HomeTableViewController
中,为回调分配一个闭包,在其中执行segue并传递数据源数组的项。
但是在每次UserDefaults().value(
的调用中调用collectionView
并为索引路径获取 same 项4次的方式非常低效。并且永远不要使用value(forKey
。 string(forKey
中有UserDefaults
。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let languageSelected = UserDefaults().string(forKey: "language")!
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
cell.callback { [weak self] in
let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
}
return cell
}
在prepare(for
中获取数据源项(我不知道它是什么类型),然后从那里检索信息。您甚至可以将整个项目传递给目标视图控制器。
func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {
let languageSelected = UserDefaults().string(forKey: "language")!
if let destination = segue.destination as? DocumentListTableViewController {
let item = sender as! WhatEverTheTypeIs // change this to the real type
destination.titlePassed = item.name.localized(lang: languageSelected)
destination.requestedEntity = item.entityName
destination.requestedSortBy = item.sortBy
destination.requestedPredicate = item.predicate
}
}
答案 2 :(得分:2)
在performSegue通话中,您正在发送CustomButton
的新实例
performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
因此在下一个视图控制器中,其参数将为零,您需要改为发送发送者。
performSegue(withIdentifier: "goToDocumentList", sender: sender)
您需要重写prepareForSegue
才能调用它,而无需更改其签名,可以这样写:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let languageSelected = UserDefaults().value(forKey: "language") as! String
if let destination = segue.destination as? DocumentListTableViewController {
let myCustomButton = sender as! CustomButton
destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
destination.requestedEntity = myCustomButton.requestEntity
destination.requestedSortBy = myCustomButton.requestSortBy
destination.requestedPredicate = myCustomButton.requestPredicate
}
}