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
}
}
Related
I have a table view with the following willSelectRowAt code:
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
for n in 0...carsArray.count - 1 {
if indexPath.row == n {
print(carsArray[n].name)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let name = carsArray[n].name
print(name)
let indexCar = n
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = name
destinationVC.indexCar = indexCar
}
}
performSegue(withIdentifier: "goToEditCar", sender: self)
}
}
}
Somehow the prepare function won't pass the desired data, neither will it print(name) - can anyone tell me the issue with this piece of code?
Your code cannot work at all. You are using the wrong API, prepare(for is never going to be called inside another method and actually you don't need a loop.
willSelectRowAt is to control if a cell is allowed to be selected. Return the indexPath if it's allowed otherwise return nil
This is not what you want. Use didSelect and pass the index path as sender when calling performSegue
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToEditCar", sender: indexPath)
}
In prepare(for get the index path from the sender parameter
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let indexPath = sender as! IndexPath
let name = carsArray[indexPath.row].name
print(name)
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = name
destinationVC.indexCar = indexPath.row
}
}
You don't need a for-loop here as n eventually will be equal to indexPath.row also you should use didSelectRowAt
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToEditCar", sender:indexPath.row)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let index = sender as! Int
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = carsArray[index].name
destinationVC.indexCar = index
}
}
I have the following class I am segueing to.
class FriendsProfileViewController: UIViewController {
var user : User!
override func viewDidLoad() {
super.viewDidLoad()
print(user.firstName)
}
}
On the segueing class I did the following to pass the data
var friends: [User]?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("viewFriend", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationVC = segue.destinationViewController
if let friendsProfileVC = destinationVC as? FriendsProfileViewController{
if let indexPath = sender as? NSIndexPath{
print(indexPath.row)
friendsProfileVC.user = friends?[indexPath.row]
}
}
}
Why is it that I am getting the error
fatal error: unexpectedly found nil while unwrapping an Optional value
even though my friend?[indexPath.row] is verified to contain a value when I segue?.
Try getting the user before performing the segue and pass it as the segue sender.
var friends: [User]?
private func friend(at index: Int) -> User? {
return friends.flatMap { $0.indicies.contains(index) ? $0[index] : nil }
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let friend = friend(at: indexPath.row) {
performSegueWithIdentifier("viewFriend", sender: friend)
} else {
print("Invalid index: \(indexPath.row)")
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch (segue.destinationViewController, sender) {
case (let controller as FriendsProfileViewController, let user as User):
controller.user = user
default:
break
}
}
The issue I believe is that we always get back an Optional from array as such friends![indexPath.row] returned an Optional(User).
I ended up passing the an Optional User as the sender. Unwrap it and set it to my other VC.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("viewFriend", sender: friends![indexPath.row])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
print(sender)
let destinationVC = segue.destinationViewController
if let friendsProfileVC = destinationVC as? FriendsProfileViewController{
if let friend = sender as? User{
print(friend)
print(friend.firstName)
friendsProfileVC.user = friend
}
}
}
Update, I have tried changing friendsProfileVC.user = friends?[indexPath.row] to friendsProfileVC.user = friends![indexPath.row] and it worked. Not sure why did it not work earlier on.
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!
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)
}
}
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 = ""
}
}
}