Data Repeat in UItableview When Scrolling

Repeated cells while scrolling uitableview

you seem to have created a separate class for UITableViewCell. The problem with your code is that you are not resetting the labels when reuse happens.

Oveeride prepareForReuse method in your custom UITableviewCell class and reset your interfaces there. That should fix the issue.

Values Repeat When Scrolling in TableView

From the code you have posted, it is clear that you are not setting the enabled property of the UIButton with respect to the DataSource(The array and its objects you are using to load the tableview, that is the elements in objects array). Whatever objects that array contains, add a property to determine if the condition for the button should be true or false, and then in cellForRowAtIndexPath set the enabled property of the button according to that. When the button is clicked, add a callback to the ViewController(using a delegate) and set the property there.

Sample Code

In custom cell class:

protocol CellButtonDelegate
{
func buttonClicked(cell : PFTableViewCell)
}

public var delegate : CellButtonDelegate?

public var buttonEnabled : Bool?
{
get
{
return heartOutlet.enabled
}
set
{
heartOutlet.enabled = newValue
}
}

@IBAction func heartButton(sender: AnyObject) {
if(parseObject != nil) {
if var votes:Int? = parseObject!.objectForKey("votes") as? Int {
votes!++

parseObject!.setObject(votes!, forKey: "votes")
parseObject!.saveInBackground()

votesLabel?.text = "\(votes!)"
}
}
delegate?.buttonClicked(self)
}

In ViewController:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {

var cell: FeedTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? FeedTableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("FeedTableViewCell", owner: self, options: nil)[0] as? FeedTableViewCell
}
if let pfObject = object {
//I took out the irrelevant methods. I can add them if that makes a difference...
var votes:Int? = pfObject["votes"] as? Int
if votes == nil {
votes = 0
}
cell?.buttonEnabled = objects[indexPath.row].isEnabled //The new property you need to add. true by default
cell?.delegate = self //Make sure you implement the delgate
cell?.votesLabel?.text = "\(votes!)"
return cell?
}

func buttonClicked(cell : PFTableViewCell)
{
//Here, get the indexPath using the cell and assign the new property in the array.
}

Please note that the above code is rough. Just get the idea from the code and implement it as per your requirement.

Duplication in values of tableView when Scrolling Swift

From the Apple Docs:

At runtime, the table view stores cell objects in an internal queue. When the table view asks the data source to configure a cell object for display, the data source can access the queued object by sending a dequeueReusableCellWithIdentifier: message to the table view, passing in a reuse identifier. The data source sets the content of the cell and any special properties before returning it. This reuse of cell objects is a performance enhancement because it eliminates the overhead of cell creation.

So what you're doing when reusing cells from the queue is retrieving cells you have already created and configured. Changes made to the created Cells will be also applied to the reused cells which are displayed when scrolling as soon as the reused cells aren't visible anymore. This means you have to re-assign any values you want to override which are custom to the unique cell you are displaying, which also applies if there is no content/an empty string you want to display. Otherwise you will get random results as you have been experiencing.

let cell = tableView.dequeueReusableCellWithIdentifier("TimingsCell", forIndexPath: indexPath) as! timingCell     
let timings = self.Details!.timingsArray
let dayTime = timings[indexPath.row]
cell.dayLabel.text = dayTime.dayName

if dayTime.open != nil && dayTime.close != nil {
cell.timeLabel.text = "\(convertTimeFormat(dayTime.open!)) - \(convertTimeFormat(dayTime.close!))"
}
else{
//change label to empty string when reusing
cell.timeLabel.text = "";
}

return cell

How to make a loop appending 20 -20 rows in a tableview when scrolling?

I'll elaborate the pagination in tableView using an example. You can go through it and then implement it in your project.

1. Let's assume you've a String array that contains around 500 elements.

var allUsers = [String](repeating: "User", count: 500)

2. Create another String array that initially contains first 10 elements from allUsers array.

var dataSource = [String]()

override func viewDidLoad() {
super.viewDidLoad()
self.addElements() //explained next..
}

The dataSource array will act as the actual dataSource for the tableView.

3. Let's maintain an offset that'll keep track of the index from which we need to add next 10 elements, i.e.

var nextOffset = 0

func addElements() {
let newOffset = nextOffset+10
for i in nextOffset..<newOffset {
dataSource.append(allUsers[i])
}
nextOffset = newOffset
}

addElements() method simply add next 10 elements starting from the nextOffset.

4. The UITableViewDataSource methods look like,

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(dataSource[indexPath.row]) : \(indexPath.row)"
return cell
}

5. Now implement UITableViewDelegate method - tableView(_:willDisplay:forRowAt:)

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let currentCount = self.dataSource.count
if currentCount < 500 && indexPath.row == (currentCount-1) { //last row
self.addData()
self.setUpLoaderView(toShow: true)
} else {
self.setUpLoaderView(toShow: false)
}
}

In the above methods, I've checked if the cell is being displayed for the last row. If yes, then we add more data to it using addData() method and show a loaderView at bottom using setUpLoaderView(toShow:) method.

6. Here is the definition of both the methods,

func addData() {
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
self.addElements()
self.tableView.reloadData()
}
}

func setUpLoaderView(toShow: Bool) {
if toShow {
self.tableView.tableFooterView?.isHidden = false
self.tableView.tableFooterView = self.loaderMoreView
} else {
self.tableView.tableFooterView = UIView()
}
}

In addData() I've added a delay of 10 seconds as per your requirement. So the loader will be visible for 10 seconds before the tableView is updated with new data.

7. loaderMoreView is simply a UIActivityIndicatorView that is set as the tableFooterView, like:

private lazy var loaderMoreView: UIView = {
let loaderView = UIActivityIndicatorView(style: .whiteLarge)
loaderView.color = UIColor.gray
loaderView.startAnimating()
return loaderView
}()

images repeating cells when scrolled in tableview

AlamofireImage handles this very well. https://github.com/Alamofire/AlamofireImage

import AlamofireImage

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DataTableViewCell
cell.selectionStyle = .none

let kid = kidsdata[indexPath.row] as KidDetails

cell.NameLabel.text = kid.name
cell.ClassNameLabel.text = kid.standard

// assuming cell.ProfileImage is a UIImageView
cell.ProfileImage.image = nil

let frame = CGSize(width: 50, height: 50)
let filter = AspectScaledToFillSizeWithRoundedCornersFilter(size: frame, radius: 5.0)

cell.ProfileImage.af_setImage(withURL: urlToImage, placeholderImage: nil, filter: filter,
imageTransition: .crossDissolve(0.3), runImageTransitionIfCached: false)

return cell
}

Data repeat in UITableView when scrolling

use cell Identifier different

For example like bellow...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

NSString *CellIdentifier = [NSString stringWithFormat:@"%d,%d",indexPath.section,indexPath.row];

UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
/// write your code here..
}
}

OR set nil like bellow..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

//static NSString *CellIdentifier = @"CellIdentifier";

UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
/// write your code here..
}
}

Swift tableView checkmark repeating on scroll

First make a class/struct of Workout with a flag

struct Workout {
let name: String
let isComplete: Bool
}

Make a sample Data Model

var workouts = [
Workout(name: "Squats", isComplete: false),
Workout(name: "Burpees", isComplete: false),
Workout(name: "Crunches", isComplete: true),
Workout(name: "Push Ups", isComplete: false),
Workout(name: "Jumping Jacks", isComplete: true),
Workout(name: "High Knees", isComplete: false),
Workout(name: "Lunges", isComplete: false),
Workout(name: "Plank", isComplete: false),
Workout(name: "Sechigh Knees", isComplete: false),
Workout(name: "Tricep Dips", isComplete: false),
Workout(name: "Mountain Climbers", isComplete: true),
Workout(name: "Wall Sit", isComplete: true),
Workout(name: "Squats 2", isComplete: false),
Workout(name: "Burpees 2", isComplete: false),
Workout(name: "Crunches 2", isComplete: true),
Workout(name: "Push Ups 2", isComplete: false),
Workout(name: "Jumping Jacks 2", isComplete: false),
Workout(name: "High Knees 2", isComplete: false),
Workout(name: "Lunges 2", isComplete: false),
Workout(name: "Plank 2", isComplete: false),
Workout(name: "Sechigh Knees 2", isComplete: true),
Workout(name: "Tricep Dips 2", isComplete: false),
Workout(name: "Mountain Climbers 2", isComplete: false),
Workout(name: "Wall Sit 2", isComplete: false),
]

Make a custom UITableViewCell with a Workout type variable

class CustomCell: UITableViewCell {

var workout: Workout? {
didSet {
guard let workout = workout else { return }

self.textLabel?.text = workout.name

if workout.isComplete {
self.accessoryType = .checkmark
}
else {
self.accessoryType = .none
}
}
}
}

Then in tableView:cellForRowAtIndexPath: method pass the variable

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.workout = workouts[indexPath.row]

return cell
}


Related Topics



Leave a reply



Submit