TableView Not loading from didselectRowAtindexPath in another tableview - ios

I'm working with swift 2.2 and xcode 7.3 . I am trying to load a table view from another tableview when a row gets clicked . In
didSelectRowAtIndexPath
of the first table View , I create an instance of the other table view class and call it using the pushViewController . But the table view doesn't get loaded and screen remains the same. My code is
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
NSLog("It did enter the didselectRowAtIndexPath")
if (indexPath.section == 0){
let enrolledView = DetailsViewController()
navigationController?.pushViewController(enrolledView, animated: true)
}
if (indexPath.section == 1){
let appcatalog = AppCatalogViewController()
navigationController?.pushViewController(appcatalog, animated: true)
}
if (indexPath.section == 2){
let support = supportViewController()
navigationController?.pushViewController(support, animated: true)
}
}
Note : "It did enter the didselectRowAtIndexPath" gets printed in the log . SO Kindly let me know if there is something that am not doing correctly .

Could you give us a bit more of your code?
For example how have you embedded your class in a navigation controller?
Because if nothing appears it is probably due to the fact that navigationController is nil

I think you have two mistakes in your code.
The first one:
You haven't embedded your controller into a UINavigation controller.
The second One:
You are not initiating your view controller before your could move onto it.First assign a storyboard identifier to each of your view controller. So change your code as:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
NSLog("It did enter the didselectRowAtIndexPath")
if (indexPath.section == 0){
let enrolledView = self.storyboard?.instantiateViewControllerWithIdentifier("identifier of your DetailsViewController")
navigationController?.pushViewController(enrolledView, animated: true)
}
if (indexPath.section == 1){
let appcatalog = self.storyboard?.instantiateViewControllerWithIdentifier("identifier of your AppCatalogViewController")
navigationController?.pushViewController(appcatalog, animated: true)
}
if (indexPath.section == 2){
let support = self.storyboard?.instantiateViewControllerWithIdentifier("identifier of your supportViewController")
navigationController?.pushViewController(support, animated: true)
}
}

Related

Presenting a different view when selecting each Cell in a TableView

I want to present a different view when selecting each Cell in a Table View.
I figured out that I have to use this function:
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
What should I add inside the function to make this work?
First of all, you need didSelectRowAtIndexPath and inside the function you could use indexPath.row to know witch cell was tapped and then you need to create and push the view you want
let viewControllerObj = self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerIdentifier") as? ViewController
self.navigationController?.pushViewController(viewControllerObj!, animated: true)
also, make sure your navigationController is not nil
...hope it helps
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if indexPath.row == 0
{
let objOne = self.storyboard?.instantiateViewControllerWithIdentifier("ID_OneScene") as? OneScene
self.navigationController?.pushViewController(objOne!, animated: true)
}
else if indexPath.row == 1
{
let objTwo = self.storyboard?.instantiateViewControllerWithIdentifier("ID_TwoScene") as? TwoScene
self.navigationController?.pushViewController(objTwo!, animated: true)
}
else
{
let objOther = self.storyboard?.instantiateViewControllerWithIdentifier("ID_OtherScene") as? OtherScene
self.navigationController?.pushViewController(objOther!, animated: true)
}
}

How to assign Two segues on a table cell in SWIFT?

I am totally new at IOS swift and working with android.
Here is my issue :
I'm developing a simple chatting App of IOS. I've already completed android ver and this is a kind of clone.
It has view controllers named VCList, VCMyFriends and VCChat. VCList is my very first view controller and has a table view. Touching a table view cell changes current view controller to VCMyFriends or VCChat.
When I touch a cell, app checks the member counts of the cell, so if it has other members then go to VCChat. If not, VCMyFriends on to invite my friends. Like following pic.
What I found is, I cannot assign two segues on a cell or split a segue with two ways. So I thought that can I change my VC without a segue? However I could not find any references or tutorial about it.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if( memberCnt == 0 ) {
self.presentViewController(VCMyFriends(), animated: true, completion: nil);
} else {
self.presentViewController(VCChat(), animated: true, completion: nil);
}
}
Above is my last try, and failed. It moves somewhere, but shows nothing at all. And if I can, I wish to use segues because have some datas to pass with segue.
Take care.
What I normally do is to create an instance of the controller via the instantiateViewControllerWithIdentifier and set the necessary member variables before calling presentViewController. You can also add a NavigationController if you want the capability the go back to the previous window.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let mainStoryBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if( memberCnt == 0 )
{
let vcMyFriends = mainStoryBoard.instantiateViewControllerWithIdentifier("VCMyFriend") as! VCMyFriends
vcMyFriends.membervar1 = membervar1
vcMyFriends.membervar2 = membervar2
self.presentViewController(vcMyFriends, animated: true, completion: nil)
}
else
{
let vcChat = mainStoryBoard.instantiateViewControllerWithIdentifier("VCChat") as! VCChat
vcChat.membervar1 = membervar1
vcChat.membervar2 = membervar2
self.presentViewController(vcChat, animated: true, completion: nil)
}
}
membervar and membervar2 are the data that you pass to the View Controllers. You need to set it before calling presentViewController so that they will be available when viewDidLoad is called.
Simply do this
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if( memberCnt == 0 ) {
performSegueWithIdentifier("VCMyFriends_segue", sender: self)
} else {
performSegueWithIdentifier("VCChat_segue", sender: self)
}
}
In your storyboard, select the first segue (the red line in your image) and choose Attributes inspector, then add VCMyFriends_segue as identifier.
Do the same thing for the second line (blue) and add VCChat_segue identifier.
Hope this helps

Send info and reload page from another view controller without segue in swift

I have a tableView(top) and a view controller(bottom) within container views in the same view. I need to send info and refresh the bottom view when selecting a table row. I'd like it to work like the apple stocks app. I originally had the bottom view on another page and used a segue and it worked great. But I'm not sure how to do it without a segue now.
Here is the code for selecting the row:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
let item = items[indexPath.row]
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
What I had before for the segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let controller = segue.destinationViewController as SNPDetailViewController
if let indexPath = tableView.indexPathForCell(sender as UITableViewCell) {
controller.itemToEdit = items[indexPath.row]
}
}
And what was working when I used the segue in the (now) bottom view:
override func viewDidLoad() {
super.viewDidLoad()
if let item = itemToEdit {
title = item.name
snpDetails.text = item.details
}
}
Any help is greatly appreciated!
In your table view controller, self.parentViewController will point to the container view controller. Then you can get a reference to the existing detail view controller via the childViewControllers property of the container:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
let item = items[indexPath.row]
if let vc = self.parentViewController {
let siblings = vc.childViewControllers
if siblings.count > 1 {
if let detailVC = siblings[1] as? SNPDetailViewController {
detailVC.itemToEdit = item
} else {
println("Odd, that detail view controller is not the right class")
abort()
}
} else {
println("Odd, there is no detail view controller")
abort()
}
} else {
println("Strange, I'm not embedded in a parent view controller")
abort()
}
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
This assumes your table view controller is at index 0 of childViewControllers, and the detail view controller is at index 1. Amend siblings[1] to siblings[0] if it's the other way around.
You may need to implement a setter method for itemToEdit in order to reload the labels etc when the value changes.
I guess your bottom view is SNPDetailViewController
As you can see in your previous code you had a variable called controller. That variable is missing in your actual code. Try to create it in your first snippet of code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
let item = items[indexPath.row]
}
let controller = SNPDetailViewController()
// then you can call the _itemToEdit_ method in your other view
if let indexPath = tableView.indexPathForCell(sender as UITableViewCell) {
controller.itemToEdit = items[indexPath.row]
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
I'm not completely sure if that works but the idea is that you need like an instance of your bottom view to access its methods. Let me know if that helps.

how to programmatically deselect a static cell iOS

I have a static cell and when clicked it launches a modal view. Except when i return from the modal view the cell is still selected? Why is it doing this and how can I make it only make the cell selected until the modal completely covers the view.
Thanks in advance
For Swift 2 :
override func viewWillAppear(animated: Bool) {
if let indexPath = self.tableView.indexPathForSelectedRow {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
For Swift 3 and 4 :
override func viewWillAppear(animated: Bool) {
if let indexPath = self.tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: true)
}
}
If you use a UITableViewController instead of a UIViewController this will be done automatically. Otherwise, you need to do the deselecting yourself using
deselectRowAtIndexPath:animated: on the UITableView. The best place to do this is probably on viewDidAppear: of the presenting view controller. That way, the user still sees the deselecting animation allowing them to reorient themselves.
If you don't need to track the selected row for other purposes, you can use
indexPathForSelectedRow to determine which index path needs to be deselected (if any).
I know this is too late but may help someone who's using Swift -
This will give a nice effect when you return to masterViewController from detailViewController
override func viewWillAppear(animated: Bool)
{
if let indexPath = self.tableView.indexPathForSelectedRow
{
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
Otherwise add this delegate method of TableView and call it from didSelectRowAtIndexPath
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
if let indexPath = tableView.indexPathForSelectedRow
{
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
You can use this in your UITableViewController;
- (void)viewWillAppear:(BOOL)animated
{
[yourTableView deselectRowAtIndexPath:[yourTableView indexPathForSelectedRow] animated:YES];
}
In your condition, yourTableView property should be self.tableView
swift 3
override func viewWillAppear(animated: Bool) {
tableView.deselectRow(at: tableView.indexPathForSelectedRow!, animated: true)
}

Why does UITableViewCell remain highlighted?

What would cause a table view cell to remain highlighted after being touched? I click the cell and can see it stays highlighted as a detail view is pushed. Once the detail view is popped, the cell is still highlighted.
In your didSelectRowAtIndexPath you need to call deselectRowAtIndexPath to deselect the cell.
So whatever else you are doing in didSelectRowAtIndexPath you just have it call deselectRowAtIndexPath as well.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Do some stuff when the row is selected
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
The most clean way to do it is on viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Unselect the selected row if any
NSIndexPath* selection = [self.tableView indexPathForSelectedRow];
if (selection) {
[self.tableView deselectRowAtIndexPath:selection animated:YES];
}
}
This way you have the animation of fading out the selection when you return to the controller, as it should be.
Taken from http://forums.macrumors.com/showthread.php?t=577677
Swift version
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// deselect the selected row if any
let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
if let selectedRowNotNill = selectedRow {
tableView.deselectRow(at: selectedRowNotNill, animated: true)
}
}
For the Swift users, add this to your code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
It's paulthenerd's answer but in Swift instead of Obj-C.
Did you subclass -(void)viewWillAppear:(BOOL)animated? The selected UITableViewCell won't deselect when you don't call [super viewWillAppear:animated]; in your custom method.
Swift 3 Solution
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
If you are using a UITableViewCell, then comment the following line
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
// [super setSelected:selected animated:animated];
}
Hope this helps.
Updated with Swift 4
After few experiments, also based of previous answers, I've got the conclusion that the best behaviour can be achieved in 2 ways: (almost identical in practice)
// First Solution: delegate of the table View
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
}
// Second Solution: With the life cycle of the view.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
if let selectedRow = selectedRow {
tableView.deselectRow(at: selectedRow, animated: false)
}
}
I'm personally adopting the first solution, because it's simply more concise. Another possibility, if you need a little animation when you return to your tableView, is to use viewWillAppear:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let selectedRow: IndexPath? = _view.tableView.indexPathForSelectedRow
if let selectedRow = selectedRow {
_view.tableView.deselectRow(at: selectedRow, animated: true)
}
}
Last but not least, if you're using a UITableViewController, you can also take advantage of the property clearsSelectionOnViewWillAppear.
To get the behaviour Kendall Helmstetter Gelner describes in his comment, you likely don't want deselectRowAtIndexPath but rather the clearsSelectionOnViewWillAppear property on your controller. Perhaps this was set to YES by accident?
See the comment in the default Apple template for new UITableViewController subclasses:
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
}
Swift 5 Solution:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
I was getting this problem as well for my drill-down application. After a viewcontroller, which I'll call VC, returns after pushing another ViewController, the selected cell in VC remained highlighted. In my app, I had created VC to handle the second level (out of three levels) of my drill-down.
The problem in my case is that VC was a UIViewController (that contained a View that contained a TableView). I instead made VC a UITableViewController (that contained a TableView). The UITableViewController class automatically handles the de-highlighting of the table cell after returning from a push. The second answer to the post "Issue with deselectRowAtIndexPath in tableView" gives a more complete answer to this problem.
The problem did not occur for the root viewcontroller because when I created the app as a "Navigation-based App" in XCode, the resulting root viewcontroller was already made to subclass UITableViewController.
If none of these work for you, consider this work-around:
Use an unwind segue to call:
#IBAction func unwind_ToTableVC (segue: UIStoryboardSegue) {
if let index = tableView.indexPathForSelectedRow {
tableView.deselectRowAtIndexPath(index, animated: true)
}
}
Why do this? Primarily if you're having trouble getting the deselect code to run at the right time. I had trouble with it not working on the viewWillAppear so the unwind worked a lot better.
Steps:
Write the unwind segue (or paste from above) into your 1st VC (the one with the table)
Go to the 2nd VC. Control-drag from the Cancel/Done/Etc button you're using to dismiss that VC and drag to the Exit Icon at the top.
Select the unwind segue you created in step 1
Good luck.
I am using CoreData so the code that worked for me was a combination of ideas from various answers, in Swift:
override func viewDidAppear(_ animated: Bool) {
if let testSelected = yourTable.indexPathForSelectedRow {
yourTable.deselectRow(at: testSelected, animated: true)
}
super.viewDidAppear(true)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
I've been having the same issue for long time so in case anyone else is struggling:
Take a look at your -tableView: cellForRowAtIndexPath: and see if you are creating cells or using a 'reuse identifier'. If the latter, make sure that your table in IB has a cell with that identifier. If you're not using a reuse Identifier just create a new cell for each row.
This should then give your table the expected 'fade selected row' on appearing.
Use this method in UITableViewCell class
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
// Just comment This line of code
// [super setSelected:selected animated:animated];
}
For Swift 3:
I would prefer it to use in viewDidDisappear
Define:-
var selectedIndexPath = IndexPath()
In viewDidDisappear:-
override func viewDidDisappear(_ animated: Bool) {
yourTableView.deselectRow(at: selectedIndexPath, animated: true)
}
In didSelectRowAtIndexPath:-
func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
selectedIndexPath = indexPath
}
if the cell is remaining highlighted after touching it, you can call UITabelView method,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
`[tableView deselectRowAtIndexPath:indexPath animated:YES];`
}
Or, you can use the following method and modify it according to your requirements,
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.backgroundColor = UIColor.greenColor()
}
}
func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.backgroundColor = UIColor.blackColor()
}
}
Xcode 10, Swift 4
I had this same issue and discovered I left an empty call to viewWillAppear at the bottom of my tableViewController. Once I removed the empty override function the row no longer stayed highlighted upon return to the tableView view.
problem func
override func viewWillAppear(_ animated: Bool) {
// need to remove this function if not being used.
}
removing empty function solved my problem.

Resources