how to avoid reusable custom cell from overwriting data when scrolling? - ios

This is the code I am using and it works fine until I scroll in the table view, the cells overwrite each others and all the repostedFromLabel are hidden.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FeedsTableViewCell", forIndexPath: indexPath) as? FeedsTableViewCell
if (arrayofPostsFeed[indexPath.row].postedByUser!.nickName!) != arrayofPostsFeed[indexPath.row].ownedByUser!.nickName! {
cell!.repostedFromLabel.text! = "Reposted From \(self.arrayofPostsFeed[indexPath.row].postedByUser!.nickName!)"
} else {
cell!.repostedFromLabel.hidden = true
}
}
how should I prevent reusable cells to override each others?

You can implement the prepareForReuse function in your FeedsTableViewCell to reset the hidden property of the repostedFromLabel. Something like this:
override func prepareForReuse() {
self.repostedFromLabel.hidden = false
}
At the moment you are not resetting that value, so it will get mixed up when reusing the cells.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("FeedsTableViewCell", forIndexPath: indexPath) as? FeedsTableViewCell
if (arrayofPostsFeed[indexPath.row].postedByUser!.nickName!) != arrayofPostsFeed[indexPath.row].ownedByUser!.nickName! {
cell!.repostedFromLabel.text! = "Reposted From \(self.arrayofPostsFeed[indexPath.row].postedByUser!.nickName!)"
cell!.repostedFromLabel.hidden = false
}else {
cell!.repostedFromLabel.hidden = true
}

Related

User Creation Form just Like iOS Contact Creation working behind this? [duplicate]

My table view can expand and collapse cells when they are pressed, but the content that appears when the cell expands loads before the animation is finished.
What I am left with is this:
What I would like it to look like is this example. This content appears as if it were behind a curtain and the cell expansion animation just reveals it.
Here is the code that controls the table view:
class HistoryViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
var expandedIndexPath: NSIndexPath? // Index path of the cell that is currently expanded
let collapsedHeight: CGFloat = 44.0 // Constant to set the default collapsed height
var ticketHistoryService = TicketHistoryService() // Service to gather info about Ticket History CoreData
var tickets = [Ticket]()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Remove any appended table view cells
tableView.tableFooterView = UIView()
self.tickets = self.ticketHistoryService.fetchData() // Load inital data
}
// MARK: - Table View Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tickets.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! HistoryTableViewCell
let ticket = self.tickets[indexPath.row]
cell.titleLabel!.text = ticket.ticketNumber
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
self.ticketHistoryService.removeObject(indexPath.row)
self.tickets = self.ticketHistoryService.fetchData()
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.beginUpdates()
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
if indexPath.isEqual(self.expandedIndexPath){ // If currently selected cell was just previously selected
self.expandedIndexPath = nil
cell.commentLabel.hidden = true
}
else {
self.expandedIndexPath = indexPath
cell.commentLabel.hidden = false
}
self.tableView.endUpdates()
}
func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
cell.commentLabel.hidden = true
return indexPath
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.isEqual(self.expandedIndexPath) {
return UITableViewAutomaticDimension
}
return collapsedHeight
}
}
One approach is to have your cell clip subview content that would expand outside of itself:
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! HistoryTableViewCell
cell.clipsToBounds = true

TableViewCell not updating properly swift 2.2

In my app I created two custom tableview cells.
Problem I am facing now the second tableview cell update with last element of the array only.
In cellForRowAtIndexpath array elements are displaying fine.
Consider [ "Value1", "Value2" ] is my array. In tableView only value2 is displaying in two cells.
var title = ["value1","value2"]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
let x = Id[indexPath.row]
if x == 0{
let cell1 = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! MyCell1
return cell1
}
else{
let cell2 = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! MyCell2
for index in 0..<myArray.count{
cell2.titleButton.setTitle(title[index],forState:UIControlState.Normal)
}
return cell2
}
}
I am stuck here, your help will be appreciated.
Following is the solution, reason it was going out of range was because value incremented when cell were dequed as cellforrowAtIndexPath was called every time we scrolled down(since some cells were not visible and these cells were dequed when we scrolled down):-
var name = ["HouseBolo","HouseBolo1","HouseBolo2","HouseBolo3"]
var propertyVal:Int = 0
var projectVal:Int = 0
var type = ["Apartment","Villa","Home","Flat","Plot"]
var arrangedData = [String]()
var flatId = [0,1,2,0,0]
override func viewDidLoad() {
super.viewDidLoad()
// I want the Expected Output in Tableview Cell is
// 1. Apartment 2. HouseBolo 3. HouseBolo1 4. Villa 5. Home
for item in flatId {
if item == 0 {
arrangedData.append(type[propertyVal])
propertyVal+=1
}
else {
arrangedData.append(name[projectVal])
projectVal+=1
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrangedData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let flatDetails = flatId[indexPath.row]
// For Property Cell
if flatDetails == 0{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as? PropertyCell
if(cell != nil) {
cell!.pType.text = arrangedData[indexPath.row]
}
return cell!
}
// For Project Cell
else {
let cellan = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as? ProjectCell
if(cellan != nil) {
cellan!.projectName.setTitle(arrangedData[indexPath.row], forState: UIControlState.Normal)
}
return cellan!
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You need to use :
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! searchCell
in :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {}
block.
searchCell : is a class of type : UITableViewCell
After that, go in Storyboard and change the identifier of your cell with : "cell"
In the code...
let cell2 = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! MyCell2
for index in 0..<myArray.count{
cell2.titleButton.setTitle(title[index],forState:UIControlState.Normal)
}
return cell2
you are iterating over 'myArray' and assigning the value to 'cell2.titleButton'. Cell 2 will always have the last value assigned to it's title. It's assigning it to 'value1', then reassigning it to 'value2'. Looping through the array seems to be the issue (assuming the cells are displaying - just always showing the title from the last item in the array.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
}
You have to add your custom tableview cell class name in the place of UITableViewCell
Something like this -
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> **custom tableview cell class name**
{
}
And also in Storyboard ,change the identifier of your cell with : "cell1" and "cell2"

Hide element on select within table cell - Swift

I followed this app to build a table with custom cells: https://github.com/awseeley/Custom-Table-Cell
I am trying to expand a cell and show different content when the cell is clicked.
Here is what I have in my view controller:
var cellTapped:Bool = true
var currentRow = 0;
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//CODE TO BE RUN ON CELL TOUCH
let selectedRowIndex = indexPath
currentRow = selectedRowIndex.row
let cell:TblCell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TblCell
cell.image.hidden = true
tableView.beginUpdates()
tableView.endUpdates()
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == currentRow {
if cellTapped == false {
cellTapped = true
return 141
} else {
cellTapped = false
return 70
}
}
return 70
}
The cell expands when it is clicked and shrinks when it is clicked again. But the image does not hide. How do I get the image to hide? Is there a better way to show another custom .xib file when the cell is selected and have an expand/collapse effect?
You should add this implement below to your cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == currentRow {
if cellTapped == false {
cell.image.hidden = false
} else {
cell.image.hidden = true
}
}
return cell
}
And didSelectRowAtIndexPath you should remove wrong code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//CODE TO BE RUN ON CELL TOUCH
let selectedRowIndex = indexPath
currentRow = selectedRowIndex.row
tableView.reloadData()
}
If you want use want use tableView.beginUpdate() for better animation, you can reference to my demo:
Demo hide image on cell
Hope this help!
I'm not familiarized with it, but you can look at Stack View. I think it's can help you doing what you want:
http://www.raywenderlich.com/114552/uistackview-tutorial-introducing-stack-views

Dynamic Dimension of UITableViewCell ok, but how hide them if empty?

I have a UITableView with 3 prototyped cells (ex. 1st cell: image, 2nd cell: Description, 3. Links,...).
I would like to hide them if for a cell the data from the backend is empty (Ex. if there is no image, hide the first cell). In order to do that, I have override the heightForRowAtIndexPath function in this way:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
switch (indexPath.row) {
case 0:
if event?.photo_urls.count == 0{
return 0
}
else{
return 80.0
}
case 1:
if event?.description == ""{
return 0
}
else{
return 90.0
}
default:
return 100.0
}
}
and hidden the cell by doing
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch (indexPath.row) {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("PhotoCell", forIndexPath: indexPath) as! UITableViewCell
if event?.photo_urls.count != 0 {
// ...
}
else{
cell.hidden = true
}
return cell
case 1:
let cell = tableView.dequeueReusableCellWithIdentifier("DesCell", forIndexPath: indexPath) as! UITableViewCell
if event?.description != "" {
// ...
}
else{
cell.hidden = true
}
return cell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("PhotoCell", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
Until here no problem, it works properly!
Now, THE PROBLEM is that I would like to make the cells dynamics according to the cell contents (ex. description height). In order to do that, I have used
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80.0
}
and if I comment the heightForRowAtIndexPath the cells are actually dynamics but I can't hide them anymore.
Do you have any suggestion on how to be able to hide the cells if they are empty and apply the automatic dimension according to their content?
lets say you have dynamic data and you want to show it in tableview so you need to create an array of your data to display.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet
var tableView: UITableView
var items: [String] = ["We", "Heart", "nothing" ,"" ,"imageurl", "", "xyz"]
override func viewDidLoad() {
super.viewDidLoad()
reloadTableAfterSorting()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
func reloadTableAfterSorting(){
for var i = 0; i < self.items.count; i++
{
if self.items[i] == ""{
self.items.removeAtIndex(2)
}
}
self.tableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
For that i recommend you to sort the array before displaying it in the table view. Hiding the cell is not a good idea and its not good according to Apple recommendations. So you can do one thing except hiding the cell: remove the index from the array. In this way you can always have data to show in table and it will behave properly. So don’t try to hide the cell just pop the index from array.

How do I show a hidden subtitle in a UITableView when selected?

Is there a way to hide the subtitles of all the cells until you select a cell - then it only shows you that cell's subtitle? I tried the following code - which successfully hides all the subtitles but fails to show one when I select a cell:
if cell.selected {
cell.detailTextLabel?.hidden = false
} else {
cell.detailTextLabel?.hidden = true
}
Thanks for any help.
Edit 2 - I ended up doing this in my didSelectRowAtIndexPath:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
for cell in tableView.visibleCells() {
cell.detailTextLabel??.hidden = true
}
var cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.detailTextLabel?.hidden = false
}
Thanks very much, Christian!
Just use the didSelectRowAtIndexPath method and access the touched cell. Then you can show the detailTextLabel.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellID) as UITableViewCell
cell.detailTextLabel?.hidden = false
}

Resources