Error within tableView when swapping detailView for a different view - swift

I have the function
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let indexPath = tableView.indexPathForSelectedRow {
let object = dailyAgenda[indexPath.row]
if object == "Time Management" {
self.performSegue(withIdentifier: "showTimeManagement", sender: self)
}
else {
self.performSegue(withIdentifier: "showDetail", sender: self)
}}}
And the prepare for segue function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let object = dailyAgenda[indexPath.row]
var controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.textDescription = indepthDescript[indexPath.row]
}}
if segue.identifier == "showTimeManagement" {
var controller = (segue.destination as! UINavigationController).topViewController as! TimeManagement
}
}
But I keep getting the error "Thread 1: Fatal error: Index out of range" when selecting the cell that performs the showTimeManagement segue. The error occurs on the "controller.textDescription = indepthDescript[indexPath.row]]" line within the showDetail segue. Why would it even be running this line in the first place and where am I going wrong?

Related

assign the selected indexpath.row to a variable in another class

I show the data in labelTEx in the table.
When I click labelTEx, I open another table class.
I want to transfer the text data of labelTExt that I clicked in UITableViewCell to formBaslik in DetayViewController.
that is, I want to transfer the gifsabaslik [indexPath.row] that I have selected to the detayBaslik in DetayViewController. How can I do that?
DetayViewController
class DetayViewController: UIViewController {
var formBaslik = String()
}
TableViewController
class TableViewController: UIViewController{
var gifsayeniresim: [String] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! TableViewCell
cell.labelTExt.text = self.gifsabaslik[indexPath.row]
cell.labelTExt.textColor = UIColor.white
cell.labelTExt.font = UIFont(name: "HelveticaNeue", size: 14.0)!
cell.labelTExt.backgroundColor = UIColor.lightGray
cell.labelLayout.constant = cell.labelTExt.contentSize.height
cell.labelTExt.isEditable = false
let tap = UITapGestureRecognizer(target: self,action: #selector(handleTaponTextField(_:)))
tap.numberOfTapsRequired = 1
tap.delegate = self
cell.labelTExt.isUserInteractionEnabled = true
cell.labelTExt.addGestureRecognizer(tap)
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "newo"{
if segue.destination is DetayViewController {
}
}
#SH Yasilm
In DetayViewController, declare
var formBaslik = String?
In TableViewController, in prepare, write
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "newo" {
if let cell = sender as? UITableViewCell {
// You have clicked in a cell, but that may not have selected it: let's compute its indePath
let tapPosition:CGPoint = cell.convert(CGPoint.zero, to: self.table)
let indexPath = self.table.indexPathForRow(at: tapPosition)
if let vc = segue.destination as? DetayViewController {
vc.formBaslik = gifsabaslik[indexPath.row]
}
}
}
You can retrieve the indexPath by following the code below.
In the DetayViewController's very top (below class)
var myStr: String!
Inside the class where you have the tableview
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "newo"{
if segue.destination is DetayViewController {
let vc = segue.destination as? DetayViewController
let indexPath = self.tableView.indexPathForSelectedRow
let cell = tableView.cellForRow(at: indexPath!) as! YourCellClassName
vc.myStr = cell.yourString
//NOTE! If. the cell is a string just do like I did, other way, if that's a textfield/label you should use cell.yourLabel.text
}
}

How to append string to tableview from separate ViewController using alert

I'm trying to append string using an alert in createPlaylistVC to a tableView in another ViewController createdPlaylistVC.
I've looked up this answer and it didn't do much for me
add a row to the tableView from another viewController
CreatePlaylistVC
var crdPlaylistVC = CreatedPlaylistVC()
alert.addAction(UIAlertAction(title:"OK", style:.default, handler: {
action in
if let playlistName = alert.textFields?.first?.text {
self.crdPlaylistVC.emptyArray.append("Your playlist: \(playlistName)")
let indexPath = IndexPath(row: self.crdPlaylistVC.emptyArray.count - 1, section: 0)
self.crdPlaylistVC.tableView?.beginUpdates()
self.crdPlaylistVC.tableView?.insertRows(at: [indexPath], with: .automatic)
self.crdPlaylistVC.tableView?.endUpdates()
self.crdPlaylistVC.tableView?.reloadData()
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let SEC: CreatedPlaylistVC = segue.destination as! CreatedPlaylistVC
SEC.emptyArray.append("Your playlist: \(playlistName)")
self.crdPlaylistVC.tableView.reloadData()
}
CreatedPlaylistVC
class CreatedPlaylistVC:UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var emptyArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "playlistCell", for: indexPath) as! UITableViewCell
cell.textLabel?.text = emptyArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return emptyArray.count
}
}
The code cannot work. createdPlaylistVC() is never the instance in the storyboard.
You have to call performSegue in the action and pass the string as sender. And prepare for must be on the top level of the class
var crdPlaylistVC = createdPlaylistVC()
alert.addAction(UIAlertAction(title:"OK", style:.default) { [weak self] action in
if let playlistName = alert.textFields?.first?.text {
self?.performSegue(withIdentifier: "MyIdentifier" sender: playlistName)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "MyIdentifier" else { return }
let playlistName = sender as! String
let sec = segue.destination as! createdPlaylistVC
sec.emptyArray.append("Your playlist: \(playlistName)")
}
You have to reload the table view in createdPlaylistVC because the table view might be not connected yet.
And please conform to the naming convention that class names start with an uppercase letter and variable names start with a lowercase letter.

Prepareforsegue not passing the appropriate value to destination Viewcontroller?

I have two viewcontrollers (one is tableVC) that I would like to pass information between. Here is code from that tableVC:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var rowSelected = indexPath.row
print(rowSelected) //always returns the correct integer
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destViewController: newController = segue.destination as! newController
newController.rowSelected = rowSelected
}
performSegue(withIdentifier: "rowSelected", sender: Any?.self)//segue to newController
}
And here is the code for the newController that I want the info to be passed to:
#IBOutlet weak var label: UILabel!
var rowSelected = Int()
override func viewDidLoad() {
super.viewDidLoad()
label.text = infoArray[rowSelected]
print(rowSelected) //always logs 0 to the console, regardless of cell selection
}
I thought I had set this up appropriately, but for whatever reason the index called to the infoArray is always 0, no matter what cell is selected in the tableVC. Not sure what the problem is.
write prepareForSegue in class scope/global scope. in your code prepareForSegue will never call because you are writing this inside the method. pass rowSelected in performSegue and get rowSelected value in prepareForSegue using sender or you can use indexPathForSelectedRow property of tableView.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
...
performSegue(withIdentifier: "rowSelected", sender: rowSelected)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: Any?) {
let rowSelected = sender as! Int
// or you can use indexPathForSelectedRow for getting row value
// let indexPath = self.tableView.indexPathForSelectedRow?
// let rowSelected = indexPath!.row
let destViewController: newController = segue.destination as! newController
newController.rowSelected = rowSelected
}
Need to use override in your function when you prepareForSegue
See below example code : -
Swift 3
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowAttractionDetails" {
let detailViewController = segue.destination
as! AttractionDetailViewController
let myIndexPath = self.tableView.indexPathForSelectedRow!
let row = myIndexPath.row
detailViewController.webSite = webAddresses[row]
}
}
Swift 2.3
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowAttractionDetails" {
let detailViewController = segue.destination
as! AttractionDetailViewController
let myIndexPath = self.tableView.indexPathForSelectedRow!
let row = myIndexPath.row
detailViewController.webSite = webAddresses[row]
}
}
Source - Segue from UITableViewCell Taps in Swift & TableView Navigation using Storyboards in Xcode 8

custom cell segue using button swift

I have created custom cell with button inside. Now I am trying to pass a data via pressing on this button, but cant catch indexPath, need your help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier=="editData"){
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = (segue.destinationViewController as! AddDetail)
destinationController.info = data[indexPath.row]
let nItem : Dealers = data [indexPath.row]
destinationController.nItem = nItem
also Im trying do the same but from swiping menu:
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?{
let edit = UITableViewRowAction(style: .Normal, title: "Edit") { (action, indexPath) in
self.performSegueWithIdentifier("addDealer", sender: self)
let name = self.data [indexPath.row].dealerName
print(name)
}
edit.backgroundColor = UIColor.lightGrayColor()
return [delete, edit]
is it possible pass segue from swiping menu?
You can pass indexPath as the sender in performSegueWithIdentifier.
self.performSegueWithIdentifier("addDealer", sender: indexPath)
then
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let indexPath = sender as? NSIndexPath {
// then here you know what the indexPath was
// and can do whatever you want with it
}
...
Try using tableView.indexPathForCell(selectedCell) instead of tableView.indexPathForSelectedRow; you first extract selectedCell as your custom table view cell (YourCustomTableViewCell below):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "editData" {
let destinationController = segue.destinationViewController as! AddDetail
if let selectedCell = sender as? YourCustomTableViewCell {
let indexPath = tableView.indexPathForCell(selectedCell)!
destinationController.info = data[indexPath.row]
let nItem : Dealers = data[indexPath.row]
destinationController.nItem = nItem
}
}
}
As for the swiping question: I'll get back answer to this.

swift passing data from a tableview cell to view controller

I'm trying to pass some data to a separate view controller, the view controller is connected to a navigation controller, i can get to this view controller using
parentNavigationController!.performSegueWithIdentifier("ExercisePage", sender: self)
but the data isn't passed along, here is my code?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell2 = tableView.cellForRowAtIndexPath(indexPath) as! SelectionProperties
let desVc = uploadDetails1()
desVc.workoutName = cell2.nameLabel!
desVc.parentNavigationController!.performSegueWithIdentifier("ExercisePage", sender: self)
}
It says it found nil while unwrapping an optional.
desVc.performSegueWithIdentifier("ExercisePage", sender: self) }
if i do this,it says theres no segue
Try this: (You don't have to use all if statements...)
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("ExercisePage", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
// Get the new view controller using segue.destinationViewController.
if segue.identifier == "ExercisePage"
{
guard let indexPath = sender as? NSIndexPath else {
return } 
guard let destinationViewController = segue.destinationViewController as? uploadDetails1 else {
return } 
guard let cell = tableView.cellForRowAtIndexPath(indexPath) else {
return } 
guard let _ = cell.nameLabel else { 
return } 
destinationViewController.workoutName = cell.nameLabel!
}
}