How to get custom cell label when segue? - ios

I'm trying to get the name of the selected row in the custom cell. How I can do that in Swift?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var selectedCell = CustomCell()
selectedCell = tableView(tbl, cellForRowAtIndexPath: <#NSIndexPath#>)
if(segue.identifier == "next") {
var next = (segue.destinationViewController as! EngineViewController)
next.titleSub = selectedCell.cell.lblBrand.text
}
}

I believe if you are just selecting a cell, the cell should be the sender. Try this
if let selectedCell = sender as? CustomCell {
if(segue.identifier == "next") {
var next = (segue.destinationViewController as! EngineViewController)
next.titleSub = selectedCell.cell.lblBrand.text
}
}

You could attempt to override didSelectRowAtIndexPath to get your cell.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as! CustomCell
cell.yourLabel.textYouWant
let yourViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
navigationController?.pushViewController(yourViewController, animated: true)
}

Related

navigationItem.title from UITableViewCell

Navigation Bar title is not appearing according to the Selected Cell.
I have the Navigation View Controller inside a Container View.
The Container View is in ViewController.
ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "embedseg" {
guard let splitViewController = segue.destination as? UISplitViewController,
let leftNavController = splitViewController.viewControllers.first as? UINavigationController,
let masterViewController = leftNavController.topViewController as? MasterViewController,
//let detailViewController = splitViewController.viewControllers.last as? DetailViewController
let rightNavController = splitViewController.viewControllers.last as? UINavigationController,
let detailViewController = rightNavController.topViewController as? DetailViewController
else { fatalError() }
let firstMonster = masterViewController.monsters.first
detailViewController.monster = firstMonster
masterViewController.delegate = detailViewController
detailViewController.navigationItem.leftItemsSupplementBackButton = true
detailViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
//detailViewController.navigationItem.title = "Hello" <-- tested this, it worked.
//detailViewController.navigationItem.title = cell.textLabel?.text <-- this didn't work.
//detailViewController.navigationItem.title = monster.name <-- and this didn't work.
}
}
MasterViewController:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let monster = monsters[indexPath.row]
cell.textLabel?.text = monster.name
return cell
}
When you select the cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! YourCellClassName
self.performSegue(withIdentifier: "embedseg", sender:cell.textLabel?.text)
}
in prepareforSegue
let cellText = sender as! String
detailViewController.navigationItem.title = cellText
This happens because monster and cell are defined inside
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
but not inside
override func prepare(for segue: UIStoryboardSegue, sender: Any?){}
If you have set your segues using the storyboard you can do something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if let cell = sender as? UITableViewCell {
detailViewController.navigationItem.title = cell.textLabel?.text
}
}
or something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if let cell = sender as? UITableViewCell {
let indexPath = tableView.indexPath(for: cell)
detailViewController.navigationItem.title = monsters[indexPath.row].name
}
}
In the first case you cast "sender" as the cell so you can access it's values, in the second case you cast "sender" as the cell, you find what is it's indexPath and then you use the indexPath to find the correct "monster" using you array monsters

Segue from CollectionViewCell to Another View Controller Passing IndexPath

I'm trying to pass the indexPath of a cell tapped in a UICollectionView to another view controller. I can't seem to get the indexPath of what was selected and segue it to the next view controller
I get this error: "Could not cast value of type Post to PostCell"
View Controller #1:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let post = posts[indexPath.row]
if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PostCell", forIndexPath: indexPath) as? PostCell {
cell.configureCell(post)
}
return cell
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedPost: Post!
selectedPost = posts[indexPath.row]
performSegueWithIdentifier("PostDetailVC", sender: selectedPost)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
//Error here: Could not cast value of Post to PostCell
if let selectedIndex = self.collection.indexPathForCell(sender as! PostCell){
print(selectedIndex)
}
if let detailsVC = segue.destinationViewController as? PostDetailVC {
if let selectedPost = sender as? Post {
print(selectedIndex)
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndex
}
}
}
}
View Controller #2:
var indexNum: NSIndexPath!
override func viewDidLoad() {
super.viewDidLoad()
print(indexNum)
}
You are passing a Post instance which doesn't match the expected PostCell instance.
I recommend to pass the index path
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("PostDetailVC", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PostDetailVC" {
guard let selectedIndexPath = sender as? NSIndexPath,
detailsVC = segue.destinationViewController as? PostDetailVC else { return }
print(selectedIndexPath)
let selectedPost = posts[selectedIndexPath.row]
detailsVC.post = selectedPost
detailsVC.myId = self.myId!
detailsVC.indexNum = selectedIndexPath
}
}
You are passing a Post and not a PostCell as sender. You don't need that anyway, as the collectionView keeps track of selected items.
Try this:
if let selectedIndex = self.collection.indexPathsForSelectedItems()?.first {
print(selectedIndex)
}
It's because you are giving argument which has type of Post and you are trying to cast it as PostCell. Which will not work.

prepareForSegue - CollectionView/TableView

How can I use indexPathForSelectedRow in CollectionView?
CollectionView/TableView:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("levelCell", forIndexPath: indexPath) as! CollectionViewCell
guard levelListen != nil else {
return cell
}
let levelListe = levelListen[indexPath.row]
cell.levelLabel?.text = levelListe.name
return cell
}
TableView - prepareForSegue (work):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "zumLevel" {
let dstCtl = segue.destinationViewController as! InLevelViewController
let indexPath = tableView.indexPathForSelectedRow!
dstCtl.levelList = levelListen[indexPath.row]
}
}
CollectionView - prepareForSegue (not work):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "zumLevel" {
let dstCtl = segue.destinationViewController as! InLevelViewController
// like TableView?
let indexPath = collectionView.indexPathsForSelectedItems()!
dstCtl.levelList = levelListen[indexPath.row] // <--- .row doesn't work, should I use .count ?
}
}
When I try .count it says: "unexpectedly found nil while unwrapping an Optional value"
collectionView.indexPathsForSelectedItems() returns multiple IndexPath's because you can select multiple cells. This function returns an array of IndexPaths, e.g [NSIndexPath].
It should work if you'd do something like:
let indexPath = collectionView.indexPathsForSelectedItems()
if let lastRowSelected = indexPath?.last?.row {
dstCtl.levelList = levelListen[lastRowSelected]
}

UIImage not appearing

When I segue my UIImageView from my NewsTableViewController.swift, the image does not appear in my NewsDetailTableViewController.swift.
Here is an image of my simulator:
Here is an image of my Main.storyboard:
Here is my prepareForSegue() method code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as! NewsDetailTableViewController
destinationController.item = items[indexPath.row]
let newsImage = UIImageView(image: UIImage(named: detailImages[indexPath.row]))
destinationController.image = newsImage
}
}
}
It is also worth mentioning that my image in my NewsTableViewController.swift is set to 0x0, and in my NewsDetailTableViewController.swift, it is set to 600x216. I don't know if this would matter or not. If you desire any code, please do feel free to ask.
FYI, I use Swift.
In prepareForSegue the IBOutlets of your destinationController have not been initialized yet. Just pass detailImages to another array property on NewsDetailTableViewController. Change your prepareForSegue to:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as! NewsDetailTableViewController
destinationController.item = items[indexPath.row]
destinationController.imageNames = detailImages
}
}
}
Then in NewsTableViewController add the following code:
var imageNames:[String]?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//replace with whatever identifier you're using
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.imageView?.image = self.imageNames[indexPath.row]?
return cell
}

How to pass data from UITableViewCell to ViewController?

I have followed multiple tutorials, and have tried many answers on here, but I cannot seem to figure out what the problem is.
Here is my code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
let indexPath = homeTimelineTableView.indexPathForSelectedRow()
let currentCell = homeTimelineTableView.cellForRowAtIndexPath(indexPath!) as! ProductTableViewCell
productTitle = currentCell.productCellTitleLabel!.text
println("The product title is \(productTitle)")
self.performSegueWithIdentifier("timelineDetail", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var titleLables: String!
if (segue.identifier == "timelineDetail") {
println("it works thus far!")
let viewController = segue.destinationViewController as! ProductDetailViewController
let selectedRow = homeTimelineTableView.indexPathForSelectedRow()!.row
viewController.titleLabel?.text = productTitle
}else {
println("wtf is wrong with your code?!")
}
}
I do not receive any errors. However, when I go to run my app, my product title still refuses to pass to the viewcontroller.
Any suggestions? Thanks.
At this stage viewController.titleLabel is nil (you are using ?, that's why there is no error)
The correct approach should be:
add var productTitle: String! in ProductDetailViewController
pass productTitle not to UILabel, but to viewController.productTitle
in viewDidLoad of ProductDetailViewController set viewController.titleLabel?.text = self.productTitle
The productTitle variable must be assigned from the currently selected cell in the prepareForSegue method.
Check the code below.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var titleLables: String!
if (segue.identifier == "timelineDetail") {
println("it works thus far!")
let viewController = segue.destinationViewController as! ProductDetailViewController
let selectedRow = homeTimelineTableView.indexPathForSelectedRow()!.row
let currentCell = homeTimelineTableView.cellForRowAtIndexPath(indexPath!) as! ProductTableViewCell
productTitle = currentCell.productCellTitleLabel!.text
viewController.titleLabel?.text = productTitle
} else {
println("wtf is wrong with your code?!")
}
}
The problem is most lilely in these two lines:
let indexPath = homeTimelineTableView.indexPathForSelectedRow()
let currentCell = homeTimelineTableView.cellForRowAtIndexPath(indexPath!) as! ProductTableViewCell
First, func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) provides already the selected indexPath. There is no need for let indexPath = ....
Second, don't load the cell's value (which returns nil, if the cell is visible and tableView.visibleCells() brings other issues), but use your data source to get the item at the selected indexPath.
In total it might look like:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// `indexPath` comes from the function parameters
let item = model.itemAtIndexPath(indexPath)
// the 'model'-part should be the same like in `cellForRow:indexPath`
// your mission is only to get the item at the path, not the cell
productTitle = item.title
self.performSegueWithIdentifier("timelineDetail", sender: self)
}

Resources