Reputation: 349
I created a custom button to include in the button the information I need:
class CustomButton: UIButton {
var urlString: String?
var documentType: String?
var requestEntity: String?
var requestSortBy: [NSSortDescriptor]?
var requestPredicate: NSPredicate?
}
When I create the cells in the collectionView (embedded in a tableView) I include the information in my custom button, called documentTypeButton
. And also the target for executing the function HomeTableViewController.documentTypeButtonTapped(_:)
to perform the 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
}
And the, in the HomeTableViewController
I have the function to execute when touching inside the button:
@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
}
}
The print statements above work well and print the information. And the segue goes to the DocumentListTableViewController
.
In the viewDidLoad
of the DocumentListTableViewController
I added the following:
override func viewDidLoad() {
super.viewDidLoad()
print(titlePassed)
print(requestedEntity)
}
And the two print statements print nil
.
I guess the problem should be in the prepareForSegue
, maybe with the sender... I don't know.
Any help would be appreciated.
Upvotes: 3
Views: 696
Reputation: 285079
The issue is that you pass a new (empty) instance of CustomButton
in the performSegue
call rather than the sender
of the action.
But your design to create a custom button as data container is still worse. Don't do that. It's horrible.
There is a much easier and more efficient solution:
In AllDocumentsCollectionViewCell
create a callback closure
var callback : (()->Void)?
and an IBAction
and connect it to the button, the callback is called when the button is tapped.
@IBAction func documentTypeButtonTapped(_ sender: UIButton) {
callback?()
}
In HomeTableViewController
assign a closure to the callback, perform the segue in there and pass the item of the data source array.
But the way calling UserDefaults().value(
in each call of collectionView
and getting the same item for index path 4 times is very very inefficient. And never use value(forKey
. There is string(forKey
in 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 {
let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
self.performSegue(withIdentifier: "goToDocumentList", sender: item)
}
return cell
}
In prepare(for
get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.
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
}
}
Upvotes: 2
Reputation: 1292
In your performSegue call your are sending a new instance of CustomButton
performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
So its parameters are going to be nil in the next view controller, you need to send the sender instead.
performSegue(withIdentifier: "goToDocumentList", sender: sender)
You need to override prepareForSegue
for it to be called, no need to change to its signature, you could write it like this instead:
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
}
}
Upvotes: 2
Reputation: 587
Try to pass sender
parameter in performSegue()
method like this:
@objc func documentTypeButtonTapped(_ sender: CustomButton) {
performSegue(withIdentifier: "goToDocumentList", sender: sender)
print(sender.documentType)
print(sender.requestEntity)
}
Problem is that you are instantiating new object of type CustomButton() instead passing sender
.
Upvotes: 4