custom UITableViewCell exception - ios

What can it be?
Failed to set (identifier) user defined inspected property on (UIView): [ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key identifier.
On iOS 8 it works, but spamming in debugger, in prior versions it crash app.
All connections in interface builder i checked and reconnected.
My code cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(self.identifier, forIndexPath: indexPath) as PostCell
cell.backgroundColor = UIColor.clearColor()
cell.likeButton.setBackgroundImage(UIImage(named: "post_like_active"), forState: UIControlState.Selected)
cell.dislikeButton.setBackgroundImage(UIImage(named: "post_dislike_active"), forState: UIControlState.Selected)
var storageManager: PostStorageManager = PostStorageManager.sharedManager()
var model: PostModel = storageManager.storageObjects()[indexPath.row] as PostModel
cell.likeButton.selected = model.likeManager.likeState!.liked
cell.dislikeButton.selected = model.likeManager.likeState!.disliked
cell.textView.text = model.text
cell.textView.font = UIFont(name: "HelveticaNeue-Light", size: fontSize)!
cell.textView.contentInset = UIEdgeInsets(top: self.contentInsetTop, left: 0, bottom: 0, right: 0)
cell.likeLabel.text = String(format: "%#", model.amountOfLikes)
cell.dislikeLabel.text = String(format: "%#", model.amountOfDislikes)
var date: NSDate = model.date
cell.timeLabel.text = date.timeAgo()
var tapRecog: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapOccure:")
tapRecog.numberOfTapsRequired = 1
cell.textView.addGestureRecognizer(tapRecog)
var isMan = model.isMan.boolValue
cell.trollfaceImage.image = UIImage(named: String(format: "%#_%i", isMan ? "man" : "woman", model.experiance.integerValue))
var manColor = UIColor(red: 41/255, green: 86/255, blue: 115/255, alpha: 1)
var womanColor = UIColor(red: 206/255, green: 68/255, blue: 96/255, alpha: 1)
cell.ageLabel.textColor = isMan ? manColor : womanColor
cell.ageLabel.text = String(format: "%i", model.age.integerValue)
cell.textView.userInteractionEnabled = false
return cell
}

Check all views in the cell, I think you put your identifier in the wrong place.

Related

Swift Playground UITable View Cell not resizing after I add a subview

the table view loads
the sub view loads but you can see it is over other cells
sometimes the sub view loads but other cells are on top of it
I have a UITableView, and when the user touches a row a subview gets added to the screen. When they click another row, the last subview disappears (and the row should shrink back down to its normal size). The subview displays perfectly (and goes away when another row is clicked), but it hangs out of the row and covers some of the other options. Also, when the table view reloads after screen rotations, the subview ends up behind the other rows of the table.
I want the row with the subview to resize so that it matches the frame of the subview. Also, each subview is a different size depending on the text and images included in it. Because of this I have tried using auto layouts and UITableViewAutomaticDimension, but nothing seems to be working.
I am including my UITableViewController so you can see what I have and can steer me in the right direction.
class TableViewController : UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
tableView.backgroundColor = #colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
self.tableView.estimatedRowHeight = rowHeight
return filmsToDisplay.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var currentFilm = filmsToDisplay[indexPath.row]
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.selectionStyle = .none
cell.textLabel?.text = "\(currentFilm.year) - \(currentFilm.movieTitle)"
cell.textLabel?.textColor = #colorLiteral(red: 0.254901975393295, green: 0.274509817361832, blue: 0.301960796117783, alpha: 1.0)
cell.textLabel?.font = UIFont.systemFont(ofSize: fontSize)
cell.textLabel?.sizeToFit()
cell.backgroundColor = #colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
cell.contentView.backgroundColor = #colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
let accessory = makeChart(currentFilm: filmsToDisplay[indexPath.row])
cell.contentView.addSubview(accessory)
accessory.translatesAutoresizingMaskIntoConstraints = false
accessory.trailingAnchor.constraint(equalTo:cell.contentView.trailingAnchor).isActive = true
accessory.topAnchor.constraint(equalTo: cell.contentView.topAnchor).isActive = true
accessory.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor).isActive = true
accessory.widthAnchor.constraint(equalTo: cell.contentView.widthAnchor, multiplier: nomBarWidth).isActive = true
cell.contentView.translatesAutoresizingMaskIntoConstraints=false
cell.contentView.leadingAnchor.constraint(equalTo:cell.leadingAnchor).isActive = true
cell.contentView.trailingAnchor.constraint(equalTo:cell.trailingAnchor).isActive = true
cell.contentView.topAnchor.constraint(equalTo:cell.topAnchor).isActive = true
cell.contentView.bottomAnchor.constraint(equalTo: cell.bottomAnchor).isActive = true
return cell
}
var lastSelectedCell : UITableViewCell? = nil
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let currentFilm = filmsToDisplay[indexPath.row]
var detailView = createView(film: currentFilm)
detailView.tag = 555
let selectedCell:UITableViewCell = tableView.cellForRow(at: indexPath)!
//get rid of last detail view
if let lastCell = lastSelectedCell {
for i in 0..<lastCell.contentView.subviews.count {
let content = lastCell.contentView.subviews[i]
if content.tag == 555{
content.removeFromSuperview()
}
}
}
selectedCell.contentView.addSubview(detailView)
detailView.translatesAutoresizingMaskIntoConstraints=false
detailView.leadingAnchor.constraint(equalTo:selectedCell.contentView.leadingAnchor).isActive = true
detailView.trailingAnchor.constraint(equalTo:selectedCell.contentView.trailingAnchor).isActive = true
detailView.topAnchor.constraint(equalTo:selectedCell.contentView.topAnchor).isActive = true
detailView.bottomAnchor.constraint(equalTo:detailView.subviews[detailView.subviews.count - 2].bottomAnchor).isActive = true
lastSelectedCell = selectedCell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}
The pieces of the sub view define their height as follows (there are more pieces but they all have the same kind of constraints:
//MOVIE TITLE BAR
let movieTitleBar = UIButton()
movieTitleBar.setTitleColor(#colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), for: UIControlState.normal)
movieTitleBar.setTitle(film.movieTitle, for: UIControlState.normal)
movieTitleBar.backgroundColor = #colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
movieTitleBar.alpha = 0.5
movieTitleBar.layer.borderWidth = outlineWidth
movieTitleBar.layer.borderColor = #colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
filmView.addSubview(movieTitleBar)
movieTitleBar.translatesAutoresizingMaskIntoConstraints = false
movieTitleBar.topAnchor.constraint(equalTo:filmView.topAnchor).isActive = true
movieTitleBar.heightAnchor.constraint(equalToConstant: rowHeight).isActive = true
movieTitleBar.leadingAnchor.constraint(equalTo:filmView.leadingAnchor).isActive = true
movieTitleBar.trailingAnchor.constraint(equalTo:filmView.trailingAnchor).isActive = true
//POSTER IMAGE
var poster = UIButton()
isPoster = false
if let posterImg = film.image {
if let url = NSURL(string:posterImg){
if let data = NSData(contentsOf:url as URL){
film.poster = UIImage(data:data as Data)
poster.setImage(film.poster, for: UIControlState.normal)
isPoster = true
filmView.addSubview(poster)
}
}
}
//BRIEF DESCRIPTION LABEL
let briefDescriptionBar = UILabel()
briefDescriptionBar.backgroundColor = film.colorUI
briefDescriptionBar.alpha = 0.8
briefDescriptionBar.text = "\(film.year) - \(film.briefDescription)"
briefDescriptionBar.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
briefDescriptionBar.numberOfLines = 0
briefDescriptionBar.textAlignment = .center
filmView.addSubview(briefDescriptionBar)
briefDescriptionBar.translatesAutoresizingMaskIntoConstraints = false
briefDescriptionBar.leadingAnchor.constraint(equalTo:movieTitleBar.leadingAnchor).isActive = true
briefDescriptionBar.topAnchor.constraint(equalTo:movieTitleBar.bottomAnchor).isActive = true
if isPoster == true {
poster.translatesAutoresizingMaskIntoConstraints = false
poster.topAnchor.constraint(equalTo:movieTitleBar.bottomAnchor).isActive = true
poster.trailingAnchor.constraint(equalTo:movieTitleBar.trailingAnchor).isActive = true
poster.widthAnchor.constraint(equalTo:filmView.widthAnchor, multiplier:nomBarWidth).isActive = true
let aspect = (nomBarWidth * 41) / 27
poster.heightAnchor.constraint(equalTo: filmView.widthAnchor, multiplier: aspect).isActive = true
briefDescriptionBar.trailingAnchor.constraint(equalTo:poster.leadingAnchor).isActive = true
briefDescriptionBar.bottomAnchor.constraint(equalTo:poster.bottomAnchor).isActive = true
}
else {
briefDescriptionBar.widthAnchor.constraint(equalTo:filmView.widthAnchor).isActive = true
briefDescriptionBar.heightAnchor.constraint(equalTo:movieTitleBar.heightAnchor, multiplier : 2).isActive = true
}
Your problem is that you don't give a height constraint for the subviews you add , you only hook leading ,trailing , top and bottom but the contentView expects it's height from inner subviews ( if they don't have intrinsic content size like labels / buttons ) , also no need for this part of code
cell.contentView.translatesAutoresizingMaskIntoConstraints=false
cell.contentView.leadingAnchor.constraint(equalTo:cell.leadingAnchor).isActive = true
cell.contentView.trailingAnchor.constraint(equalTo:cell.trailingAnchor).isActive = true
cell.contentView.topAnchor.constraint(equalTo:cell.topAnchor).isActive = true
cell.contentView.bottomAnchor.constraint(equalTo: cell.bottomAnchor).isActive = true
Also there should be only one view inside to the contentView that is connected to the bottom , if you add more than one , then you'll get conflicts if both views are also hooked to top of it , so you have to break last view bottom constraint before hooking a new one

iOS Swift TableviewCell issue

I have a strange problem with tableView cell.
when I scroll tableView and cell disappear and back again to the cell I understand that tableView add similar cell exactly on cell.
for example look at the picture . 3 exact text add on each other.
cellForRowAtIndexPath function :
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
if indexPath.row == 0 {
let reviewNumber = UILabel()
if (self.book.review_count == 0) {
reviewNumber.text = "\(self.lang.book["no_review"]!)"
}
if (self.book.review_count > 0) {
reviewNumber.text = "\(self.book.review_count!) \(self.lang.general["review"]!)"
}
reviewNumber.textAlignment = .Right
reviewNumber.font = UIFont(name: "Vazir", size: 14)
reviewNumber.numberOfLines = 0
reviewNumber.translatesAutoresizingMaskIntoConstraints = false
reviewNumber.textColor = UIColor.grayColor()
cell.contentView.addSubview(reviewNumber)
let voteIcon = UIImageView()
voteIcon.image = UIImage(named: "vote-icn")
voteIcon.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(voteIcon)
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[v0(24)]-|",options: [],metrics: nil,views: ["v0" : voteIcon]))
let reviewIcon = UIImageView()
reviewIcon.image = UIImage(named: "review-icn")
reviewIcon.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(reviewIcon)
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[v0(24)]-|",options: [],metrics: nil,views: ["v0" : reviewIcon]))
let voteNumber = UILabel()
voteNumber.text = " ۴.۵ از ۱۶۵۴رأی"
voteNumber.textAlignment = .Left
voteNumber.font = UIFont(name: "Vazir", size: 14)
voteNumber.numberOfLines = 0
voteNumber.translatesAutoresizingMaskIntoConstraints = false
voteNumber.textColor = UIColor.grayColor()
cell.contentView.addSubview(voteNumber)
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-3-[v0]-3-|",options: [],metrics: nil,views: ["v0" : reviewNumber]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-3-[v0]-3-|",options: [],metrics: nil,views: ["v0" : voteNumber]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-35-[v0]-8-[v1(25)]",options: [],metrics: nil,views: ["v0" : voteNumber, "v1" : voteIcon, "v2" : reviewNumber, "v3" : reviewIcon]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[v2]-8-[v3(25)]-35-|",options: [],metrics: nil,views: ["v0" : voteNumber, "v1" : voteIcon, "v2" : reviewNumber, "v3" : reviewIcon]))
}
if indexPath.row == 1 {
let userBookStatusButtn = UIButton(type: .Custom)
userBookStatusButtn.setTitle("خواهم خواند", forState: .Normal)
userBookStatusButtn.alpha = 0.2
userBookStatusButtn.titleLabel?.font = UIFont(name: "Vazir", size: 14)
userBookStatusButtn.setTitleColor(UIColor.whiteColor(), forState: .Normal)
// userBookStatusButtn.setImage(UIImage(named: "vote-icn"), forState: .Normal)
userBookStatusButtn.translatesAutoresizingMaskIntoConstraints = false
userBookStatusButtn.backgroundColor = UIColor(red:0.0/256.0 ,green:150.0/256.0, blue:136.0/256.0 ,alpha:1 )
cell.contentView.addSubview(userBookStatusButtn)
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-20-[v0(48)]-20-|",options: [],metrics: nil,views: ["v0" : userBookStatusButtn]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-35-[v0]-35-|",options: [],metrics: nil,views: ["v0" : userBookStatusButtn]))
}
if indexPath.row == 2 {
let topBorder = UIView()
topBorder.translatesAutoresizingMaskIntoConstraints = false
topBorder.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
cell.contentView.addSubview(topBorder)
let bottomBorder = UIView()
bottomBorder.translatesAutoresizingMaskIntoConstraints = false
bottomBorder.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
cell.contentView.addSubview(bottomBorder)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
paragraphStyle.baseWritingDirection = .RightToLeft
guard let descriptionStr = self.book.description else {return cell}
let attrString = NSMutableAttributedString(string: descriptionStr)
attrString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSMakeRange(0, attrString.length))
let description = UILabel()
description.attributedText = attrString
description.textAlignment = .Justified
description.font = UIFont(name: "Vazir", size: 14)
description.numberOfLines = 0
description.translatesAutoresizingMaskIntoConstraints = false
description.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.contentView.addSubview(description)
let title = UILabel()
title.text = "\(self.lang.book["summery"]!)"
title.alpha = 0.2
title.textAlignment = .Center
title.font = UIFont(name: "Vazir-Bold", size: 16)
title.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(title)
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[v0]-|",options: [.AlignAllCenterX],metrics: nil,views: ["v0" : title]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[v0]-20-|",options: [],metrics: nil,views: ["v0" : description]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[v1]-44-[v0]",options: [],metrics: nil,views: ["v0" : description,"v1" : title ]))
cell.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[v0]-8-|",options: [],metrics: nil,views: ["v0" : description,"v1" : title ]))
}
cell.textLabel?.text = nil
return cell
}
I get data from son file with Alamofire and reloadData :
func tableRefresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.bookDetailTableView.reloadData()
})
}
what's my problem?
thanks guys.
You made a classical error when using iOS cells.
(I am a teacher, so I see this kind of error frequently... don't worry..)
some Considerations:
1) NEVER add a label to a cell. Doing so, very time a cell is reused, previous label stays here, and a new label is added
2) as label are transparent, you will see all text overlapped..
3) You are leaking memory, as no one will detach/ release labels.
so the way can be:
A)Simple for simple case
use TAGS, as Apple did on old days of cells..
(code i
make some defines:
let TEXT_TAG = 2000
add label if not present, if present get it vi TAG:
let cell = tableView.dequeueReusableCell(withIdentifier: REUSE, for: indexPath )
let text = "my text..."
if let label = cell.viewWithTag(TEXT_TAG) as? UILabel{
label.text = text
}else{
let frame = CGRect(x: 100, y: 20, width: 50, height: 50)
let label = UILabel(frame: frame)
label.text = text
cell.addSubview(label)
}
B) make a custom cell...
class CustomViewCell: UITableViewCell {
var label: UILabel?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let frame = CGRect(x: 100, y: 20, width: 50, height: 50)
let label = UILabel(frame: frame)
self.addSubview(label)
}
in controller simply:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: REUSE,
for: indexPath ) as! CustomViewCell
cell.label = "my text"
I get your problem,you get the cell from tableView reuseable pool.The first problem,if you want change UITableViewCell View,you need to creat a son class of it.I get a function to fix it.
I use Stackoverflow first time,I don't know where can I put my code,so I write it under this sentence.
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
for let item in cell.contentView.subviews {
item.removeFromSuperView();
}
And then using your code,it should help you.

UITableView mixing values because of reusable cells

I have a problem when I scroll in my tableview which contains elements that can be scrolled horizontal it is mixing the values.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : RoundWorkoutCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! RoundWorkoutCell
let tmpCell = cell
print(tmpCell)
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! RoundWorkoutCell;
}
let exerviseName = RoundLabels[indexPath.row]
if(indexPath.row == 0){
for countMe in 0..<self.round_1_exercises.count {
if(countMe<1){
roundPosition1.append(5)
}else{
roundPosition1.append(115+roundPosition1[countMe-1])
}
scrollerSize = 115+roundPosition1[countMe]
}
}else if(indexPath.row == 1){
for countMe in 0..<self.round_2_exercises.count {
if(countMe<1){
roundPosition2.append(5)
}else{
roundPosition2.append(115+roundPosition2[countMe-1])
}
scrollerSize = 115+roundPosition2[countMe]
}
}else if(indexPath.row == 2){
for countMe in 0..<self.round_3_exercises.count {
if(countMe<1){
roundPosition3.append(5)
}else{
roundPosition3.append(115+roundPosition3[countMe-1])
}
scrollerSize = 115+roundPosition3[countMe]
}
}......
cell.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(scrollerSize),115)
cell.RoundExercise_Cell_ScrollView.showsHorizontalScrollIndicator = true
cell.RoundExercise_Cell_ScrollView.indicatorStyle = .Default
if(indexPath.row==0){
for index in 0..<self.round_1_exercises.count {
print("Round position 1 \(self.roundPosition1[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition1[index],y: 5, width:110, height: 110 ))
imageView.backgroundColor = UIColor.whiteColor()
cell.RoundExercise_Cell_ScrollView.addSubview(imageView)
let label1: UILabel = UILabel()
label1.frame = CGRect(x:roundPosition1[index],y: 5, width:110, height: 20 )
label1.textColor = UIColor(red:17/255.0, green: 22/255.0, blue: 40/255.0, alpha:1.0)
label1.textAlignment = NSTextAlignment.Center
label1.font = UIFont(name: "OpenSans-CondensedLight", size: 14)
label1.text = exerciseInfo.exercise_name(self.round_1_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition1[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_1_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_1_exercises[index] as? String, forState: .Normal)
button.setTitleColor(UIColor(red:0/255,green:0/255,blue:0/255,alpha:0.0), forState: .Normal)
button.addTarget(self, action: "buttonClick:", forControlEvents: .TouchUpInside)
cell.RoundExercise_Cell_ScrollView.addSubview(button)
let label: UILabel = UILabel()
label.frame = CGRect(x:roundPosition1[index],y: 115, width:110, height: 20 )
label.font = UIFont(name: "OpenSans", size: 14)
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = self.round_1_decoration[index] as? String
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
}else if(indexPath.row == 1){
for index in 0..<self.round_2_exercises.count {
print("Round position 2 \(self.roundPosition2[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition2[index],y: 5, width:110, height: 110 ))
imageView.backgroundColor = UIColor.whiteColor()
cell.RoundExercise_Cell_ScrollView.addSubview(imageView)
let label1: UILabel = UILabel()
label1.frame = CGRect(x:roundPosition2[index],y: 5, width:110, height: 20 )
label1.textColor = UIColor(red:17/255.0, green: 22/255.0, blue: 40/255.0, alpha:1.0)
label1.textAlignment = NSTextAlignment.Center
label1.font = UIFont(name: "OpenSans-CondensedLight", size: 14)
label1.text = exerciseInfo.exercise_name(self.round_2_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition2[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_2_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_2_exercises[index] as? String, forState: .Normal)
button.setTitleColor(UIColor(red:0/255,green:0/255,blue:0/255,alpha:0.0), forState: .Normal)
button.addTarget(self, action: "buttonClick:", forControlEvents: .TouchUpInside)
cell.RoundExercise_Cell_ScrollView.addSubview(button)
let label: UILabel = UILabel()
label.frame = CGRect(x:roundPosition2[index],y: 115, width:110, height: 20 )
label.font = UIFont(name: "OpenSans", size: 14)
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = self.round_2_decoration[index] as? String
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
}.....
cell.RoundExercise_Cell_Label.text = exerviseName
return cell as RoundWorkoutCell
}
Here is the custom cell class
class RoundWorkoutCell: UITableViewCell {
#IBOutlet var RoundExercise_Cell_Label: UILabel!
#IBOutlet var RoundExercise_Cell_ScrollView: UIScrollView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.RoundExercise_Cell_Label.text = ""
self.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(0),115)
}
I have placed this thread before but no one answered.I need to fix this.I have finished my whole app and this is left.I know that i have to use somehow prepareForReuse() but am not sure how,or if i could disable this reusable cells.
Thanks
The cells are reused to save on memory, this means that you need to recycle them properly to stop old data from being shown. You can do this by adding the prepareForReuse() function into your tableviewCell. In here you will need to set image outlets to be empty i.e by setting it to UIImage(). You will need to do the same with all outlets. This will ensure that old data that is not relevant will not be shown.
Example:
override func prepareForReuse() {
//myOutletName = myNilValue
super.prepareForReuse()
}
If you don't want to reuse cells, you can simply remove the call to dequeueReusableCellWithIdentifier. Try replacing these lines:
var cell : RoundWorkoutCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! RoundWorkoutCell
let tmpCell = cell
print(tmpCell)
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! RoundWorkoutCell;
}
With this:
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! RoundWorkoutCell;
This approach doesn't reuse cells and will be less performant and will leak memory.
A better approach would be to construct the cells once and then reuse them, instead of rebuilding them in cellForRowAtIndexPath method. For example, if you design the cells in the NIB (as you are doing now), there's no need to add buttons and labels again by code, you can simply change the contents and hide those that are not needed.
Then, on prepareForReuse (or even at the beginning of cellForRowAtIndexPath), you reset the content of the row to the initial state.
class RoundWorkoutCell: UITableViewCell {
#IBOutlet var RoundExercise_Cell_Label: UILabel!
#IBOutlet var RoundExercise_Cell_ScrollView: UIScrollView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.RoundExercise_Cell_Label.text = ""
self.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(0),115)
}
override func prepareForReuse() {
//myOutletName = myNilValue
self.RoundExercise_Cell_Label.text = ""
self.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(0),115)
for subview in RoundExercise_Cell_ScrollView.subviews {
print(subview)
subview.removeFromSuperview()
}
super.prepareForReuse()
}
}
#Swinny89 was at right point thank you for that, but I can add more detail about prepareForReuse method. If you remove all your reusing cell data in that method, the performance will reduce. On the other hand, you can hide your variables in prepareForReuse method, and make them visible in your cell init method.
For example as the way I did:
override func prepareForReuse() {
if(commentLabels != nil) {
for item in commentLabels {
item.hidden = true
}
}
super.prepareForReuse()
}
In other method I make the visible with if check:
if(commentLabels == nil) {
// creating new labels and adding to commentLabels
} else { // it means reuse cell data and it has been hidden
// hidden = false
for item in commentLabels {
item.hidden = false
}
}

swift uitableviewCell repeat subviews

I have a UIButton in a uitableviewcell associated to a target:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! ProCell
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
This is the buttonClicked function:
func buttonClicked(sender:UIButton) {
let boton = sender as UIButton
let index = boton.tag
let buttonPosition: CGPoint = boton.convertPoint(CGPointZero, toView: self.tableView)
var indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! ProductoCell
cell.btn.setImage(UIImage (named: "rotacion-Null"), forState: UIControlState.Normal)
let indicador = UIActivityIndicatorView()
indicador.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
indicador.color = UIColor(red: 153.0/255.0, green: 0.0, blue: 0.0, alpha: 1.0)
indicador.startAnimating()
cell.btn.addSubview(indicador)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let datosEd = ed.search(product)
dispatch_async(dispatch_get_main_queue(), {
//update UI in main thread once the loading is completed.
indicador.stopAnimating()
indicador.hidesWhenStopped = true
let label2 = UILabel(frame: CGRect(x: 15 , y: -5, width: 16, height: 16))
label2.textAlignment = NSTextAlignment.Center
label2.font = UIFont.boldSystemFontOfSize(13.0)
label2.backgroundColor = UIColor (red: 0.85, green: 0.20, blue: 0.33, alpha: 1.0)
label2.textColor = UIColor.whiteColor()
label2.layer.masksToBounds = true
label2.layer.cornerRadius = 8
let rowData = datosEd[0] as! NSDictionary
if rowData["art"] as! String == "No Results" {
label2.text = "0"
cell.contentView.addSubview(label2)
cell.btn.setImage(UIImage (named: "ed-25G"), forState: UIControlState.Normal)
} else {
label2.text = String(datosEd.count)
cell.btn.addSubview(label2)
cell.btn.setImage(UIImage (named: "ed-25R"), forState: UIControlState.Normal)
}
});
})
}
The problem is when I scroll down and scroll up back again, the subview(label2) is repeated in some cells.
Reading some responses think it has to do with the reuse of the cells, but I do not how to make the subviews are not repeated.
Some help, please... :-)

Custom UIImageView added to UItableview cell doesnot shift on on x-axis?

I am trying to give some margin on x-axis for a imageView that is set inside a tableView cell. But the imageView does not move. And I also tried same for a label. It does shift to the value I gave.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// cell.textLabel?.font = UIFont(name: label.font.fontName, size: 22)
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("myCell") as UITableViewCell
// cell.imageView?.image = UIImage(named: self.cellImgs[indexPath.row])
cell.textLabel?.text = self.cellTxtArrs[indexPath.row]
cell.textLabel?.textAlignment = NSTextAlignment.Right
cell.textLabel?.textColor = UIColor.whiteColor()
cell.backgroundColor = UIColor(red: 0.000, green: 0.400, blue: 0.404, alpha: 1.00)
cell.selectionStyle = UITableViewCellSelectionStyle.None
// var videoImgView:UIImageView = UIImageView(frame: CGRectMake(50, 10, 20, 30.0))
// let videoImage = UIImage(named: "accounts")
// videoImgView = UIImageView(image: videoImage)
// cell.contentView.addSubview(videoImgView)
var newLabel = UILabel(frame: CGRectMake(80, 0, 80, 30.0))
newLabel.text = "hello all"
newLabel.textColor = UIColor.redColor()
cell.contentView.addSubview(newLabel)
return cell
}
I have created a table view as
var tblView : UITableView = UITableView()
tblView.frame = CGRectMake(0, 168, 320-50 , 448)
tblView.separatorColor = UIColor.clearColor()
tblView.scrollEnabled = false
tblView.rowHeight = 39
self.addSubview(tblView)
tblView.delegate = self
tblView.dataSource = self
tblView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "myCell")
1) your code will cell.contentView.addSubview everytime that cellForRowAtIndexPath is called. You are not reusing cell properly .
2) Subclass UITableViewCell and add your "logic View code" inside there (right place to do it)
3) look at this: http://www.objc.io/issue-1/lighter-view-controllers.html
Please try to use this one i hope it helps you.
videoImgView = UIImageView(image: videoImage)
videoImgView.frame = CGRectMake(100, 10, 20, 30.0)
cell.contentView.addSubview(videoImgView)

Resources