Prepare for segue is autocalled - ios

I have a view crontroller called "subcateory2", this viewcontroller has a uicollectionview wit custom cell. I need two segues from my app. One of the called "to_videostable" from the viewcontroller to other view controller and the other calles "reload_collection" from the cell to the same viewcontroller(because the subcategory can have n-level of subcategories). The problem is with my prepareForSegue(i check in this function the identifier , that is defined in the " func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)",and execute different actions). When i select a cell this should happen:
first: go to my "func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)", check the condition and define my identifier for segue.
second: go to the prepareforsegue, check the condition and execute the actions.
but actually this happen:
first: in my ios simulator i select a cell.
second: my code go the prepareforsegue and go always for the segue called "reload_collection"(before going to my func collectionView(...)), and create a white views. In this moment is like a two threads are created, one of them go to the white windows and the other to the next stop.
third: this "second theard" go to the func collectionview(...) and check the condition, define the identifier, call to the performSegueWithIdentifier and go to the prepareforsegue function. In the prepareforsegue check the identifier and execute the differentes actions.
This is my code:
import UIKit
class Subcategory2: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
let viewUtils = ViewControllerUtils()
var result_category: Array<JSON> = []
#IBOutlet weak var collectionview: UICollectionView!
var tit: String!
var url: String!
var end_url:String = "?page_size=100"
var id_category: Int!
var index: NSIndexPath!
var url_children : String = ""
let imagePath = "http://d1rkb03u2ginv9.cloudfront.net/wp-content/uploads/"
override func viewDidLoad() {
self.viewUtils.showActivityIndicator(self.view)
super.viewDidLoad()
self.viewUtils.showActivityIndicator(self.view)
if self.result_category.isEmpty{
var category = category_function()
self.url = self.url + self.end_url
self.result_category = category.load_subcategory(self.url)}
self.viewUtils.hideActivityIndicator(self.view)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
println("entroooooooo")
if (self.result_category[indexPath.row]["children"].string != nil){
self.url_children = self.result_category[indexPath.row]["children"].string!
//while(self.url_children.isEmpty){}
println("voy a reloadcollection")
performSegueWithIdentifier("reload_collection", sender: cell)
//performSegueWithIdentifier("reload_collection3", sender: self)
}else{
println("voy a to_videostables")
performSegueWithIdentifier("to_videostable", sender: cell)
}
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//println(result_category.count)
return result_category.count }
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) ->UICollectionViewCell {
let cell: CollectionViewCellController2 = collectionView.dequeueReusableCellWithReuseIdentifier("cell2", forIndexPath: indexPath) as! CollectionViewCellController2
println(self.result_category[indexPath.row]["slug"].stringValue)
cell.label.text = self.result_category[indexPath.row]["slug"].stringValue
if (self.result_category[indexPath.row]["images"]["file"].string != nil){
//println("+++++++++++++++++")
var image = self.result_category[indexPath.row]["images"]["file"].stringValue
cell.image.sd_setImageWithURL(NSURL(string:self.imagePath + (image as! String)))
}else{
var image = "http://www.camping-oaza.com/images/joomlart/demo/default.jpg"
cell.image.sd_setImageWithURL(NSURL(string: image))
//cell.image.image = UIImage(named: image)
}
cell.NumberVideosLabel.text = self.result_category[indexPath.row]["videos_count"].stringValue
cell.NumberSubcategoryLabel.text = self.result_category[indexPath.row]["children_count"].stringValue
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "to_videostable"{
println("-------------")
println("voy a to_videostables")
let cell = sender as! UICollectionViewCell
let index = self.collectionview!.indexPathForCell(cell) // this return -> NSIndexPath?
//if (self.result_category[index!.row]["children"].string != nil){
// self.loaddata(self.result_category[index!.row]["children"].string!)
//}else{
let vc : VideosViewController = segue.destinationViewController as! VideosViewController
println(self.result_category[index!.row]["id"].intValue)
vc.id_category = self.result_category[index!.row]["id"].intValue
}
if segue.identifier == "to_livevideos"{
println("-------------")
println("to_livevideos")
println("-------------------")
let vc : SWRevealViewController = segue.destinationViewController as! SWRevealViewController
}
if segue.identifier == "reload_collection"{
println("-------------")
println("reload_collection")
println("-------------------")
var category = category_function()
let vc : Subcategory2 = segue.destinationViewController as! Subcategory2
vc.url = self.url_children
println(category.load_subcategory(self.url_children + self.end_url))
}
}
}
With this problem, always is created a white windows and after is created a windows with the real information.
the order of the println is :
- "reload_collection"
- "entroooooooo"
- "voy a reloadcollection" or "voy a to_videostables"
In this pictures show my main.stoyboard and the windwos that i can see in my app.

Updated Answer
You have a situation where you want to decide which segue to take when a cell is selected. You have wired one of your segues directly from the cell, which means the storyboard will create that segue for you. You also are calling performSegueWithIdentifier which creates another segue. You need to implement shouldPerformSegueWithIdentifier to cancel the "reload_collection" segue when you want segue to "to_videostables".
In the Original Answer below, I suggested you wire both segues from the viewController, but that won't work because one of your segues is back to the same viewController.
So, another way to do this is to:
Modify didSelectItemAtIndexPath to remove the code that handles the "reload_collection" segue. The Storyboard will be making that segue:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
println("entroooooooo")
if result_category[indexPath.row]["children"].string == nil {
println("voy a to_videostables")
performSegueWithIdentifier("to_videostable", sender: cell)
}
}
Wire the segue "reload_collection" from the cell to the viewController. This will allow the Storyboard to perform this segue for you.
Implement shouldPerformSegueWithIdentifier to tell the Storyboard when it should make this segue:
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if segue.identifier == "reload_collection" {
let indexPath = collectionView.indexPathForCell(sender as! UICollectionViewCell)
return result_category[indexPath.row]["children"].string != nil
}
return true
}
In prepareForSegue you will need to set up url_children since it is no longer being done by didSelectItemAtIndexPath:
if segue.identifier == "reload_collection"{
println("-------------")
println("reload_collection")
println("-------------------")
var category = category_function()
let vc : Subcategory2 = segue.destinationViewController as! Subcategory2
let indexPath = collectionView.indexPathForCell(sender as! UICollectionViewCell)
url_children = result_category[indexPath.row]["children"].string!
vc.url = url_children
println(category.load_subcategory(self.url_children + self.end_url))
}
Original Answer
Your segue is getting auto-called because you have wired it from the cell. If you want to trigger it with performSegueWithIdentifier it needs to be wired from the viewController like the other segue. Just remove the segue from the cell and rewire it from the viewController and give it the same identifier it had when you wired it from the cell and it should work.

Related

how to push ViewController from xib tableview Cell?

I have tableView within collectionView and i created using xib. I want to pushViewController when item is selected .I tried pushing the view controller in itemForRowAt method but it's not possible
class SecondTableView: UITableViewCell , UIcollectionViewDelegate ,UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// let vc = DataTableViewController()
// vc.delegate = self
// vc.pushNav()
let memeVC = storyboard?.instantiateViewController(withIdentifier: "MemeViewController") as! MemeViewController
memeVC.imagePassed = image
navigationController?.pushViewController(memeVC, animated: true)
print("item tapped\(indexPath)")
}
}
errors
Use of unresolved identifier 'storyboard'; did you mean 'UIStoryboard'?
Add segue as mentioned in the image and select show
Set segue identifier in your storyboard as mentioned in the image
Add below Protocol:
protocol CollectionViewCellDelegate: class {
func userDidTap()
}
Add below property in your table view class where the collection view delegate returns.
weak var delegate: CollectionViewCellDelegate?
Update delegate method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
delegate.userDidTap()
print("item tapped\(indexPath)")
}
}
confirm CollectionViewCellDelegate delegate to your first view controller & add this method:
func userDidTap() {
performSegue(withIdentifier: "showMemeViewController", sender: nil)
}
Add prepare for segue in your first VC.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showMemeViewController" {
let memeVC: MemeViewController = segue.destination as! MemeViewController
memeVC.imagePassed = image
}
}
Please try this let me know if you faced any other issue. Thanks.
You're trying to access storyboard property in a tableview cell, which isn't there in the first place, it's a UIViewController property not a UITableViewCell property, hence the error, you'll have to delegate your selection to the viewController then let the controller do the segue normally.
You can start doing that via delegates as I mentioned above, for example if you're passing image to the controller you wanna segue to:
protocol ImageTableViewCellDelegate: class {
// pass the the image or any variable you want in the func params
func userDidTap(_ image: UIImage)
}
then you'd add it to the cell and confirm the controller to it
class SecondTableView {
weak var delegate: ImageTableViewCellDelegate?
}
In your controller:
extension MyViewController: ImageTableViewCellDelegate {
func userDidTap(_ image: UIImage){
let memeVC = storyboard?.instantiateViewController(withIdentifier: "MemeViewController") as! MemeViewController
memeVC.imagePassed = image
navigationController?.pushViewController(memeVC, animated: true)
print("item tapped\(indexPath)")
}
}
this should work, let me know if you had any further problems

Perform a segue selection from a uicollectionview that is embedded in a tableview cell?

Currently we have a uicollectionview that is embedded in a tableview cell. When the collection view cell is selected it's suppose to initiate a push segue to another view controller. The problem is there is no option to perform the segue on the cell. Is there a way around it? Here is the cell:
class CastCell : UITableViewCell {
var castPhotosArray: [CastData] = []
let extraImageReuseIdentifier = "castCollectCell"
let detailToPeopleSegueIdentifier = "detailToPeopleSegue"
var castID: NSNumber?
#IBOutlet weak var castCollectiontView: UICollectionView!
override func awakeFromNib() {
castCollectiontView.delegate = self
castCollectiontView.dataSource = self
}
}
extension CastCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return castPhotosArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = castCollectiontView.dequeueReusableCell(withReuseIdentifier: extraImageReuseIdentifier, for: indexPath) as! CastCollectionViewCell
cell.actorName.text = castPhotosArray[indexPath.row].name
return cell
}
}
extension CastCell: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.castID = castPhotosArray[indexPath.row].id
performSegue(withIdentifier: detailToPeopleSegueIdentifier, sender: self) //Use of unresolved identifier 'performSegue' error
}
}
extension CastCell {
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let peopleVC = segue.destination as! PeopleDetailViewController
peopleVC.id = self.castID
}
}
The problem is there is no option to perform the segue on the cell
There is no such thing as a "segue on a cell". A segue is from one view controller to another. performSegue is a UIViewController method. So you cannot say performSegue from within your CastCell class, because that means self.performSegue, and self is a UITableViewCell — which has no performSegue method.
The solution, therefore, is to get yourself a reference to the view controller that controls this scene, and call performSegue on that.
In a situation like yours, the way I like to get this reference is by walking up the responder chain. Thus:
var r : UIResponder! = self
repeat { r = r.next } while !(r is UIViewController)
(r as! UIViewController).performSegue(
withIdentifier: detailToPeopleSegueIdentifier, sender: self)
1: A clean method is to create a delegate protocol inside your UITableViewCell class and set the UIViewController as the responder.
2: Once UICollectionViewCell gets tapped, handle the taps inside the UITableViewCell and forward the tap to your UIViewController responder through delegatation.
3: Inside your UIViewController, you can act on the tap and perform/push/present whatever you want from there.
You want your UIViewController to know what is happening, and not call push/presents from "invisible" subclasses that should not handle those methods.
This way, you can also use the delegate protocol for future and other methods that you need to forward to your UIViewController if needed, clean and easy.

Issue when performing a segue on a tableview cell

I'm currently learning Swift and trying to perform a segue when the user taps on one of the tableview cells that the app presents. At the moment, whenever the user performs this action, the next view controller is loaded successfully, but it seems that, for some reason, I cannot access any of its UI elements, as each time that I try to do it, I end up getting this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
The error points to the line in which I try to modify the text of one of the labels that are displayed on the next view controller
This is the didSelectRowAt function:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
self.performSegue(withIdentifier: "segue1", sender: self)
}
and this is the prepareForSegue function:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue1" {
let destinationVC = segue.destination as! UserViewController
let selectedRow = tableView.indexPathForSelectedRow!
let selectedCell = tableView.cellForRow(at: selectedRow) as! CustomCell
destinationVC.usernameLabel.text = selectedCell.userName.text //this is where the error is pointing to
destinationVC.bioLabel.text = selectedCell.bio.text
destinationVC.userImage.image = selectedCell.photo.image
}
}
I have no idea about what is causing this problem. My goal is to pass the data from the tapped cell to the next view controller, but this obviously is preventing me from doing so. Does anyone know how I can fix this? Thanks in advance.
Note: I assumed that userName and bio were both UITextFields
Why don't you try something like this?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue1" {
let destination = segue.destination as! UserViewController
// Use of optional binding to make sure an indexPath exists
if let indexPath = tableView.indexPathForSelectedRow {
let cell = tableView.cellForRow(at: IndexPath(row: indexPath.row, section: indexPath.section)) as! CustomCell
// Notice how we are not directly updating the label as before.
destination.usernameText = cell.userName?.text
destination.bioText = cell.bio?.text
}
}
}
Now in UserViewController:
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var bioLabel: UILabel!
// What we will be passing the text to instead.
var usernameText: String?
var bioText: String?
override func viewDidLoad() {
super.viewDidLoad()
// update the labels with the text from the proper cell.
usernameLabel?.text = usernameText
bioLabel?.text = bioText
}
You can just do the same for your image, just different types. This has to do with the outlets not being allocated when used in prepare(for segue:).
i had great issue with the prepare for segue method when trying the same thing with a UICollectionView. The 2 are very similar so you should be able to change collectionview to tableview easily.
this is what i did... using variable selectedPack
in the view controller you want to segue to you need to set the variable
// passed packName from PackViewController
var selectedPack: String!
then in the viewcontroller you are selecting the cell
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle the segue to JourneyViewController with variable "selectedPack"
// not sure why you need to set the storyboard but it works
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
//create instance of the viewcontroller
let transportJourneyViewController = storyBoard.instantiateViewController(withIdentifier: "JourneyViewController") as! JourneyViewController
//value to pass - has been defined in journey
transportJourneyViewController.selectedPack = INSERT_YOUR_VALUE_TO_PASS
//present the vc
self.present(transportJourneyViewController, animated:true, completion:nil)
}
JourneyViewController is the storyboardID and ClassName of the viewcontroller you want to go to.set in the interface builder.
You'll also need to have the tableviewdatasource and tableviewdelegate defined at the top level of your view controllers and in the storyboard itself.
class JourneyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

Passing value to another ViewController upon selecting cell in UICollectionView

I want to select a username from a UICollectionView, and pass that string to another view.
I can select the cell using "didSelectRowAtIndexPath". However the prepareForSegue function runs before my selection is set, and the segue passes the initial value.
I can't figure out how to get the index value in the prepareForSegue overide. If it were a UITableView, I think I could use indexPathForSelectedRow.
Here's what I have:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedUsername = userNames[indexPath.row]
selectedRow = indexPath.row
println ("Cell \(indexPath.row) selected")
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "userSelectSegue") {
let nextVC = segue.destinationViewController as ViewController;
nextVC.passedUsername = userNames[selectedRow]
println("prepareForSegue")
}
}
Running this always passes userNames[0]
The output window Prints:
prepareForSegue
Cell 2 selected
EDIT 1:
I basically think I want the following tableview code, but I can't get it working for UICollectionView (i.e. I can't get the cell number):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "userSelectSegue") {
let nextVC = segue.destinationViewController as ViewController;
let indexPath = UserSelectCollection.indexPathForSelectedRow()
nextVC.passedUsername = userNames[indexPath.row]
}
}
Here's How I solved it:
I deleted the segue connecting the collection cell to the second view controller
I created another segue between the two view controllers (called the identifier "userSelectSegue")
Added a performSegueWithIdentifier call to the didSelectItemAtIndexPath
Here's the code:
var userNames = ["Bob", "Sally", "Mike", "Mary", "James"]
var selectedRow = 0
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
self.performSegueWithIdentifier("userSelectSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "userSelectSegue") {
let nextVC = segue.destinationViewController as ViewController;
nextVC.passedUsername = userNames[selectedRow]
}
}
This is the general behavior of the iOS. What i implement is in this case is. Do not override the method didSelectRowAtIndexPath. When you tap on any cell, then in the function prepareForSegue. You can get the cell in the sender object. From that cell get the selected item. Get the indexPath.item. After that get the object from the array and pass it to the next view controller.

Push segue from UITableViewCell to ViewController in Swift

I'm encountering problems with my UITableViewCells. I connected my UITableView to a API to populate my cells.
Then I've created a function which grabs the indexPath.row to identify which JSON-object inside the array that should be sent to the RestaurantViewController.
Link to my Xcode Project for easier debugging and problem-solving
Here's how my small snippet looks for setting the "row-clicks" to a global variable.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
i = indexPath.row
}
And here's my prepareForSegue() function that should hook up my push-segue to the RestaurantViewController.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "toRestaurant"{
let navigationController = segue.destinationViewController as UINavigationController
let vc = navigationController.topViewController as RestaurantViewController
vc.data = currentResponse[i] as NSArray
}
}
And here's how I've set up my segue from the UITableViewCell
Here's my result, I've tried to click every single one of these cells but I won't be pushed to another viewController...I also don't get an error. What is wrong here?
Tried solutions that won't work
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "toRestaurant"{
let vc = segue.destinationViewController as RestaurantViewController
//let vc = navigationController.topViewController as RestaurantViewController
vc.data = currentResponse[i] as NSArray
}
}
The problem is that you're not handling your data correctly.
If you look into your currentResponse Array, you'll see that it holds NSDictionaries but in your prepareForSegue you try to cast a NSDictionary to a NSArray, which will make the app crash.
Change the data variable in RestaurantViewController to a NSDictionary and change your prepareForSegue to pass a a NSDictionary
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let cell = sender as? UITableViewCell {
let i = redditListTableView.indexPathForCell(cell)!.row
if segue.identifier == "toRestaurant" {
let vc = segue.destinationViewController as RestaurantViewController
vc.data = currentResponse[i] as NSDictionary
}
}
}
For Swift 5
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let cell = sender as? UITableViewCell {
let i = self.tableView.indexPath(for: cell)!.row
if segue.identifier == "toRestaurant" {
let vc = segue.destination as! RestaurantViewController
vc.data = currentResponse[i] as NSDictionary
}
}
}
The following steps should fix your problem. If not, please let me know.
Remove your tableView(tableView, didSelectRowAtIndexPath:) implementation.
Make data on RestaurantViewController have type NSDictionary!
Determine the selected row in prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let cell = sender as? UITableViewCell {
let i = tableView.indexPathForCell(cell)!.row
if segue.identifier == "toRestaurant" {
let vc = segue.destinationViewController as RestaurantViewController
vc.data = currentResponse[i] as NSDictionary
}
}
}
Dropbox link to stack3 directory
I am having difficulty understanding why your software is much different than a standard 2 level tableview structure. So I coded a short example which you can access from this link. I have also included the sources code below.
The program mimics what you have (as best as I understood it). Table Controller 1 segues to Table Controller 2 from the tableview cell. I had no issues with segue-ing. Notice that I do not have nor need to augment the Storybook to initiate the segue.
I have embedded both the controllers in Navigation Controllers. My experience is that it saves a lot of effort to set up the navigation.
Alternately, I could have control-dragged from the first TableViewController symbol on top of the screen to the second controller and set up the segue.
I used a global variable (selectedRow) although it is not a recommend practice. But you just as easily use the prepareForSegue to set a variable in the RestaurantTableViewController (I show an example)
Finally, I recommend checking the Connections Inspector (for the table view cell in the first controller) to confirm that there is a segue to the second controller. If you control-dragged properly there should be confirmation prompt as well as an entry in the Connections Inspector.
Unfortunately I just cant get the code properly formatter
import UIKit
var selectedRow = -1
class TableViewController: UITableViewController {
var firstArray = ["Item1","Item2","Item3","Item4"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return firstArray.count
}
let nameOfCell = "RestaurantCell"
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = firstArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let vc = segue.destinationViewController as RestaurantTableViewController
// can write to variables in RestaurantTableViewController if required
vc.someVariable = selectedRow
}
}
import UIKit
class RestaurantTableViewController: UITableViewController {
var secondArray = ["Item 2.1", "Item 2.2", "Item 2.3", "Item 2.4"]
var someVariable = -1
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return secondArray.count
}
let nameOfCell = "RestaurantCell"
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = secondArray[indexPath.row]
if indexPath.row == selectedRow {
cell.textLabel!.text = cell.textLabel!.text! + " SELECTED"
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
}
}
I noticed that in your screenshot of your storyboard, the segue is connecting the first prototype cell to the RestaurantViewController. This prototype cell looks like it's the "Basic" style of cell with a disclosure indicator accessory on the right. But look at the screenshot of your app running. The table is being populated with cells that appear to be the "Subtitle" style of cell without a disclosure indicator accessory on the right.
The reason that your segue is never firing no matter what you do is that the segue is only configured to work for a specific prototype cell, but that prototype cell is never being used when you populate the table. Whatever you're doing in tableView:cellForRowAtIndexPath:, you're not using the prototype cell that you want.
#Starscream has the right idea dequeueing the right cell with the right identifier and matching it with the identifier of the prototype cell in Interface Builder. The crash that you're getting even after doing that might be because of the previous problem mentioned in the comments above. Your segue in the storyboard is clearly pointing to a UITableViewController. Your code in prepareForSegue:sender: should be let vc = segue.destinationViewController as RestaurantViewController, as long as RestaurantViewController is a subclass of UITableViewController. You'll crash if you try to cast it as a UINavigationController. Also make sure that the class for the destination UITableViewController in the storyboard is listed as RestaurantController in the Identity Inspector pane. You'll crash if your program compiles thinking that the storyboard just contains a generic UITableViewController there.
Getting back to the original problem more, I don't know how you've implemented tableView:cellForRowAtIndexPath:, which might be crucial. Maybe it's not so simple. Maybe you plan on handling many prototype cells or generate custom cells at runtime. In this case, one way to make this simple for you is to programmatically perform the segue when the user taps on a cell. Instead of using a specific prototype cell, make the segue a connection originating from the "Restauranger nära mig" UITableViewController going to the RestaurantViewController. (Connect in Interface Builder by control-click dragging from the Table View Controller icon at the top of the first one over to the body of the second). You must give this segue an identifier in the Attributes Inspector pane to make this useful. Let's say it's "toRestaurant". Then at the end of your tableView:didSelectRowAtIndexPath: method, put this line of code: self.performSegueWithIdentifier("toRestaurant", sender: self). Now no matter what cell is selected in the table, this segue will always fire for you.
Try creating cells like this in your cellForRow method:
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath)
Im going out on a whim here since I am just getting into swift right now but the way I do it in my prepareForSegue() is something like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "toRestaurant"{
let navigationController = segue.destinationViewController as UINavigationController
let vc = navigationController.topViewController as RestaurantViewController
//notice I changed [i] to [index!.row]
vc.data = currentResponse[index!.row] as NSArray
}
}
What it looks like to me is that you are calling the i variable which is kind of like a private variable inside a method of your class. You can do something like #Syed Tariq did with the selectRow variable and set it above your class SomeController: UIViewController /*, maybe some more here? */ { and then sign the variable inside your
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
}
method like above but both ways should work rather well.
I had the same problem and I found the solution to be:
performSegueWithIdentifier("toViewDetails", sender: self)
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cellnumber = procMgr.processos[indexPath.row].numero
println("You selected cell #\(indexPath.row)")
println(cellnumber)
performSegueWithIdentifier("toViewDetails", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toViewDetails" {
let DestViewController : ViewDetails = segue.destinationViewController as! ViewDetails
}
}
You may need to get the selected cell index of the UItableview. Below code used the selected cell index (UItableview.indexPathForSelectedRow) to get a correct element of the array.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "seguaVisitCardDetial" {
let viewController = segue.destinationViewController as! VCVisitCardDetial
viewController.dataThisCard = self.listOfVisitCards[(tblCardList.indexPathForSelectedRow?.row)!]
}
}
I had this problem, too; the segue from UITableViewCell did not call.
After some searching, I found it is because I had chosen "No Selection" for "Selection" field.

Resources