Selecting a Table View Cell programmatically from another view controller - ios

I haven't coded this, but I am wondering if it is even possible and how it can be done. Let's say I am on VC1. If I press a button on VC1, I want to be taken to VC2, which has a table view, and then have it automatically select the first cell and segue to a VC3. Anybody with experience of doing this.

Assuming this is more of a conceptual question, yes, this can be done. I've worked on an app where the feature required animating through multiple levels of table views programmatically using NSNotification's. Essentially, you can just have a shared method that is called from tableView:didSelectRowAtIndexPath: that you would call directly to "select" the table cell and do whatever the default action was.
Let me know if this answers your question.

Yes It can be done.There can be many ways, One way is this -
1.In Your viewDidAppear of VC2 have this lines -
override func viewDidAppear() {
super.viewDidAppear()
let rowToSelect:NSIndexPath = NSIndexPath(forRow: 0, inSection: 0)
tableView.selectRowAtIndexPath(rowToSelect, animated: true, scrollPosition: UITableViewScrollPosition.None)
self.tableView(tableView, didSelectRowAtIndexPath: rowToSelect)
}
In your tableView method didSelectRowAtIndexPath -
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
self.presentVC3()
}
}
func presentVC3() {
//Initialize VC3
// And Segue to VC3
}

Related

"deselectRow" doesn't animate if using "popViewController"

Swift 5, Xcode 10
My app uses two ViewControllers:
VC1, UITableView, clicking on a cell calls
VC2, displays further information about a cell with the default UINavigationBarItem "back" button on the top left and an addition "save" button at the bottom
The "save" buttons saves the changes made. To go back to the VC2, you can either click on the "back" button or save the changes, which also automatically loads VC2 using:
#IBAction func onClickSave(_ sender: Any) {
//Save changes
delegate?.passRowSavedBack(true) //Tell VC1 that changes were saved
navigationController?.popViewController(animated: true)
}
If I go back using the UINavigationBarItem "back" button, the cell also keeps its selection color for a second, then removes it (like in the iOS "Contacts" app) using this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
myTableView.deselectRow(at: mylastRowPickedIndex!, animated: true)
}
Example gif.
The problem is: If I go back with the "Save" button, this code is called too but there's no animation.
My guess is that popViewController takes longer to go back than whatever the "back" button calls, so the animation is played but you don't "arrive" in time to see it.
But how do I fix this? Is there a different way to go back to VC1 through the "Save" button (without removing the default "back" button!) that still plays the animation?
Edit: What I'm doing exactly:
In VC2: Save the changes
Tell VC1 that they were saved with a delegate (check 1st code above):
protocol PassingProtocol {
func passRowSavedBack(_ valueSent: Bool)
}
Go back to VC1 using popViewController (check 1st code above)
In VC1: deselectRow in viewWillAppear (check 2nd code above)
rowsSaved[lastRowPicked] = true, so it can add an accessoryType in here:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
cell.accessoryType = (rowsSaved[indexPath.row]==true) ? .checkmark : .none
return cell
}
myTableView.reloadData() - so it displays the new checkmark
Okay, finally I think I understand what is the problem.
You are calling myTableView.reloadData() and this is the problem with deselecting animation.
You can move myTableView.reloadData() in viewDidAppear() and everything will be okay.

Open TableView To Last Clicked Cell

I have a tableview list with clickable cells, when one is clicked a new viewcontroller opens up. When a back button is clicked and the first VC is called, the tableview resets to the top of the list. How can I change this so when the back button is clicked the tableview goes back to the original cell clicked? From what I understand, I need a tableview.scrollToRow, but I'm getting a little lost in the indexPath that I need to select (believe I need to save the last selected row, but now sure how to do this)
Here's the code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let webVC = UIStoryboard.init(name: "MainVC", bundle: nil).instantiateViewController(withIdentifier: "SecondaryVC") as! WebViewController
webVC.urlLink = self.listings?[indexPath.row].url
self.present(webVC, animated: true, completion: nil) }
override func viewWillAppear(_ animated: Bool) {
tableview.scrollToRow(at: indexPathSelected, at: .middle, animated: false)
}
Your problem is that you are actually moving forward to a new instance of your view controller rather than back to the existing instance. If you move back then the state of the view controller will be as you left it and there will be no need to do anything to the tableview.
You should use an unwind segue to move back
As your cell is respond to your touch(and you did not call deselectRow(at indexPath: IndexPath) after selecting cell), the tableView will keep your selection(s), so when you back to your viewController just call tableView.indexPathForSelectedRow(or tableView.indexPathsForSelectedRows) in your viewWillAppear() method.

Swift - How to implement a defaultviewcontroller loop

I'm attempting to create 2 different default view controllers that then get called and do their specified action depending on what was in the cell. Would you create the view controller in the main storyboard use an xib, etc?
Basically I have a xml file that I'm parsing and then creating table views for till I get to the last (details) page for the item. From my understanding it is better to use the same tableviewcontroller multiple times instead of creating 1 for each level. Am I supposed to be creating a segue loop?
There are checks currently in place to make sure I use the right segue.
Would you pefrom the segue with:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath as IndexPath)
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
segueLocation = hNTUL[(indexPath as NSIndexPath).row].locationLevel
segueTitle = hNTUL[(indexPath as NSIndexPath).row].locationTitle
if segueLocation == "TableView" {
performSegue(withIdentifier: "defaultDetailSeague", sender: cell)
let destinationVC = DefaultDetailViewController()
destinationVC.detailTitle = segueTitle
}
if segueLocation == "DetailView" {
performSegue(withIdentifier: "defaultTableSeague", sender: cell)
let destinationVC = DefaultTableViewController()
destinationVC.tableTitle = segueTitle
}
}
It is also possible that I'm trying to go about this the wrong way.
I've also been searching for project examples but haven't found any that might guide me in the right direction.
Thoughts?
If you call performSegue, you must not create a destinationVC; the segue creates it for you. To configure the destination view controller, implement prepare(for:sender:) and fetch the segue's destination, casting it down to a DefaultDetailViewController. Be sure to check that this is the right segue first!

Navigating different table-cell to different UIVewController in Swift

I am sorry for echoing same question but after a lot of time spending I could not figure out the issue.
Suppose, a UITableView have 2 table_cell s and I want to navigate different UIViewController from each table_cell. How do I do that?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
// go to DetailVC_1
} else if indexPath.row == 1 {
// go to DetailVC_2
}
Either present a new view controller manually:
self.presentViewController(controller, animated:true, completion:nil)
// or push on a navigation controller
self.navigationController.pushViewController(controller, animated:true)
Or perform a segue you set up in a storyboard earlier. (Drag from the view controller to another view controller in your storyboard).
self.performSegueWithIdentifier("MyIdentifier", sender: self)
When using storyboards you can also use multiple cell types and setup a segue from each cell type to a new controller. This way the new controller will be presented automatically. The only code you might need to use in that case would be a prepareForSegue method where you pass the correct information to the presented controller before the segue is performed.
Try this:
if indexPath.row == 0 {
self.performSegueWithIdentifier("firstViewController", sender: self)
} else if indexPath.row == 1 {
self.performSegueWithIdentifier("secondViewController", sender: self)
}
If you have several view controllers, you can call them viewController0 and viewController1 etc. Then you can have a string "viewController" + String(indexPath.row). Hope this helps.

ViewController presented slowly in didSelectRowAtIndexPath

I want to display next ViewController ondidSelectRowAtIndexPath and is happening as follows.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var section = indexPath.section
var row = indexPath.row
var cell:UITableViewCell = self.tblView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = "hello"
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
frequentVC = storyboard.instantiateViewControllerWithIdentifier("frequentVC") as? DropOffFrequentVC
self.presentViewController(frequentVC!, animated: true,completion: nil)
}
The nextViewController is presented and i dismiss the UIViewController as self.dismissViewControllerAnimated(true, completion:nil) and again the previous UIViewController gets called but now when i wait for sometime and try again presenting UIViewController, the UIViewController gets called very slowly but thedidSelectRowAtIndexPath is called instantly. During the waiting period if i tap aroundView anywhere then instantlyUIViewController is presented.Also, if i tapp for two timesUIViewController is presented instantly.
HERE IS THE PROJECT:
https://drive.google.com/open?id=0B6dTvD1JbkgBN0J3SkFOTDJtZlU&authuser=0
I've encountered this many times.
I don't fully understand why this fixes the problem but it works.
tableView.deselectRow(at: indexPath, animated: false)
Make sure animated is false and call this before you present the view controller.
My hypothesis:
The selected cell is the first responder.
Therefore it's in charge of presenting the new view controller.
Hence the lag.
We can't see the actual UITableViewCell code because it's private but something in there is responsible for performing that action with a delay.
Note: The response above said that the lag is due to using storyboard.
That is wrong because I'm not using storyboards and I still get the lag.
I downloaded you code. Did not experience any lag in opening the ViewController. It may depend on the performance on your computer (if running in simulator like I did).
However, you should definitely make some changes to your code. Firstly look into how storyboards can be constructed. You are making a lot of UI in code now which is both harder and in your case performance wise bad. Always creating a new UILabel and other UI-element every time cellForRowAtIndexPath is called is a bad practice.
Secondly using seques with storyboards also makes your life easier. Skip presentViewController and use performSegueWithIdentifier and other methods instead. A lot of the logic can be created directly in Interface builder by just dragging between the views.
http://www.raywenderlich.com/81879/storyboards-tutorial-swift-part-1
You should present your viewcontroller in main thread just like:
DispatchQueue.main.async {
self.presentViewController(
frequentVC!,
animated: true,
completion: nil
)
}

Resources