Why indexPath.row doesn't work here? - ios

I am adding values from the first TableView var savedUrls to the first section of var detailsInSection in second TableView. In prepareForSegue, Xcode shows " unresolved Identifier for 'indexPath'. How should I revise the codes?
In first View Controller:
var folderNames = [String]()
var savedUrls = [String]()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let url = savedUrls[indexPath.row]
self.performSegueWithIdentifier(segueToDetailsTable, sender: url)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == segueToDetailsTable {
let detailsVC = segue.destinationViewController as! DetailsViewController
detailsVC.detailsInSection[0].append(savedUrls[indexPath.row])
}
}
In Second View Controller:
var sectionTitles = ["WebSite", "Date Saved", "Document Used","Add Notes"]
var detailsInSection = [[String]() , [NSDate]() , [AnyObject]() , String]() ]

indexPath is not a variable defined or passed into prepareForSegue. You are on the right track though. Since you pass the url as the sender in performSegue..., you don't need an indexPath to reference the url. You can check that the sender was a String and use sender as the url that was selected.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let url = savedUrls[indexPath.row]
self.performSegueWithIdentifier(segueToDetailsTable, sender: url)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let url = sender as? String where segue.identifier == segueToDetailsTable {
let detailsVC = segue.destinationViewController as! DetailsViewController
detailsVC.detailsInSection[0].append(url)
}
}

Pass the index path in didSelectRow... as sender parameter and get the url later
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier(segueToDetailsTable, sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == segueToDetailsTable {
let indexPath = sender as! NSIndexPath
let url = savedUrls[indexPath.row]
let detailsVC = segue.destinationViewController as! DetailsViewController
detailsVC.detailsInSection[0].append(url)
}
}

Related

Swift 4.2 - How to call "indexPath.row" from "didSelectRowAtIndexPath" method in a tableView to another class?

I have two viewControllers. One has a tableView which has some cells from an array; And the other is a viewController which contains a webkit that I want to present some local HTML files. Also I defined the webKit page as tableView's next page.
What I want is, when a user chooses a cell in the tableView, according to which cell is selected, it goes to webkit Page, and some parts of codes runs for user to show a specific HTML. In other words, I have 5 HTML files and 5 items in tableViewCells
so if a user chooses for example the first item, the HTML1 shows to him, if he chooses the second cell, the HTML2 present for him etc.
I tried a lot of ways. but nothing happened. also tried to create instance object from the tableview class...
tried also some same problem here ins StackOverFlow but not succeed
First Page:
var arr = ["masoud" , "hossein", "reza" , "shiva" , "fateme"]
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("item selected is : \(indexPath.row)")
// if indexPath.row == 1 {
performSegue(withIdentifier: "TableSegue", sender: nil)
//}
tableView.deselectRow(at: indexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination.view, segue.destination, sender) {
case let (_, controller as WebKitController, indexPath as NSIndexPath):
controller.indexPath = indexPath
break
default:
break
}
}
the Second Page:
import WebKit
class WebKitController: UIViewController, WKUIDelegate, WKNavigationDelegate {
#IBOutlet weak var myWebKit: WKWebView!
var reza : String = String()
var indexPath: NSIndexPath? {
didSet {
reza = (indexPath?.row.description)!
print(indexPath?.row as Any)
self.myWebKit.uiDelegate = self
self.myWebKit.navigationDelegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "reza", withExtension: "html", subdirectory: "ReZeynoo2")!
myWebKit.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
myWebKit.load(request)
self.myWebKit.uiDelegate = self
self.myWebKit.navigationDelegate = self
}
As an alternative approach
I would store not a simple array but struct of name and bool is selected or not
struct CellData {
let name: String!
let isSelected: Bool!
let index: Int!
init(name: String, isSelected: Bool, index: Int) {
self.name = name
self.isSelected = isSelected
self.index = index
}
}
Then in didSelectAtRow func will make selected the cell which tapped and use this info in prepare for segue func
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.deselectAll()
self.cellItems[indexPath.row].isSelected = true
performSegue(withIdentifier: "TableSegue", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination.view, segue.destination, sender) {
case let (_, controller as WebKitController, indexPath as NSIndexPath):
if let item = cellItems.first(where: {$0.isSelected == true}) {
controller.indexPath = item.index
}
break
default:
break
}
}
private func deselectAll() {
for item in cellItems {
item.isSelected = false
}
}
You need to create a Int variable in WebKitController class as selectedRow where the selected row will get assigned from table view cell selection,
// MARK: - Table view delegates
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "TableSegue", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TableSegue", let indexPath = sender as? IndexPath {
let webController = segue.destination as? WebKitController
webController.selectedRow = indexPath.row
}
}
I think you can pass your indexpath.row value in sender of your perfomSegue and your second view controller just use this
here is code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "secondvc", sender: indexPath.row)
}
just send indexpath.row value in sender
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "secondvc"{
let vc = segue.destination as! SecondViewController
vc.row = sender as! Int
}
}

Passing data from table view controller to view controller

I'm having issues with moving from a table view controller to a view controller to display information about a particular cell that was selected.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SentDetailView" {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow! as NSIndexPath
let referrals = referralsSent[indexPath.row]
let destViewController = segue.destination as! SentDetailViewController
destViewController.referringTo = referrals.referTo
destViewController.patientsName = referrals.patientsName
//print("Contained value during segue " + destViewController.patientsName!)
destViewController.patientsPhoneNumber = referrals.patientsNumber
destViewController.patientsEmail = referrals.patientsEmail
destViewController.comments = referrals.comment
}
}
Storyboard setup:
I get the following results:
I select a cell and it just highlights and doesn't do anything.
You should override didSelectRowAt and call performSegue with sender as the selected index path. Try this.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "SentDetailView", sender: indexPath)
}
And this.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SentDetailView"{
let indexPath = sender as! IndexPath
let referrals = referralsSent[indexPath.row]
let destViewController = segue.destination as! SentDetailViewController
destViewController.referringTo = referrals.referTo
destViewController.patientsName = referrals.patientsName
//print("Contained value during segue " + destViewController.patientsName!)
destViewController.patientsPhoneNumber = referrals.patientsNumber
destViewController.patientsEmail = referrals.patientsEmail
destViewController.comments = referrals.comment
}
}

UICollectionView prepareForSegue indexPathForCell is nil iOS 9

The problem is this line return nil:
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell)
For that reason I can't pass any information, The identifier is set and the delegate is set.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell) {
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[indexPath.row]
}
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: collectionView.cellForItemAtIndexPath(indexPath))
}
Any help?
The problem is how to try to get the cell back. You must pass the cell in the performSegueWithIdentifier and then recover it in prepareForSegue.
Here is the code:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: collectionView.cellForItemAtIndexPath(indexPath))
}
And then
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
if let cell = sender as? UICollectionViewCell{
let indexPath = self.collectionView!.indexPathForCell(cell)
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[indexPath.row]
}
}
}
Hope it helps!
Try Like this..
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("DetalleSegueIdentifier", sender: indexPath)
}
and get your indexpath like this...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetalleSegueIdentifier" {
let aIndPath = sender as! NSIndexPath
let detailVC = segue.destinationViewController as! DetalleNoticiaViewController
detailVC.contact = self.noticia[aIndPath.item]
}
}
The problem is the var collectionView is not reference in my ViewController for that reason always return nil. My mistake thanks you for your answers.
#IBOutlet weak var collectionView: UICollectionView!

Swift didSelectRowAtIndexPath and prepareForSegue

I need to add a value to the selected row than in prepareForSegue that it does its action.But my prepareForSegue is doing the action before it.When i try to place the "performSegueWithIdentifier" it crashes,also i have added the id to the segue idenfifier in the storyboard.Im working with sqlite.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "editSegue")
{
let viewController : WorkoutView = segue.destinationViewController as! WorkoutView
viewController.workoutInfoData = marrStudentData.objectAtIndex(selectedRow) as! WorkoutInfo
navigationItem.title = ""
}
}
You can fetch the selected indexPaths from tableView in your prepare for segue
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "editSegue")
{
if let indexPath = tableView.indexPathForSelectedRow{
let viewController : WorkoutView = segue.destinationViewController as! WorkoutView
viewController.workoutInfoData = marrStudentData.objectAtIndex(indexPath.row) as! WorkoutInfo
navigationItem.title = ""
}
}
}

Refresh same view controller with new data?

I have a song page with recommended songs in a table view. When a user clicks on a recommended song, I want to essentially reload the song page with the new data. To do that, I'm using this method, with a segue from the cell to its own view controller:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let newSong = recommendedTitles[indexPath.row]
self.performSegueWithIdentifier("refreshSong", sender: newSong)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let newSong:String = sender as! String
let song = segue.destinationViewController as! SongViewController
song.search = newSong
}
}
But I'm getting an error at let newSong:String = sender as! String, that it could not cast value of type recommendationCell to NSString. Is the best way to do all of this with the aforementioned tableView methods?
You do not have to declare global variable.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("refreshSong", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let indexPath = tableView.indexPathForSelectedRow()
let song = segue.destinationViewController as! SongViewController
song.search = recommendedTitles[(indexPath?.row)!]
}
}
you try this. Take the variable newSong in declaration section
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
newSong = recommendedTitles[indexPath.row]
self.performSegueWithIdentifier("refreshSong", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "refreshSong" {
let song = segue.destinationViewController as! SongViewController
song.search = newSong
}
}

Resources