I'm creating a UiTableView with 2 different cell nibs. it is working perfectly fine expect 1 specific scenario.
ISSUE:
On cell selection, i perform some action in didSelectRowAtIndexPath. After didSelectRowAtIndexPath execution, iOS invokes cellForRowAtIndexPath method and recreates that clicked cell.
What is the affects of recreation:
My cells heights are dynamic. When UiTableView recreates any cell from middle, it causes unnatural jerks on scrolling back/up.
Below is the code snippet of my methods. Any help would be appriciated :)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var post = self.posts[indexPath.row]
if(post.valueForKey(MEDIA) != nil) {
var cell:PostImageTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("PicCell") as PostImageTableViewCell
cell.loadPostData(post)
return cell
} else {
var cell:PostTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as PostTableViewCell
cell.loadPostData(post)
return cell
}
}
Selection method:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedRow = indexPath.row
self.performSegueWithIdentifier("detailSegue", sender: nil);
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
Call Stack:
Related
Here is my code for the WillDisplayRow function:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let monetaryCell = tableView.cellForRow(at: [1,0])
//configure you cell here.
if AppState.sharedInstance.filterPaymentMonetaryIsOn {
monetaryCell?.accessoryType = .checkmark
return monetaryCell!
} else {
monetaryCell?.accessoryType = .none
return monetaryCell!
}
}
And in my DidSelectRow:
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
let monetaryCell = tableView.cellForRow(at: [1,0])
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
if indexPath == [0,0] {
print(indexPath)
} else if indexPath == [1,0] {
if AppState.sharedInstance.filterPaymentMonetaryIsOn == true {
monetaryCell!.accessoryType = .none
AppState.sharedInstance.filterPaymentMonetaryIsOn = false
} else {
monetaryCell?.accessoryType = .checkmark
AppState.sharedInstance.filterPaymentMonetaryIsOn = true
}
Can someone help me out as to why this isnt working? Also, I have alot more cells and when selected each one has the same properties as above. What I'm looking for is the checkmark to be displayed when I reload the view or close and reopen the view. I hope this makes sense. I'm sorry if this is a duplicate, I looked for a few hours but couldn't find a similar situation.
Thank you in advance.
Denis Angell
Move your check mark display functionality from cellForRowAtIndexPath method to willDisplayCell method of UITableViewDelegate. willDisplayCell method works in such a way that whenever the cell about to appear on screen willDisplayCell method calls and desired functionality executes as expected.
My table view has some elements sorted by some types: TypeA, TypeB and TypeC.
I want that when I click on a cell with TypeA to change the selection color to Red, when I type on TypeB to change color to Blue and when pressing on TypeC to change color to Yellow.
Right now I came up with this code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let mode = dataSource.selectedObject else {
fatalError("willDisplayCell, but no selected row?")
}
let type = ModeType(rawValue: mode.type)!
let selectionColor = UIView() as UIView
selectionColor.backgroundColor = type.color()
cell.selectedBackgroundView = selectionColor
}
My issue with this is that willDisplayCell is called when I start my app and my data source is empty so I get a fatal error.
How can I overcome this ? Maybe using a flag to do this only when didSelectRowAtIndexPath was called.
Or is there another way to achieve what I am after ?
I assume you have created custom UITableviewCell. Create a cell type enum.
enum CellType {
case RedCell
case Yellowcell
case OrangeCell
}
//Create enum property
class CustomCell : UITableViewCell {
var cellType:CellType = CellType.RedCell //Default is RedCell
}
Now you have to assign the cell type in your ViewController tableview datasource.
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! CustomCell
cell.cellType = .RedCell //your choice
return cell
}
override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath)
switch(cell.cellType) {
//Handle Switch case
case .RedCell:
cell?.contentView.backgroundColor = UIColor.redColor()
cell?.backgroundColor = UIColor.redColor()
}
}
override func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath)
// Set unhighlighted color
cell?.contentView.backgroundColor = UIColor.blackColor()
cell?.backgroundColor = UIColor.blackColor()
}
EDIT:
If you have created 3 different types of cell class check tableview cell class type and change the color in didHighlightRowAtIndexPath method.
My issue with this is that willDisplayCell is called when I start my
app and my data source is empty so I get a fatal error.
tableView(_:willDisplayCell:forRowAtIndexPath:) will only be called if your data source tells the table view that there are rows to display. So the problem more likely is that your tableView(_:numberOfRowsInSection:) method is returning a number larger than zero when your data source is empty.
Also, your code looks like it expects tableView(_:willDisplayCell:forRowAtIndexPath:) to get called only for selected rows. It gets called for all displayed rows. But this method isn't necessary to affect the background color. In fact, it's rarely used in most apps. There are only a few edge cases where you need to mess with the cell just before it's displayed.
The proper way to set the selection background color is to create and assign a UIView to the cell's selectedBackgroundView property. You can do that either from the cell's subclass (preferred for complex cells) or from the tableView:cellForRowAtIndexPath: data source method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell")
cell!.textLabel?.text = "Kilroy was here."
cell!.selectedBackgroundView = UIView(frame: cell!.bounds)
cell!.selectedBackgroundView!.backgroundColor = .greenColor()
return cell!
}
I'm having this strange issue in my app where it sometimes takes several seconds (10ish) for a custom TableViewCell to trigger a segue to another ViewController. If I click anywhere else in the app during this time, the click triggers the segue.
The problem only occurs when selecting the same cell several times. Meaning if you click the first cell, segue over to the new ViewController, exit the new ViewController and click the same cell again, the problem could occur.
I've reconstructed this issue in a small project here for any kind souls to try out.
http://www.filedropper.com/customcellsegue_2
Any ideas guys?
Edit
Alright here's some code for you guys who don't wanna download the app.
Original ViewController
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100.0
}
// Number of cells in each section.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
// Fill UITableView...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("Selected")
}
Custom Table Cell
class customCell: UITableViewCell {
#IBOutlet var firstLabel: UILabel!
#IBOutlet var secondLabel: UILabel!
}
New ViewController
#IBAction func close(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
I've simply applied a modal segue from the custom cell to the new ViewController.
How can I make a static table view to create an action when one of the cells is clicked in Swift?
I have created a static table like a general menu of the app, I can directly create a push segue when one of the cells are clicked. But at the same time when I click to one of the seques, I want the below function to be run. By draging a cell to the UITableView in storyboard the create action option is not appearing.
var goToProfiles = PFObject(className: "goToProfile")
goToProfiles["user"] = PFUser.currentUser()!.username
goToProfiles["goToUser"] = usernameLbl.text
goToProfiles.save()
If you use sections you will also need to query them.
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.section)
print(indexPath.row)
if indexPath.section == 1 && indexPath.row == 1 {
// do something
}
}
I found the solution with the code below:
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 1 {
//here you can enter the action you want to start when cell 1 is clicked
}
}
For swift 3 compatibility:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Your action here
}
I just made a UITableView in swift with expandable cells when clicking them. Upon being expanded, the cells show a UIDatePicker.
The expanding itself works fine, but the cell-content that should only visible when the cell is expanded kind of shines through the cells. Here is a screenshot of what I am talking about:
Cell 1 is expanded and the other cells are not. As you can see, their expandable content is visible while it actually shouldn't be.
Here is the code I use:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cellIdentifier = "Cell";
var cell: NewExpenseTableCell;
var array: NSArray = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil);
cell = array.objectAtIndex(0) as NewExpenseTableCell;
cell.backgroundColor = UIColor.whiteColor();
cell.descriptionLabel?.text = descriptionLabels[indexPath.item];
return cell;
}
var selectedRowIndex = -1;
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if selectedRowIndex == indexPath.row {
selectedRowIndex = -1;
} else {
self.selectedRowIndex = indexPath.row;
}
newExpenseTable.beginUpdates();
newExpenseTable.endUpdates();
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == selectedRowIndex {
return 206;
}
return 55;
}
Could anyone tell me how I can make sure the UIDatePicker is only visible when the cell is expanded?
Here's what I would recommend to get the cell reuse working correctly.
Open the .xib file for your NewExpenseTableCell. Go to Attributes Inspector, enter "NewExpenseTableCell" as the Identifier.
In the viewDidLoad method of your view controller, register the nib like so:
self.tableView.registerNib(UINib(nibName: "NewExpenseTableCell", bundle: nil), forCellReuseIdentifier: "NewExpenseTableCell")
In the cellForRowAtIndexPath method, replace the first four lines you have with this:
var cell = tableView.dequeueReusableCellWithIdentifier("NewExpenseTableCell") as NewExpenseTableCell