I got a strange issue (in my opinion;)) considering a subclass of uitableview cell. The code for my subclass is:
class SubLevelTableCell: UITableViewCell {
var subLevelLabel:UILabel
var subLevelBack:UIView
var subLevelScore:UIImageView
override init(style: UITableViewCellStyle, reuseIdentifier: String!)
{
self.subLevelBack = UIView()
self.subLevelLabel = UILabel()
self.subLevelScore = UIImageView()
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
self.subLevelLabel.textColor = whiteColor
self.subLevelLabel.font = UIFont(name: subLevelLabel.font.fontName, size: 20)
self.addSubview(self.subLevelBack)
self.subLevelBack.addSubview(self.subLevelLabel)
self.subLevelBack.addSubview(self.subLevelScore)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
self.subLevelBack.frame = CGRectMake(10, 10, self.bounds.size.width-20, self.bounds.size.height-20)
self.subLevelLabel.frame = CGRectMake(5, 0, subLevelBack.frame.size.width/2-10, subLevelBack.frame.size.height)
self.subLevelScore.frame = CGRectMake(subLevelBack.frame.size.width-120, 15, 100, subLevelBack.frame.size.height-30)
}
}
Now I create these cells in my view controller as follows:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:SubLevelTableCell? = SubLevelTable?.dequeueReusableCellWithIdentifier("Cell") as? SubLevelTableCell
if (cell == nil)
{
cell = SubLevelTableCell(style: UITableViewCellStyle.Subtitle,
reuseIdentifier: "Cell")
cell!.backgroundColor = grayColor
}
if (indexPath.row == 0){nextLevelCanBePlayed = true}
if(nextLevelCanBePlayed){
canBePlayedArray[indexPath.row] = true
cell!.subLevelBack.backgroundColor = blueColor
}else{
canBePlayedArray[indexPath.row] = false
cell!.subLevelBack.backgroundColor = redColor
}
cell!.subLevelLabel.text = "Stage \(indexPath.row+1)"
let data = db.query("SELECT * FROM LEVEL_DETAIL WHERE MAIN_LEVEL =\(MainLevelNr!) AND SUB_LEVEL = \(indexPath.row+1)")[0]
var levelScore: Int = 0
if let columnValue = data["COMPLETED"]{
levelScore = columnValue.asInt()
if (levelScore > 0){nextLevelCanBePlayed = true}else{nextLevelCanBePlayed = false}
cell!.subLevelScore.image = UIImage(named: "\(levelScore)Stars.png")
}
return cell!
}
My problem is that when the view loads for the first time, the subLevelBack.backgroundColor is set properly, ie. the subview's color is correct.
Though when I start scrolling, it becomes a bit of a mess with different cells having incorrect background colors, and I don't know how to solve this issue. I don't have this same issue with the image displayed in the UIImageView btw.
I hope someone will point me in the right direction. Kind regards, Sander
if (indexPath.row == 0){nextLevelCanBePlayed = true}
if(nextLevelCanBePlayed){ ...
The above code seems incorrect. You're trying to keep track of how many levels have been played, but each time the first cell gets re-rendered, nextLevelCanBePlayed will be reset. Perhaps try just if(nextLevelCanBePlayed || indexPath.row == 0){.
The other thing is you're making the assumption that the table view will re-render its cells near the viewport in order, but isn't documented anywhere and very likely isn't reliably true, and is especially likely if you're scrolling in the reverse direction. So when the table view re-builds cell 4 (nextLevelCanBePlayed calculates and sets to false) and maybe goes back to cell 3 next, and even if 3 is actually playable, nextLevelCanBePlayed will be false and 3 will show up incorrect. It then starts making sense that your colors start erratically changing as you scroll up and down.
My suggestion is to properly use your UITableViewDataSource methods and use those to work with the db and return proper data objects that represent the state and data of your cells.
Related
I am attempting to pass data from a the UITableView function cellForRowAt to a custom UITableViewCell. The cell constructs a UIStackView with n amount of UIViews inside of it. n is a count of items in an array and is dependent on the data that is suppose to be transferred (a count of items in that array). Something very confusing happens to me here. I have checked in the VC with the tableView that the data has successfully passed by using the following snippet of code
print("SELECTED EXERCISES: ", self.selectedExercises)
cell.randomSelectedExercises = self.selectedExercises
print("PRINTING FROM CELL: ", cell.randomSelectedExercise)
I can confirm that both of these print statements return non-empty arrays. So to me, this means that the custom cell has the data I require it to have. But, when I try to print out the very same array in the UITableViewCell swift file (randomSelectedExercises) , it returns empty to me. How is this possible? From what I understand, the cell works on creating the property initializers first, then 'self' becomes available. I had a previous error telling me this and to fix it, I turned my UIStackView initializer to lazy, but this is how I ended up with my current problem.
Here is the code in beginning that is relevant to the question that pertains to the table view. I have decided to present this code incase the issue is not in my cell but in my table view code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RoutineTableViewCell") as! RoutineTableViewCell
let workout = selectedWorkouts[indexPath.row]
//get the information we need - just the name at this point
let name = workout["name"] as! String
var randomInts = [Int]()
//perform a query
let query = PFQuery(className: "Exercise")
query.includeKey("associatedWorkout")
//filter by associated workout
query.whereKey("associatedWorkout", equalTo: workout)
query.findObjectsInBackground{ (exercises, error) in
if exercises != nil {
//Created an array of random integers... this code is irrelevant to the question
//Picking items from parent array. selectedExercises is a subarray
for num in randomInts {
//allExercises just contains every possible item to pick from
self.selectedExercises.append(self.allExercises[num-1])
}
//now we have our selected workouts
//Both print statements successfully print out correct information
print("SELECTED EXERCISES: ", self.selectedExercises)
cell.randomSelectedExercises = self.selectedExercises
print("PRINTING FROM CELL: ", cell.randomSelectedExercises)
//clear the arrays so we have fresh ones through each iteration
self.selectedExercises.removeAll(keepingCapacity: false)
self.allExercises.removeAll(keepingCapacity: false)
} else {
print("COULD NOT FIND WORKOUT")
}
}
//***This works as expected - workoutName is visible in cell***
cell.workoutName.text = name
//clear the used arrays
self.allExercises.removeAll(keepingCapacity: false)
self.selectedExercises.removeAll(keepingCapacity: false)
return cell
}
Below is the code that gives me a problem in the cell swift file. the randomSelectedExercise does not have any data in it when I enter this area. This is an issue because in my for loop I am iterating from 1 to randomSelectedExercise.count. If this value is 0, I receive an error. The issue is focused in the UIStackView initializer:
import UIKit
import Parse
//Constants
let constantHeight = 50
//dynamic height number
var heightConstantConstraint: CGFloat = 10
class RoutineTableViewCell: UITableViewCell {
//will hold the randomly selected exercises that need to be displayed
//***This is where I thought the data would be saved, but it is not... Why???***
var randomSelectedExercises = [PFObject]()
static var reuseIdentifier: String {
return String(describing: self)
}
// MARK: Overrides
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
contentView.addSubview(containerView)
containerView.addSubview(workoutName)
containerView.addSubview(stackView)
NSLayoutConstraint.activate(staticConstraints(heightConstantConstraint: heightConstantConstraint))
//reset value
heightConstantConstraint = 10
}
//MARK: Elements
//Initializing workoutName UILabel...
let workoutName: UILabel = {...}()
//***I RECEIVE AN EMPTY ARRAY IN THE PRINT STATEMENT HERE SO NUM WILL BE 0 AND I WILL RECEIVE AN ERROR IN THE FOR LOOP***
lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.backgroundColor = .gray
stackView.translatesAutoresizingMaskIntoConstraints = false
//not capturing the data here
print("rSE array:", randomSelectedExercises)
var num = randomSelectedExercises.count
for i in 1...num {
let newView = UIView(frame: CGRect(x: 0, y: (i*50)-50, width: 100, height: constantHeight))
heightConstantConstraint += CGFloat(constantHeight)
newView.backgroundColor = .purple
let newLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
newLabel.text = "Hello World"
newView.addSubview(newLabel)
stackView.addSubview(newView)
}
return stackView
}()
//initializing containerView UIView ...
let containerView: UIView = {...}()
//Setting the constraints for each component...
private func staticConstraints(heightConstantConstraint: CGFloat) -> [NSLayoutConstraint] {...}
}
Why is my data not properly transferring? How do I make my data transfer properly?
Here is what you're doing in your cellForRowAt func...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// get a cell instance
let cell = tableView.dequeueReusableCell(withIdentifier: "RoutineTableViewCell") as! RoutineTableViewCell
// ... misc stuff
// start a background process
query.findObjectsInBackground { (exercises, error) in
// nothing here will happen yet... it happens in the background
}
// ... misc stuff
return cell
// at this point, you have returned the cell
// and your background query is doing its work
}
So you instantiate the cell, set the text of a label, and return it.
The cell creates the stack view (with an empty randomSelectedExercises) and does its other init /setup tasks...
And then - after your background find objects task completes, you set the randomSelectedExercises.
What you most likely want to do is run the queries while you are generating your array of "workout" objects.
Then you will already have your "random exercises" array as part of the "workout" object in cellForRowAt.
I have made a UITableView with some cells containing UISliders. Every UISlider has a unique tag - the number of a value it represents.
When isContinuous value is set to true for them, the first and the last sliders affect each other - dragging one of them makes the same change in value on the other.
Here is how those cells are made:
class CellWithSliderValues: UITableViewCell{
#IBOutlet var slider: UISlider! = {
let ctrl = UISlider()
ctrl.backgroundColor = Constants.SETTINGS_CELL_COLOR
return ctrl
}()
// some labels
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// layout
}
override func prepareForReuse() {
super.prepareForReuse()
slider.tag = -10
minLabel.text = nil
maxLabel.text = nil
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
internal func makeSignalLevelCell(\*some args*\) -> UITableViewCell{
let tag: Int
let currValue: Float
let minValue, maxValue: Float
switch(kind){
\\ set all the values above
}
if (numInSection == 0){
// other cells
} else{
let cell = mainScreen.table.dequeueReusableCell(withIdentifier: "CellWithSliderValues") as! CellWithSliderValues
cell.slider.maximumValue = maxValue
cell.slider.minimumValue = minValue
cell.slider.value = currValue
cell.minLabel.text = Int(minValue).description
cell.maxLabel.text = Int(maxValue).description
cell.slider.tag = tag
cell.slider.addTarget(self, action: #selector(sliderChange), for: .valueChanged)
return cell
}
#objc func sliderChange(sender: UISlider){
guard let valueToAdjustNumber = HeatmapSettings.RangedValueOption(rawValue: sender.tag) else {print("Non-understood slider"); return}
print (valueToAdjustNumber)
let newValueGiven = sender.value
switch(valueToAdjustNumber){
\\check for validity and save changes to a different variable
}
sender.resignFirstResponder()
mainScreen.table.reloadData() // beacuse we need to refresh the number in text box
}
The first and the last sliders in the table affect each other - when one has its value adjusted, the other changes its value too. With some debug outputs - see the
print (valueToAdjustNumber)
line above - it looks like valueToAdjustNumber alternates between the one expected for the slider and the one affected by the glitch.
It is not the problem of cell reuse - I tried genereting new cells instead of reuse, and also reusing cells but recreating sliders, it did not help.
When .isContinuous is set to false for the sliders, the problem disappears.
Bug disappeared after reloading only one section at a time.
mainScreen.table.reloadData()
Is made into
mainScreen.table.reloadSections([sectionNumberToReload(value: valueToAdjustNumber)], with: .none)
I'm writing a demo to show user's tweets.
The question is:
Every time I scroll to the bottom and then scroll back, the tweet's images and comments are reloaded, even the style became mess up. I know it something do with dequeue, I set Images(which is an array of UIImageView) to [] every time after dequeue, but it is not working. I'm confused and couldn't quite sleep....
Here is core code of my TableCell(property and Images set), which provide layout:
class WechatMomentListCell: UITableViewCell{
static let identifier = "WechatMomentListCell"
var content = UILabel()
var senderAvatar = UIImageView()
var senderNick = UILabel()
var images = [UIImageView()]
var comments = [UILabel()]
override func layoutSubviews() {
//there is part of Image set and comments
if images.count != 0 {
switch images.count{
case 1:
contentView.addSubview(images[0])
images[0].snp.makeConstraints{ (make) in
make.leading.equalTo(senderNick.snp.leading)
make.top.equalTo(content.snp.bottom)
make.width.equalTo(180)
make.height.equalTo(180)
}
default:
for index in 0...images.count-1 {
contentView.addSubview(images[index])
images[index].snp.makeConstraints{ (make) in
make.leading.equalTo(senderNick.snp.leading).inset(((index-1)%3)*109)
make.top.equalTo(content.snp.bottom).offset(((index-1)/3)*109)
make.width.equalTo(90)
make.height.equalTo(90)
}
}
}
}
if comments.count != 0, comments.count != 1 {
for index in 1...comments.count-1 {
comments[index].backgroundColor = UIColor.gray
contentView.addSubview(comments[index])
comments[index].snp.makeConstraints{(make) in
make.leading.equalTo(senderNick)
make.bottom.equalToSuperview().inset(index*20)
make.width.equalTo(318)
make.height.equalTo(20)
}
}
}
}
Here is my ViewController, which provide datasource:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let tweetCell = tableView.dequeueReusableCell(withIdentifier: WechatMomentListCell.identifier, for: indexPath) as? WechatMomentListCell else {
fatalError("there is no WechatMomentList")
}
let tweet = viewModel.tweetList?[indexPath.row]
for i in tweet?.images ?? [] {
let flagImage = UIImageView()
flagImage.sd_setImage(with: URL(string: i.url))
tweetCell.images.append(flagImage)
}
for i in tweet?.comments ?? [] {
let flagComment = UILabel()
flagComment.text = "\(i.sender.nick) : \(i.content)"
tweetCell.comments.append(flagComment)
}
return tweetCell
}
The Images GET request has been define at ViewModel using Alamofire.
The firsttime is correct. However, If I scroll the screen, the comments will load again and images were mess up like this.
I found the problem in your tableview cell. in cell you have two variables like this.
var images = [UIImageView()]
var comments = [UILabel()]
Every time you using this cell images and comments are getting appended. make sure you reset these arrays every time you use this cell. like setting theme empty at initialization.
I've read around so don't knock this as a duplicate unless my searching has been completely awful.
Basically I have a small table (5 Fixed rows) however they do have indexes associated with them in a tuple (this is why I'm using the dynamic way rather than a static way.
The players goal is to swap the cells around. I am not using a nib to get these cells populated, this is how.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellID = "Cell"
let customCell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! DefinitionMatchTableViewCell
customCell.background.layer.borderWidth = CGFloat(2.0)
if tableView == nameTableLeft{
customCell.textToDislay!.text = nameList[indexPath.row].0
customCell.background.layer.borderColor = UIColor(red: 255/255, green: 192/255, blue: 1/255, alpha: 1.0).cgColor
let cellIDFromTuple = nameList[indexPath.row].1
customCell.tag = cellIDFromTuple
}
if tableView == definitionTableRight{
customCell.textToDislay!.text = definitionList[indexPath.row].0
customCell.background.layer.borderColor = UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.2).cgColor
let cellIDFromTupleForDefinition = definitionList[indexPath.row].1
customCell.tag = cellIDFromTupleForDefinition
}
customCell.background.backgroundColor = UIColor.clear
customCell.backgroundColor = UIColor.clear
return customCell
}
Now the problem is that on an iPhone SE the 5 cells can't fit which results in the top or bottom cell losing it's reference ID when checking if the values match. This makes the game impossible to complete, I need a way so I can populate the table with an index value associated with each string but so the table doesn't reuse the cell but it remains in memory.
The only method I can think of is writing a static table with the data but then providing each cell with an invisible index that it carries associated with the string. However I'd much rather do it dynamically.
Any advice on to keep the state of these cells would be greatly appreciated. Thanks!
EDIT 1
Here is the way I check the answers based on my index values in the table. I imagine the problem comes from .indexPathsForVisibleRows as some aren't visible
for index in nameTableLeft.indexPathsForVisibleRows!{
let leftCell = nameTableLeft.cellForRow(at: index) as? DefinitionMatchTableViewCell
let rightCell = definitionTableRight.cellForRow(at: index) as? DefinitionMatchTableViewCell
if nameTableLeft.cellForRow(at: index)?.tag == definitionTableRight.cellForRow(at: index)?.tag{
leftCell?.background.layer.borderColor = UIColor.green.cgColor
rightCell?.background.layer.borderColor = UIColor.green.cgColor
counter += 1
}else{
leftCell?.background.layer.borderColor = UIColor.red.cgColor
rightCell?.background.layer.borderColor = UIColor.red.cgColor
}
}
As you can see I then check the values match up on the tags. However I'm struggling with this concept if I used something Different.
My Model
var nameList : [(String, Int)] = [("Trojan", 0),
("Virus", 1),
("Spyware", 2),
("Ransomware", 3),
("Leakware", 4)]
var definitionList : [(String, Int)] = [("Attaches onto another program. Replicates itself. Something loaded onto your device without your knowledge. Continues to spread", 0),
("When malware is disguised as something else. Usually an e-mail attachment", 1),
("Tracks a user's actions, this includes login details, internet habits and any secure accounts", 2),
("Locks a device or encrypts files and demands money to unlock it", 3),
("Threatens to distribute your information", 4)]
Edit 2
Thanks to some help in the answers I had decided to add this to my answer checking.
for answerIndex in 0...4{
if definitionList[answerIndex].1 == nameList[answerIndex].1{
print("MATCH")
counter += 1
}else{
print("NO MATCH")
}
}
I jumble both the definition and name lists to start with. I then decide to look at both of the indexes placed in the tuple based on the tables total length. Unfortunately I had to resort to magic numbers are you cannot iterate through a tuple.
So this little loop decides if the indexes line up in my tuples and if they do it's correct otherwise it's not. Thanks again everyone for the help.
I also solved a similar problem. My advise is to keep reusing the cells. Store the data corresponding to each cell externally in a separate model class. Then store it in a mutable array. When you shuffle the cells, shuffle the data in the mutable array.
It can be done in the following way.
The model class
class model: NSObject {
var name: String = ""
var definition: String = ""
var type: String = ""
required init(name: String, definition: String, type: String) {
super.init()
self.name = name
self.definition = definition
self.type = type
}
}
Custom UITableViewCell - trivial example for different layouts
class CustomTableViewCell: UITableViewCell {
var nameLabel: UILabel = UILabel()
var definitionLabel: UILabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
nameLabel.textColor = UIColor.black
nameLabel.font = UIFont.systemFont(ofSize: 15)
nameLabel.textAlignment = NSTextAlignment.left
self.contentView.addSubview(nameLabel)
definitionLabel.textColor = UIColor.brown
definitionLabel.font = UIFont.systemFont(ofSize: 15)
definitionLabel.textAlignment = NSTextAlignment.right
self.contentView.addSubview(definitionLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
nameLabel.frame = CGRect(x: 10, y: 10, width: self.contentView.frame.size.width - 20, height: self.contentView.frame.size.height - 20)
definitionLabel.frame = CGRect(x: 10, y: 10, width: self.contentView.frame.size.width - 20, height: self.contentView.frame.size.height - 20)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Registering the cell:
self.tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "reuseIdentifier")
Using the CustomTableViewCell according to model:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
if model.type == "name" {
cell.nameLabel.text = model.name
cell.definitionLabel.isHidden = true
}else if model.type == "definition" {
cell.definitionLabel.text = model.definition
cell.nameLabel.isHidden = true
}
return cell
}
The moving cells part:
let mutableArray:[model] = [model1, model2, model3, model4, model5] // model class holds data for each cell
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let source = sourceIndexPath.row;
let destination = destinationIndexPath.row;
let sourceModel = mutableArray[source]
let destinationModel = mutableArray[destination]
mutableArray[source] = destinationModel
mutableArray[destination] = sourceModel
}
Feel free to comment if you have any doubts regarding this implementation. Feel free to suggest edits to make this better :)
Edit:-
Even if it's a tuple with it's index position, you can change the values when the rows moved accordingly.
var nameList : [(String, Int)] = [("Trojan", 0),
("Virus", 1),
("Spyware", 2),
("Ransomware", 3),
("Leakware", 4)]
let source = sourceIndexPath.row
let destination = destinationIndexPath.row
var sourceTuple: (String, Int) = nameList[source]
var destinationTuple: (String, Int) = nameList[destination]
sourceTuple.1 = destination
destinationTuple.1 = source
nameList[destination] = sourceTuple
nameList[source] = destinationTuple
First of all you should expect cells to be reused and not store state in your cells. But if you want a quick answer then set a different reuse identifier for every cell.
I am having a problem creating UILabels to insert into my tableview cells. They insert fine and display fine, the problem comes in when I go to scroll. The ordering of the row's goes haywire and looses it's initial order. For instance, at the beginning, the idLabel's cell text, goes from 0 > 14, in sequential order. After scrolling down and back up, the order could be anything, 5, 0, 10, 3 etc.
Any ideas on why this is happening? I am presuming my attempts to update the label's after cell creation is wrong.
var idArr: NSMutableArray!
// In init function
self.idArr = NSMutableArray()
for ind in 0...14 {
self.idArr[ind] = ind
}
// Create the tableview cells
internal func tableView( tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath ) -> UITableViewCell {
if cell == nil {
let id = self.idArr[indexPath.row] as Int
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell" )
// Id
let idLabel: UILabel = UILabel( frame: CGRectZero )
idLabel.text = String( id )
idLabel.textColor = UIColor.blackColor()
idLabel.tag = indexPath.row
idLabel.sizeToFit()
idLabel.layer.anchorPoint = CGPointMake( 0, 0 )
idLabel.layer.position.x = 15
idLabel.layer.position.y = 10
idLabel.textAlignment = NSTextAlignment.Center
cell?.addSubview( idLabel )
}
// Update any labels text string
for obj: AnyObject in cell!.subviews {
if var view = obj as? UILabel {
if view.isKindOfClass( UILabel ) {
if view.tag == indexPath.row {
view.text = String( id )
}
}
}
}
// Return the cell
return cell!
}
Thanks for any assistance, I can't see the wood for the trees anymore.
The logic in your cell updating looks off. You are checking that a tag you set at initialization is equal to the index path's row but because the cells should be reused this will not always be the case. If you just remove that tag checking line in the for loop it should work fine.
Also, I'm not sure why you are checking ifKindOfClass after you have optionally cast the view as a label anyway.
To prevent accidentally updating Apple's views you would be better off adding a constant tag for the label and pulling the label by that tag instead of looping through all of the subviews.
This is clearly not the actual code you are running since the id variable is not in the proper scope and there is no definition of cell. I've added proper dequeueing and move the id variable to something that works. I'm assuming you are doing those in your actual code.
internal func tableView( tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath ) -> UITableViewCell {
let labelTag = 2500
let id = self.idArr[indexPath.row] as Int
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell" )
// Id
let idLabel: UILabel = UILabel( frame: CGRectZero )
idLabel.text = String( id )
idLabel.textColor = UIColor.blackColor()
idLabel.tag = labelTag
idLabel.sizeToFit()
idLabel.layer.anchorPoint = CGPointMake( 0, 0 )
idLabel.layer.position.x = 15
idLabel.layer.position.y = 10
idLabel.textAlignment = NSTextAlignment.Center
cell?.addSubview( idLabel )
}
// Update any labels text string
if let view = cell?.viewWithTag(labelTag) as? UILabel {
view.text = String( id )
}
// Return the cell
return cell!
}