I'm trying to build my first app with three tableViews which are hierarchical. The middle VC has two guard let in one prepare for segue function.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? AddMemberViewController else {
return
}
destination.club = club
guard let Destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else {
return
}
Destination.member = members[selectedRow]
}
That's how it looks like. Can I fix this, that both func get used by my app, because it just uses the one on the top.
The problem is if you want to segue to TransactionViewController the function already returns because segue.destination is not AddMemberViewController.
Instead you should give your segues different identifiers and ask for them in prepareForSegue. Something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddMemberVCSegue" {
guard let destination = segue.destination as? AddMemberViewController else {
return
}
destination.club = club
}
if segue.identifier == "TransactionVCSegue" {
guard let Destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else {
return
}
Destination.member = members[selectedRow]
}
}
Just replace guards with if lets:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? AddMemberViewController {
destination.club = club
} else if let destination = segue.destination as? TransactionViewController, let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row {
destination.member = members[selectedRow]
}
}
prepare(for is called for one specific segue, so executing both guard let after another is unnecessarily expensive.
Usually you are checking the identifier of the segue with a switch statement, replace the literal identifiers with your real values
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "memberSegue":
let destination = segue.destination as! AddMemberViewController
destination.club = club
case "transactionSegue":
guard let selectedRow = self.tableViewMember.indexPathForSelectedRow?.row else { return }
let destination = segue.destination as! TransactionViewController
destination.member = members[selectedRow]
default: break
}
}
Related
i have two segues in this tableViewController, but the downcasting in prepare(for: segue) doesn't work.
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
print("into segue")
super.prepare(for: segue, sender: sender)
switch segue.identifier {
case "addItem":
print("addItem Segue")
if let addItemVC = segue.destination as? ItemDetailViewController {
print("if let done")
addItemVC.container = container
} else {
print("WTF")
}
case "editItem":
print("editItem Segue")
if let editItemVC = segue.destination as? ItemDetailViewController {
guard let selectedItemCell = sender as? PriorityListTVCell else {
fatalError("Unexpected sender: \(String(describing: sender))")
}
guard let indexPath = tableView.indexPath(for: selectedItemCell) else {
fatalError("The selected cell is not being displayed by the table")
}
editItemVC.editedInfo = list[indexPath.row]
print("passed indexPath.row: \(indexPath.row)")
editItemVC.container = container
}
default:
break
}
}
if i click "add" button, in the console it'll print out
into segue
addItem Segue
WTF
not sure why the downcasting doesn't work, does it have anything to do with segue types of destination?
Thanks for help!
This
if let addItemVC = segue.destination as? ItemDetailViewController {
won't work if the destination vc isn't of type ItemDetailViewController meaning you need to assign the class name in IB , for help you can do
print(type(of:segue.destination))
For navigation do
if let nav = segue.destination as? UINavigationController ,
let addItemVC = nav.viewControllers?.first as? ItemDetailViewController {}
I am trying to pass data to another controller with a segue after clicking on a button.
This is my code:
#IBAction func agilityDogBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[0]
self.performSegue(withIdentifier: "DogAgilitySegue", sender: course)
}
}
#IBAction func baseEducationBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[1]
self.performSegue(withIdentifier: "BaseEducationSegue", sender: course)
}
}
#IBAction func puppyBtnPressed(_ sender: Any) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[2]
self.performSegue(withIdentifier: "PuppyClassSegue", sender: course)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DogAgilitySegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
} else if segue.identifier == "PuppyClassSegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
} else if segue.identifier == "BaseEducationSegue" {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
destination.course = course
}
}
}
My problem is that the first two segues are working perfectly fine.
The third one (PuppyClassSegue) is not passing the data through.
It opens the page but the data are not showing, basically the destination.course is not happening.
Any idea how is that possible?
Thank you!
It appears that course is nil , also you can do this by hooking all buttons to the same action and setting tags for them 0,1,2 respectively
#IBAction func agilityDogBtnPressed(_ sender: UIButton) {
if let objs = controller.fetchedObjects, objs.count > 0 {
let course = objs[sender.tag]
self.performSegue(withIdentifier: "SegueFromCon", sender: course)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? ClassDetailsVC {
if let course = sender as? Course {
print("hit here ",course)
destination.course = course
}
}
}
make 1 segue named say SegueFromCon from the current vc to the detailsVC
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "stopRecording" {
let playSoundsVC = segue.destination as! PlaySoundsViewController
let recordedAudioURL = sender as! URL
playSoundsVC.receivedAudio = recordedAudioURL
}
}
The question is that my Xcode generating error
Value of type 'PlaySoundsViewController' has no member 'receivedAudio'
For this to work the destinationVC should look like this
class PlaySoundsViewController:UIViewController {
var receivedAudio:URL?
.....
}
I have a tableview that lists all of my "places" from firebase. I have a UISearchController to obviously search through these "places". The problem is when I just tap on the UISearchController but don't type anything and select a "place" I get a index out of range error. If I am typing or do not activated the UISearchController, it segues fine. Just when it is active and don't type is when I get the error. It throws the error on "let user = filteredUsers[indexPath.row]"
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "BusinessProfiles" {
// gotta check if we're currently searching
if self.searchController.isActive {
if let indexPath = tableView.indexPathForSelectedRow {
let user = filteredUsers[indexPath.row]
let controller = segue.destination as? BusinessProfilesViewController
controller?.otherUser = user
}
} else {
if let indexPath = tableView.indexPathForSelectedRow {
let user = usersArray[indexPath.row]
let controller = segue.destination as? BusinessProfilesViewController
controller?.otherUser = user
}
}
}
}
As you say, you did not perform any search and select a place, right? If so, you call empty filteredUsers[indexPath.row] with indexPath.row of selected row, which have an positive index. As so, you must first check if search was perform, and only then call filteredUsers[indexPath.row] like this:
if !filteredUsers.isEmpty {
if self.searchController.isActive {
if let indexPath = tableView.indexPathForSelectedRow {
let user = filteredUsers[indexPath.row]
Just added this "&& searchController.searchBar.text != ""
" to correct my problem
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "BusinessProfiles" {
// gotta check if we're currently searching
if self.searchController.isActive && searchController.searchBar.text != "" {
if let indexPath = tableView.indexPathForSelectedRow {
let user = filteredUsers[indexPath.row]
let controller = segue.destination as? BusinessProfilesViewController
controller?.otherUser = user
}
} else {
if let indexPath = tableView.indexPathForSelectedRow {
let user = usersArray[indexPath.row]
let controller = segue.destination as? BusinessProfilesViewController
controller?.otherUser = user
}
}
}
}
I'm attempting to create a variable "indexx" that will be segued to my next tableController. indexx will hold the indexPath of the selected cell from my collectionView, however, I am unsure which property to use. I am vastly more familiar with tableController properties so I'm having difficulty finding a successful solution to this piece of code. Would you happen to know my error?
As a quick note - foodcv is my collectionView and numberr is the variable in the second destination controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destViewController = segue.destination as? foodtable {
let indexx = self.foodcv.indexPath(for: foodcell)
destViewController.numberr = indexx
}
}
let numberr : IndexPath = []
Maybe it's too late, but here you go:
Swift 4
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destViewController = segue.destination as? foodtable {
let indexPaths : NSArray = foodcv.indexPathsForSelectedItems! as NSArray
let indexx : IndexPath = indexPaths[0] as! IndexPath
destViewController.numberr = indexx[selectedindexPath.row]
}
}
Use this modified implementation,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destViewController = segue.destination as? foodtable {
let indexx = self.foodcv.indexPathForCell(sender as! UICollectionViewCell)
destViewController.numberr = indexx
}
}