didSelectRowAtIndexPath index path with uisearchcontroller - ios

I have an application when the user clicks on a cell it will open another viewController and I just add a uisearchcontroller on my tableview.
When I am searching on the tableview the result is correct ,
but when I click on the cell after filtering , it opens the wrong page.
My problem is I don't now how to identify the indexpath when the uiviewcontroller is active to make the result open correct page
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
IndexPathRow = indexPath.row
performSegueWithIdentifier("toView2", sender: self)
}
Edit
I solved my problem by adding new variable in the struct of type integer and then modify didSelectRowAtIndexPath function to
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if resultSearchController.active && resultSearchController.searchBar.text != ""{
IndexPathRow = filteredData[indexPath.row].i
}
else {
IndexPathRow = indexPath.row
}
performSegueWithIdentifier("toView2", sender: self)
}

A better way to get the selected item, is to call indexPathForSelectedRow() method inside of the segue delegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("toView2", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toView2" {
let indexPath = self.tableView.indexPathForSelectedRow() {
print("IndexPathRow = \(indexPath.row)")
//destination controller code goes here ...
}
}
}

You are getting the data with your main array, try to get the data with the searched array, then only its correct, check for searchController.isActive() on all the method related to the main array, basically check for this in your prepareForSegue

Related

Passing data from tableviewcell to another viewcontroller

I am trying to pass cell's tag data to another viewcontroller's variable
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!
print(currentCell.tag)
valueToPass = currentCell.tag
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let Dest = segue.destinationViewController as! EventDetail
if (segue.identifier == "eDetay") {
Dest.eventid = String(valueToPass)
}
}
When i try as it is, valueToPass is always passed the previous data.
Is there a way to get selected cell data from prepareForSegue ?
What is the best way to do that?
You are overriding the indexPath parameter that is being passed to you.
Remove the first let statement. Use the indexPath that is being passed to you.
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!)
{
let cell = tableView.cellForRowAtIndexPath(indexPath) as YourCell
//cell.value, cell.text, cell.randomValue or whatever you need
}

array index out of bounds when UITableViewCell tapped, with and without a didselectrowatindex method

Like Title
More information - I am populating my view controller with
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "showCalendars" {
// Setup new view controller
print("happening")
let vc = segue.destinationViewController as! CalendarSelectionViewController
for item in self.approvedCalendars {
vc.sentCalendars.append(item)
}
vc.tableView.reloadData()
vc.calendarDelegate = self
}
}
and my view controller code looks like :
import UIKit
import EventKit
class CalendarSelectionViewController: UITableViewController {
var sentCalendars: [EKCalendar]! = []
var calendarDelegate: selectCalendarDelegate?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "My Calendars"
//tableView.tableFooterView = UIView()
tableView.reloadData()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sentCalendars.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("calendarCell", forIndexPath: indexPath)
cell.textLabel?.text = sentCalendars[indexPath.row].title
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
whenever i click on any uitableview cell, my application crashes and I receive "fatal error: Array index out of range".
I've tried printing out the indexPath.row in the didSelectRowAtIndexPath method and it prints the correct index, so why is this crashing? Is there a memory leak somewhere and the tableview is not showing the proper information? Thanks for your help.
Investigated my storyboard, I had an unwind segue that wasn't being used and was causing a fatal error: array index out of bounds. Thanks for the help!

Is there something like prepareForSegue when going back with UINavigationController?

I have an array in my ViewOne, which I pass to ViewTwo with the prepareForSegue function.
When I delete data of my array in ViewTwo and go back with the back button on the NavigationController or by swiping to right, the array in ViewOne has still all the data and don't know that I deleted something of it.
Is there any solution for this problem?
ViewOne:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "submitSegue") {
let shoppingCart = segue.destinationViewController as! ShoppinCartScreen;
if(artikel != nil) {
shoppingCart.alleArtikel = alleArtikel
print("Test: \(artikel?.artikelnummer)")
}
}
}
ViewTwo:
var alleArtikel = [Artikel]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return alleArtikel.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ShoppingCartScreenCell", forIndexPath: indexPath) as!ShoppingCartScreenCell
let eintrag = alleArtikel[indexPath.row]
cell.previewImage.image = eintrag.foto
cell.artikelNummer.text = eintrag.artikelnummer
return cell
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if(editingStyle == .Delete) {
alleArtikel.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
I have a main View (ViewOne) and a TableView(ViewTwo).
In Swift, arrays are value types not reference types (see Apple Developer Blog entry), so when you 'pass' it to view2 you are really just making a copy. View2 modifies the copy but the original remains unchanged.
Instead of using a prepareForSegue method when going back, which to my knowledge is not possible, just run the viewWillDisappear function. Basically this is the viewDidLoad function for when the view disappears. It will run when you are performing a segue when you are leaving the view.
example:
override func viewWillDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
print("the view is hidden")
}

Directing to a different ViewController depending on tableView cell clicked

I am trying to present a viewController depending on which tableView cell is clicked.
Currently if they are all clicked they redirect to the same viewController, how would I alter this?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
cell.cellLabel.text = self.objects.objectAtIndex(indexPath.row) as! String
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("other", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "other"){
var upcoming: otherViewController = segue.destinationViewController as! otherViewController
let indexPath = self.tableView.indexPathForSelectedRow!
let titleString = self.objects.objectAtIndex(indexPath.row) as! String
upcoming.titleString = titleString
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
Could I do an if else on the cellLabel.text? as in if (cellLabel.text == "option8"){
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("option8", sender: self)
}
}
I am using Swift and xcode7.
Don't and never do comparision with cellLabel.text, consider using indexPath.row for that. Then adding different segues in your storyboard for each view controller you need. Code will be something like that:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 || indexPath.row == 2{
self.performSegueWithIdentifier("other", sender: self)
}
else{
self.performSegueWithIdentifier("other", sender: self)
}
}
Yes, you can.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if cell.cellLabel.text == "option8" {
self.performSegueWithIdentifier("other8", sender: self)
}
}
You can check indexpath.row in didSelectrow according to row no you can redirect to perticular controller.

Nil data is passed from tableview detail disclosure with prepareForSegue

I need to pass a string with prepareForSegue from a tableView disclosure link. Here is the prepareForSegue code I use. This is the code I found in several cases when other users needed to do the same thing, but in my case it doesn't work. Problem is with indexPathForSelectedRow() that is nil:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "alertsDetail" {
let detailAlertViewController = segue.destinationViewController as DetailAlertViewController
println(alertTable.indexPathForSelectedRow()) // NIL
if let indexPath = alertTable.indexPathForSelectedRow() {
let entryToPass = unpublishedPhotosObjectId[indexPath.row]
detailAlertViewController.entryId = entryToPass
}
}
}
I named the tableView "alertTable" and not self because the tableview is not a view controller, just a view.
In case needed, here is tableview code:
#IBOutlet weak var alertTable: UITableView!
/////////////TableView - START
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return unpublishedPhotos.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 170
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
tableView.separatorColor = UIColor.clearColor()
let cell = tableView.dequeueReusableCellWithIdentifier("adminAlertsCell") as? adminAlertsCell
var data = unpublishedPhotos[indexPath.row].getData()
let image = UIImage(data: data)
cell!.myImageInCell.image = image
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// Add access to cell
let cell = tableView.cellForRowAtIndexPath(indexPath) as? adminAlertsCell
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
println(cell!.banSwitch.on)
}
}
/////////////TableView - END
You should make the segue from the controller instead of directly from the detail disclosure button. Implement the method,
tableView:accessoryButtonTappedForRowWithIndexPath: and call performSegueWithIdentifier:sender: from inside that method. Pass the in-depth as the sender argument so you have access to that in prepareForSegue,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
let indexPath = sender as NSIndexPath
if segue.identifier == "alertsDetail" {
let detailAlertViewController = segue.destinationViewController as DetailAlertViewController
let entryToPass = unpublishedPhotosObjectId[indexPath.row]
detailAlertViewController.entryId = entryToPass
}
}
Your issue is stated in the comments to your question, and there are several solutions. Perhaps the quickest since you only have one section, is to assign the indexPath.row to the tag of the cell. Then in your prepare for segue, the sender will be your cell. You can get the value out of it. So in your cellForRow method before your return your cell:
cell!.tag = indexPath.row
Then in your prepareForSegue:
let cell = sender as? adminAlertsCell
println(cell!.tag)
Here I am just printing it, but you can use it to pass the row.

Resources