UITableView mixing values because of reusable cells - ios

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
}
}

Related

UITableView with custom cells lags while scrolling

My problem is that UITableView lags quite a lot while scrolling.
This is what I am trying to achieve
Starting from the top I have a simple section header with only one checkbox and one UILabel. Under this header, you can see a custom cell with only one UILabel aligned to the center. This custom cell works like another header for the data that would be shown below (Basically a 3D array). Under these "headers" are custom cells that contain one multiline UILabel and under this label is a container for a variable amount of lines containing a checkbox and an UILabel. On the right side of the cell is also a button (blue/white arrow).
So this means the content is shown like this:
Section header (containing day and date)
Custom UITableViewCell = header (containing some header information)
Custom UITableViewCell (containing data to be shown)
Here is my code:
cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let (isHeader, headerNumber, semiResult) = checkIfIsHeader(section: indexPath.section, row: indexPath.row)
let row = indexPath.row
if isHeader {
let chod = objednavkaDny[indexPath.section].chody[headerNumber+1]
let cell = tableView.dequeueReusableCell(withIdentifier: cellHeaderReuseIdentifier, for: indexPath) as! ObjednavkyHeaderTableViewCell
cell.titleLabel.text = chod.popisPoradiJidla
cell.selectionStyle = .none
return cell
}else{
let chod = objednavkaDny[indexPath.section].chody[headerNumber]
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! ObjednavkyTableViewCell
cell.updateData(objednavka: chod.objednavky[row-semiResult], canSetAmount: self.typDialogu == 3)
return cell
}
}
checkIfIsHeader:
func checkIfIsHeader(section: Int, row: Int) -> (Bool, Int, Int){
if let cachedResult = checkIfHeaderCache[section]?[row] {
return (cachedResult[0] == 1, cachedResult[1], cachedResult[2])
}
var isHeader = false
var semiResult = 0
var headerNumber = -1
for (index, chod) in objednavkaDny[section].chody.enumerated() {
let sum = chod.objednavky.count
if row == semiResult {
isHeader = true
break
}else if row < semiResult {
semiResult -= objednavkaDny[section].chody[index-1].objednavky.count
break
}else {
headerNumber += 1
semiResult += 1
if index != objednavkaDny[section].chody.count - 1 {
semiResult += sum
}
}
}
checkIfHeaderCache[section] = [Int:[Int]]()
checkIfHeaderCache[section]![row] = [isHeader ? 1 : 0, headerNumber, semiResult]
return (isHeader, headerNumber, semiResult)
}
and the main cell that shows the data:
class ObjednavkyTableViewCell: UITableViewCell {
lazy var numberTextField: ObjednavkyTextField = {
let textField = ObjednavkyTextField()
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
let mealLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = .black
label.textAlignment = .left
label.font = UIFont(name: ".SFUIText", size: 15)
label.numberOfLines = 0
label.backgroundColor = .white
label.isOpaque = true
return label
}()
lazy var detailsButton: UIButton = {
let button = UIButton(type: .custom)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(named: "arrow-right")?.withRenderingMode(.alwaysTemplate), for: .normal)
button.imageView?.tintColor = UIColor.custom.blue.classicBlue
button.imageView?.contentMode = .scaleAspectFit
button.contentHorizontalAlignment = .right
button.imageEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0)
button.addTarget(self, action: #selector(detailsButtonPressed), for: .touchUpInside)
button.backgroundColor = .white
button.isOpaque = true
return button
}()
let pricesContainerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.isOpaque = true
return view
}()
var canSetAmount = false {
didSet {
canSetAmount ? showNumberTextField() : hideNumberTextField()
}
}
var shouldShowPrices = false {
didSet {
shouldShowPrices ? showPricesContainerView() : hidePricesContainerView()
}
}
var pricesContainerHeight: CGFloat = 0
private let priceViewHeight: CGFloat = 30
var mealLabelLeadingConstraint: NSLayoutConstraint?
var mealLabelBottomConstraint: NSLayoutConstraint?
var pricesContainerViewHeightConstraint: NSLayoutConstraint?
var pricesContainerViewBottomConstraint: NSLayoutConstraint?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func detailsButtonPressed() {
}
func updateData(objednavka: Objednavka, canSetAmount: Bool) {
self.canSetAmount = canSetAmount
if let popisJidla = objednavka.popisJidla, popisJidla != "", popisJidla != " " {
self.mealLabel.text = popisJidla
}else{
self.mealLabel.text = objednavka.nazevJidelnicku
}
if objednavka.objects.count > 1 {
shouldShowPrices = true
setPricesStackView(with: objednavka.objects)
checkIfSelected(objects: objednavka.objects)
}else{
shouldShowPrices = false
self.numberTextField.text = String(objednavka.objects[0].pocet)
//setSelected(objednavka.objects[0].pocet > 0, animated: false)
objednavka.objects[0].pocet > 0 ? setSelectedStyle() : setDeselectedStyle()
}
}
//---------------
func checkIfSelected(objects: [ObjednavkaObject]) {
var didChangeSelection = false
for object in objects { // Checks wether cell should be selected or not
if object.pocet > 0 {
setSelected(true, animated: false)
setSelectedStyle()
didChangeSelection = true
break
}
}
if !didChangeSelection {
setSelected(false, animated: false)
setDeselectedStyle()
}
}
//--------------
func showNumberTextField() {
numberTextField.isHidden = false
mealLabelLeadingConstraint?.isActive = false
mealLabelLeadingConstraint = mealLabel.leadingAnchor.constraint(equalTo: numberTextField.trailingAnchor, constant: 10)
mealLabelLeadingConstraint?.isActive = true
}
func hideNumberTextField() {
numberTextField.isHidden = true
mealLabelLeadingConstraint?.isActive = false
mealLabelLeadingConstraint = mealLabel.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor, constant: 0)
mealLabelLeadingConstraint?.isActive = true
}
func showPricesContainerView() {
hideNumberTextField()
pricesContainerView.isHidden = false
mealLabelBottomConstraint?.isActive = false
pricesContainerViewBottomConstraint?.isActive = true
}
func hidePricesContainerView() {
pricesContainerView.isHidden = true
pricesContainerViewBottomConstraint?.isActive = false
mealLabelBottomConstraint?.isActive = true
}
//--------------
func setSelectedStyle() {
self.backgroundColor = UIColor.custom.blue.classicBlue
mealLabel.textColor = .white
mealLabel.backgroundColor = UIColor.custom.blue.classicBlue
for subview in pricesContainerView.subviews where subview is ObjednavkyPriceView {
let priceView = (subview as! ObjednavkyPriceView)
priceView.titleLabel.textColor = .white
priceView.checkBox.backgroundColor = UIColor.custom.blue.classicBlue
priceView.titleLabel.backgroundColor = UIColor.custom.blue.classicBlue
priceView.backgroundColor = UIColor.custom.blue.classicBlue
}
pricesContainerView.backgroundColor = UIColor.custom.blue.classicBlue
detailsButton.imageView?.tintColor = .white
detailsButton.backgroundColor = UIColor.custom.blue.classicBlue
}
func setDeselectedStyle() {
self.backgroundColor = .white
mealLabel.textColor = .black
mealLabel.backgroundColor = .white
for subview in pricesContainerView.subviews where subview is ObjednavkyPriceView {
let priceView = (subview as! ObjednavkyPriceView)
priceView.titleLabel.textColor = .black
priceView.checkBox.backgroundColor = .white
priceView.titleLabel.backgroundColor = .white
priceView.backgroundColor = .white
}
pricesContainerView.backgroundColor = .white
detailsButton.imageView?.tintColor = UIColor.custom.blue.classicBlue
detailsButton.backgroundColor = .white
}
//-----------------
func setPricesStackView(with objects: [ObjednavkaObject]) {
let subviews = pricesContainerView.subviews
var subviewsToDelete = subviews.count
for (index, object) in objects.enumerated() {
subviewsToDelete -= 1
if subviews.count - 1 >= index {
let priceView = subviews[index] as! ObjednavkyPriceView
priceView.titleLabel.text = object.popisProduktu // + " " + NSNumber(value: object.cena).getFormattedString(currencySymbol: "Kč") // TODO: currencySymbol
priceView.canSetAmount = canSetAmount
priceView.count = object.pocet
priceView.canOrder = (object.nelzeObj == nil || object.nelzeObj == "")
}else {
let priceView = ObjednavkyPriceView(frame: CGRect(x: 0, y: CGFloat(index) * priceViewHeight + CGFloat(index * 5), width: pricesContainerView.frame.width, height: priceViewHeight))
pricesContainerView.addSubview(priceView)
priceView.titleLabel.text = object.popisProduktu // + " " + NSNumber(value: object.cena).getFormattedString(currencySymbol: "Kč") // TODO: currencySymbol
priceView.numberTextField.delegate = self
priceView.canSetAmount = canSetAmount
priceView.canOrder = (object.nelzeObj == nil || object.nelzeObj == "")
priceView.count = object.pocet
pricesContainerHeight += ((index == 0) ? 30 : 35)
}
}
if subviewsToDelete > 0 { // Deletes unwanted subviews
for _ in 0..<subviewsToDelete {
pricesContainerView.subviews.last?.removeFromSuperview()
pricesContainerHeight -= pricesContainerHeight + 5
}
}
if pricesContainerHeight < 0 {
pricesContainerHeight = 0
}
pricesContainerViewHeightConstraint?.constant = pricesContainerHeight
}
func setupView() {
self.layer.shouldRasterize = true
self.layer.rasterizationScale = UIScreen.main.scale
self.backgroundColor = .white
contentView.addSubview(numberTextField)
contentView.addSubview(mealLabel)
contentView.addSubview(detailsButton)
contentView.addSubview(pricesContainerView)
setupConstraints()
}
func setupConstraints() {
numberTextField.anchor(leading: readableContentGuide.leadingAnchor, size: CGSize(width: 30, height: 30))
numberTextField.centerYAnchor.constraint(equalTo: mealLabel.centerYAnchor).isActive = true
detailsButton.anchor(trailing: readableContentGuide.trailingAnchor, size: CGSize(width: 30, height: 30))
detailsButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
mealLabel.anchor(top: contentView.topAnchor, trailing: detailsButton.leadingAnchor, padding: .init(top: 10, left: 0, bottom: 0, right: -10))
mealLabelBottomConstraint = mealLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10)
mealLabelBottomConstraint?.priority = UILayoutPriority(rawValue: 999)
pricesContainerView.anchor(top: mealLabel.bottomAnchor, leading: readableContentGuide.leadingAnchor, trailing: detailsButton.leadingAnchor, padding: .init(top: 10, left: 0, bottom: 0, right: -10))
pricesContainerViewBottomConstraint = pricesContainerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10)
pricesContainerViewBottomConstraint?.priority = UILayoutPriority(rawValue: 999)
pricesContainerViewHeightConstraint = pricesContainerView.heightAnchor.constraint(equalToConstant: 0)
pricesContainerViewHeightConstraint?.priority = UILayoutPriority(rawValue: 999)
pricesContainerViewHeightConstraint?.isActive = true
}
}
To conclude how it is done:
tableView.rowHeight is set to UITableViewAutomaticDymension
inside cellForRowAt I get the data from an array and give it to the
cell
all the cells are set up in code using constraints
all the views have set isOpaque = true
heights of the cells are cached
cells are set to rasterize
I also noticed that it lags at certain scroll levels and that sometimes it works just fine and sometimes it lags a lot.
Despite all of the optimization I have done, the tableView still lags while scrolling.
Here is a screenshot from Instruments
Any tip how to improve the scrolling performance is highly appreciated!
(I might have forgotten to include some code/information so feel free to ask me in the comments.)
I can't tell you where the lag happens exactly but when we are talking about lagging during scrolling, it's related to your cellForRowAt delegate method. What happends is that too many things are going on within this method and it's called for every cells that are displaying & going to display. I see that your are trying to cache the result by checkIfHeaderCache but still, there is a for loop at the very beginning to determine header cell.
Suggestions:
I don't know where you get data (objednavkaDny) from but right after you get the data, do a full loop through and determin cell type one by one, and save the result some where base on your design. During this loading time, you can show some loading message on the screen. Then, within the cellForRow method, you should be just simply using things like
if (isHeader) {
render header cell
} else {
render other cell
}
Bottom line:
cellForRow method is not designed to handle heavy calculations, and it will slow down the scrolling if you do so. This method is for assigning values to the cached table view cell only and that's the only thing it is good at.

Adding custom button in custom table view cell , and at a time only one button of cell should be selected in swift, could anyone help me out for this?

Please check out my code of custom UITableview cell, I am facing the problem because tableview delegate did select method is not called.
My Code Here:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier, forIndexPath: indexPath) as! DpMarginRptTableViewCell
cell.selectionStyle = .None
if dataSource.count > 1
{
let dpMarginModel : DPSRDPDetailModel = self.dataSource.objectAtIndex(indexPath.row) as! DPSRDPDetailModel
cell.scriptLabel.text = "\(dpMarginModel.scripCode)"
cell.dpQtyLabel.text = "\(dpMarginModel.dpBalanceAC)"
cell.haricutLabel.text = String(format: "%.2f",Float(dpMarginModel.valueAfterHairCut)/100) //"\(dpMarginModel.valueAfterHairCut)"
cell.transferTextfield.tag = indexPath.row
cell.transferTextfield.text = "\(dpMarginModel.transferText)"
cell.transferTextfield.delegate = self
cell.transferTextfield.layer.borderWidth = 1.0
cell.transferTextfield.layer.borderColor = UIColor.blackColor().CGColor
cell.radioButton1.tag = indexPath.row
cell.radioButton1.addTarget(self, action: #selector(DpMarginView.buttonTapped(_:)), forControlEvents: .TouchUpInside)
cell.radioButton1.setTitle(String.iconWithName(.radioUnchecked), forState: UIControlState.Normal)
cell.radioButton1.setTitle(String.iconWithName(.radioChecked), forState: UIControlState.Selected)
}
}
CustomTableViewCell Class code
class CustomTableViewCell : UITableViewCell {
var screenWidth:CGFloat!
var screenHeight:CGFloat!
var radioButton1 : UIButton!
var scriptLabel : UILabel!
var dpQtyLabel:UILabel!
var haricutLabel:UILabel!
var transferTextfield: UITextField!
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
let screenSize:CGRect = UIScreen.mainScreen().bounds
self.screenWidth = screenSize.width
self.screenHeight = screenSize.height
let boldFont = UIFont(name: "Helvetica Neue", size: 11)?.fontDescriptor().fontDescriptorWithSymbolicTraits(UIFontDescriptorSymbolicTraits.TraitBold)
radioButton1 = UIButton(frame: CGRectMake(0, 5, 30, 40))
radioButton1.tag = 101
radioButton1.titleLabel?.font = UIFont(name: "Icomoon", size: 18)
radioButton1.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
radioButton1.setTitleColor(UIColor.blackColor(), forState: UIControlState.Selected)
self.scriptLabel = UILabel.init(frame: CGRectMake(radioButton1.frame.size.width + 5, 5,(screenWidth/4) , 40))
self.scriptLabel.textAlignment = .Left
self.scriptLabel.font = UIFont(descriptor: boldFont!, size: 11)
self.dpQtyLabel = UILabel.init(frame: CGRectMake(scriptLabel.frame.origin.x + scriptLabel.frame.size.width, 5, (screenWidth/4), 40))
self.dpQtyLabel.textAlignment = .Left
self.dpQtyLabel.font = UIFont(name: "HelveticaNeue", size: 11)
self.haricutLabel = UILabel.init(frame: CGRectMake(dpQtyLabel.frame.origin.x + dpQtyLabel.frame.size.width, 5, (screenWidth/4), 40))
self.haricutLabel.textAlignment = .Left
self.haricutLabel.font = UIFont(name: "HelveticaNeue", size: 11)
self.transferTextfield = UITextField.init(frame: CGRectMake((haricutLabel.frame.origin.x + haricutLabel.frame.size.width)-20, 5, (screenWidth/4) - 20, 40))
self.transferTextfield.textAlignment = .Center
self.transferTextfield.font = UIFont(name: "HelveticaNeue", size: 11)
self.transferTextfield.keyboardType = .NumberPad
self.contentView.addSubview(self.radioButton1)
self.contentView.addSubview(self.scriptLabel)
self.contentView.addSubview(self.dpQtyLabel)
self.contentView.addSubview(self.haricutLabel)
self.contentView.addSubview(self.transferTextfield)
self.contentView.backgroundColor = UIColor.clearColor()
}
}
I want to add custom button in custom table view cell, and at a time only one button of cell should be selected in swift, could anyone help me out for this?
Thanks
See this line cell.radioButton1.addTarget(self, action: #selector(DpMarginView.buttonTapped(_:)), forControlEvents: .TouchUpInside) shouldn't be there in cellForRowAtIndexPath. Instead you should put that line in CustomTableViewCell when you are creating that button. And call that buttonTapped action inside CustomTableViewCell itself.
Then you need to use delegate method for passing message form this custom cell to your UIViewVontroller containing this tableview.
So your CustomTableViewCell will start like this:-
protocol CustomDelegate: class {
func buttonTouchedAction()
}
class CustomTableViewCell : UITableViewCell {
weak var delegate: CustomDelegate?
var screenWidth:CGFloat!
var screenHeight:CGFloat!
.
.
.
}
And in your cellForRowAtIndexPath, instead of adding target, use this code:-
cell.delegate = self
And at the bottom of your viewController add this. I am assuming your viewController name is CustomViewController:-
extension CustomViewController: CustomDelegate {
fun buttonTouchedAction() {
// Do your action here
}
}
NB. Why you are setting the tag as 101 for the radioButton1 in tableViewCell subclass while you are changing it to indexPath.row in viewController's subclass? This entire setting tag thing doesn't serve any purpose here.

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.

iOS Swift performSegueWithIdentifier for sending data

I want to send data to my adapter view where it should put correct data to it.I send the data over the "exerciseName" variable.In the print its correct but when it reaches the destination the second view it becomes nil.Please help
var workoutInfoData : WorkoutInfo!
var RoundLabels = ["Round 1","Round 2","Round 3","Round 4","Round 5","Round 6","Round 7","Round 8","Round 9","Round 10","Round 11","Round 12"]
var exerciseName:String = ""
var roundPosition = [Int]()
let numberOfExercises = 1
var scrollerSize = 0
override func viewDidLoad() {
super.viewDidLoad()
//self.workoutTitle.title! = workoutInfoData.workout_name
navigationItem.title = workoutInfoData.workout_name
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func workoutBack(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: {});
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return RoundLabels.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : RoundWorkoutCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! RoundWorkoutCell
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! RoundWorkoutCell;
}
let exerviseName = RoundLabels[indexPath.row]
if(indexPath.row == 1){
}
for countMe in 0..<self.numberOfExercises {
if(countMe<1){
roundPosition.append(5)
}else{
roundPosition.append(115+roundPosition[countMe-1])
}
scrollerSize = 115+roundPosition[countMe]
}
cell.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(scrollerSize),115)
cell.RoundExercise_Cell_ScrollView.showsHorizontalScrollIndicator = true
cell.RoundExercise_Cell_ScrollView.indicatorStyle = .Default
for index in 0..<self.numberOfExercises {
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition[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:roundPosition[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 = "Pushups"
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: "sit_thrust") as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle("air_sit_front_raise", 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:roundPosition[index],y: 115, width:110, height: 20 )
label.font = UIFont(name: "OpenSans", size: 14)
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "30sec"
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
cell.RoundExercise_Cell_Label.text = exerviseName
return cell as RoundWorkoutCell
}
func buttonClick(sender:AnyObject){
exerciseName = String(sender.currentTitle)
//print(sender.currentTitle)
self.performSegueWithIdentifier("showExercise", sender:exerciseName)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showExercise" {
let vc = segue.destinationViewController as! ViewExerciseFromMenu
//vc.exerciseGet = UIImage(named: "sit_thrust")!
//vc.title = "SIT THRUSTS"
print(exerciseName)
vc.exerciseGet = exerciseName
navigationItem.title = "easy"
}
}
The adapter view
#IBOutlet var imageView: UIImageView!
#IBOutlet var musInvImageHolder: UIImageView!
var exerciseGet: String = ""
var image = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//var exerciseCurrent: String
print(exerciseGet)
switch(String(exerciseGet)){
case "air_sit_front_raise":
self.title = "AIR SIT FRONT RAISE"
musInvImageHolder.image = UIImage(named: "mus_inv_20")
let url = NSBundle.mainBundle().URLForResource("air_sit_front_raise", withExtension: "gif")!
let imageData = NSData(contentsOfURL: url)
imageView.image = UIImage.animatedImageWithData(imageData!)
break;
Here is the fix for it
#IBOutlet var roundExercisesTable: UITableView!
var workoutInfoData : WorkoutInfo!
var RoundLabels = ["Round 1","Round 2","Round 3","Round 4","Round 5","Round 6","Round 7","Round 8","Round 9","Round 10","Round 11","Round 12"]
var exerciseName:String? = ""
var myButtons: [Int : UIButton] = [:]
var roundPosition = [Int]()
let numberOfExercises = 1
var scrollerSize = 0
let exerciseInfo=ExercisesInfo()
override func viewDidLoad()
{
super.viewDidLoad()
//self.workoutTitle.title! = workoutInfoData.workout_name
navigationItem.title = workoutInfoData.workout_name
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func workoutBack(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: {});
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return RoundLabels.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : RoundWorkoutCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! RoundWorkoutCell
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as! RoundWorkoutCell;
}
let exerviseName = RoundLabels[indexPath.row]
if(indexPath.row == 1){
}
for countMe in 0..<self.numberOfExercises {
if(countMe<1){
roundPosition.append(5)
}else{
roundPosition.append(115+roundPosition[countMe-1])
}
scrollerSize = 115+roundPosition[countMe]
}
cell.RoundExercise_Cell_ScrollView.contentSize = CGSizeMake(CGFloat(scrollerSize),115)
cell.RoundExercise_Cell_ScrollView.showsHorizontalScrollIndicator = true
cell.RoundExercise_Cell_ScrollView.indicatorStyle = .Default
for index in 0..<self.numberOfExercises {
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition[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:roundPosition[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 = "Pushups"
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: "sit_thrust") as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle("air_sit_front_raise", 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:roundPosition[index],y: 115, width:110, height: 20 )
label.font = UIFont(name: "OpenSans", size: 14)
label.textColor = UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "30sec"
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
cell.RoundExercise_Cell_Label.text = exerviseName
return cell as RoundWorkoutCell
}
func buttonClick(sender:AnyObject){
exerciseName = sender.currentTitle
//print(sender.currentTitle)
self.performSegueWithIdentifier("showExercise", sender:exerciseName)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showExercise" {
let vc = segue.destinationViewController as! ViewExerciseFromMenu
//vc.exerciseGet = UIImage(named: "sit_thrust")!
//vc.title = "SIT THRUSTS"
print(exerciseName)
vc.exerciseGet = exerciseName!
navigationItem.title = exerciseInfo.hradnesExerciseDeterminer(exerciseName!)
}
}

Remove subviews from ScrollView Swift

I use a for-loop to create labels and buttons inside my scrollView.
Is it possible to remove all objects indside my scrollView? (I would like to update it with new content)
for peop in personArray{
scrollView.clearContent ??????
// Name label
var label: UILabel = UILabel()
label.frame = CGRectMake(8, CGFloat(nameHeight), 183, 21)
label.backgroundColor = UIColor.whiteColor()
label.textColor = UIColor(red: 90/255.0, green: 187/255.0, blue: 206/255.0, alpha: 1.0)
label.textAlignment = NSTextAlignment.Left
label.font = UIFont (name: "HelveticaNeue-Light", size: 14)
label.text = " \(peop.getName()) - \(sex)"
self.scrollView.addSubview(label)
//Delete button
var button = UIButton.buttonWithType(UIButtonType.System) as UIButton
button.tag = playerId
button.frame = CGRectMake(199, CGFloat(nameHeight), 37, 21)
button.backgroundColor = colorWheel.colorsArray[7]
button.setTitle("Slet", forState: UIControlState.Normal)
button.addTarget(self, action: "delAction:", forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
self.scrollView.addSubview(button)
button.titleLabel!.font = UIFont(name: "HelveticaNeue-Light", size: 14)
scrollHeight = scrollHeight + 29
nameHeight = nameHeight + 29
playerId++
}
scrollView.contentSize = CGSize(width: 20.0, height: CGFloat(nameHeight))
}
func delAction(sender: UIButton!){
personArray.removeAtIndex(sender.tag)
updatePeople()
}
Have you tried this ?
let subViews = self.scrollView.subviews
for subview in subViews{
subview.removeFromSuperview()
}
One line solution, use
scrollView.subviews.forEach({ $0.removeFromSuperview() })
UPDATED
For removing only specific kind of view, say UIButton use
scrollView.subviews.forEach ({ ($0 as? UIButton)?.removeFromSuperview() })
Removing a set of objects from differing classes can be done with tags. Set the tag when creating the set of objects.
label.tag = 99
Now, when removing the objects, use:
func removeLabels() {
let subViews = self.view.subviews
for subview in subViews {
if subview.tag == 99 {
subview.removeFromSuperview()
}
}
}
You can do this with block approach,
let views: NSArray = scroller.subviews
// 3 - remove all subviews
views.enumerateObjectsUsingBlock {
(object: AnyObject!, idx: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
object.removeFromSuperview()
}

Resources