Remove subviews from ScrollView Swift - ios

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

Related

Swift sender.setTitle code didn't visible?

I have question about sender title. I have a button and I want to change title according to some condition. In this point I made sender.setTitle() code but title appear only like 0.5 second. Its not visible let me say more clear. How can I solve it?
Here my code:
#objc func handleExpandCloseForAlim(sender: UIButton) {
if (sender.tag == 1) {
if keys[0] == 0 {
sender.setTitle("titlesample", for: .normal)
keys[0] = 1
}else{
keys[0] = 0
sender.setTitle("titlesampleclose", for: .normal)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Here my header view code:
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
// code for adding centered title
headerView.backgroundColor = .lightGray
let headerLabel = UILabel(frame: CGRect(x: 0, y: 10, width: tableView.bounds.size.width, height: 28))
headerLabel.textColor = UIColor.black
headerLabel.text = " Teslim Alınacağı Adres"
headerLabel.font = UIFont.boldSystemFont(ofSize: 14)
headerLabel.textAlignment = .left
headerView.addSubview(headerLabel)
// code for adding button to right corner of section header
let button: UIButton = UIButton(frame: CGRect(x:headerView.frame.size.width - 100, y:8, width:100, height:28))
button.setTitleColor(.black, for: .normal)
button.titleLabel!.font = UIFont.boldSystemFont(ofSize: 14)
button.layer.cornerRadius = 4
button.tag = 1
button.backgroundColor = UIColor.blue
button.addTarget(self, action: #selector(handleExpandCloseForAlim(sender:)), for: .touchUpInside)
headerView.addSubview(button)
return headerView
The problematic part in the code above is that you are reloading your tableview in the handleExpandCloseForAlim. Since your tableView is reloaded, it will invoke viewForHeaderInSection function in your tableView from where you are returning a headerView with no title. That's why your label is getting disappeared.
You can solve this by having your button label as a field in your viewcontroller may be. Sample code may be like the one follows.
class YourViewController: UITableViewController {
var buttonLabel: String = "titlesampleclose"
.......
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
// code for adding centered title
headerView.backgroundColor = .lightGray
.........
.........
button.setTitle(buttonLabel,for: .normal)
button.addTarget(self, action: #selector(handleExpandCloseForAlim(sender:)), for: .touchUpInside)
headerView.addSubview(button)
return headerView
#objc func handleExpandCloseForAlim(sender: UIButton) {
if (sender.tag == 1) {
if keys[0] == 0 {
self.buttonLabel = "titlesample"
keys[0] = 1
}else{
keys[0] = 0
self.buttonLabel = "titlesampleclose"
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
Hope it helps.

Swift : Programatically Create a UIButton with Some Specific Font And Size

I want to create a basic UIButton programmatically. For example, in my view controller five UIButtons will be created dynamically in the same row and its layout or properties are set for some color, font, and size.
And I also need to add action method for a specific button.
If you wanted to do it programmatically, you might think along the following lines:
Create your buttons in a for... loop in viewDidLoad() (or elsewhere, depending on your requirements):
let buttonWidth : CGFloat = self.view.frame.width / 10
let buttonHeight : CGFloat = 50
for count in 0..<10 {
let newButton = UIButton(frame: CGRect(origin: CGPoint(x: CGFloat(count) * buttonWidth, y: 50), size: CGSize(width: buttonWidth, height: buttonHeight)))
newButton.backgroundColor = UIColor.red
newButton.setTitle("Button #\(count)", for: UIControlState.normal)
newButton.setTitleColor(UIColor.white, for: UIControlState.normal)
newButton.addTarget(self, action: #selector(self.buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
newButton.titleLabel?.font = UIFont(name: "Arial", size: 10)
newButton.tag = count
self.view.addSubview(newButton)
}
Then you can implement the selector buttonTapped(sender: UIButton) as follows, retrieving the button's tag so you can tailor the action (via a switch statement, for example):
func buttonTapped(sender: UIButton) -> Void {
print("\(sender.tag) was tapped!")
// Do something more interesting based on the tag here...
}
This allows you to set up a lot of button actions without a lot of different selectors. Hope that helps.
Create uibuttons and add them inside main view see example below.
class yourClassName: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// here method CGRectMake defines x, y, width, height
var btnOne = UIButton(frame: CGRectMake(0, 0, 50, 50))
var btnOne = UIButton(frame: CGRectMake(0, 0, 50, 50))
self.view.addSubview(btnOne) // add button inside view
self.view.addSubview(btnOne) // add button inside view
// using selector you must specify a method for each button
btnOne.addTarget(self, action: #selector(self.actionOne), forControlEvents: .TouchUpInside)
btnTwo.addTarget(self, action: #selector(self.actionTwo), forControlEvents: .TouchUpInside)
}
Actions methods:
func actionOne(sender : UIButton) {
print("button one tapped")
}
func actionTwo(sender : UIButton) {
print("button second tapped")
}
let bacViewOne=UIButton(frame: CGRectMake(20, 60 , 130, 130))
bacViewOne.backgroundColor=UIColor.whiteColor()
bacViewOne.layer.cornerRadius=5.0
btn1 = UIButton(type: UIButtonType.Custom) as UIButton
btn1.setImage(UIImage(named: "new.png"), forState: UIControlState.Normal)
btn1.frame = CGRectMake((bacViewOne.frame.size.width-90)/2, 5 , 90, 90)
//btn1.backgroundColor = UIColor.whiteColor()
btn1.tag = 1
btn1.addTarget(self, action: #selector(ViewController.dashboard(_:)), forControlEvents: UIControlEvents.TouchUpInside)
bacViewOne.addSubview(btn1)
self.view.addSubview(bacViewOne)
let l1 = UILabel(frame: CGRectMake((bacViewOne.frame.size.width-90)/2, 100, 90, 21))
l1.textAlignment = NSTextAlignment.Center
l1.textColor = UIColor(red: 41/255.0, green: 43/255.0, blue: 64/255.0, alpha: 1)
l1.text = "Dashboard"
//l1.font = UIFont (name: "BakerSignetBT-Roman", size: 15)
bacViewOne.addSubview(l1)
l1.font = UIFont.systemFontOfSize(11)
var bacViewT=UIButton(type: UIButtonType.Custom) as UIButton
bacViewT .frame = CGRectMake(20, 240, 130, 130)
bacViewT.backgroundColor=UIColor.whiteColor()
bacViewT.layer.cornerRadius=5.0
btn3 = UIButton(type: UIButtonType.Custom) as UIButton
btn3.setImage(UIImage(named: "Usernew.png"), forState: UIControlState.Normal)
btn3.frame = CGRectMake((bacViewT.frame.size.width-90)/2, 5, 90, 90)
// btn3.backgroundColor = UIColor(red: 41/255.0, green: 43/255.0, blue: 64/255.0, alpha: 1)
btn3.tag = 2
btn3.addTarget(self, action: #selector(ViewController.userExpenses(_:)), forControlEvents: UIControlEvents.TouchUpInside)
bacViewT.addSubview(btn3)
self.view.addSubview(bacViewT)
let l2 = UILabel(frame: CGRectMake((bacViewT.frame.size.width-100)/2, 100, 100, 21))
l2.textAlignment = NSTextAlignment.Center
l2.textColor = UIColor(red: 41/255.0, green: 43/255.0, blue: 64/255.0, alpha: 1)
l2.text = "User Expense"
//l2.font = UIFont (name: "BakerSignetBT-Roman", size: 15)
bacViewT.addSubview(l2)
l2.font = UIFont.systemFontOfSize(11)
//7
let bacViewTh=UIButton(frame: CGRectMake(170, 60, 130, 130))
bacViewTh.backgroundColor=UIColor.whiteColor()
bacViewTh.layer.cornerRadius=5.0
btn7 = UIButton(type: UIButtonType.Custom) as UIButton
btn7.setImage(UIImage(named: "events.png"), forState: UIControlState.Normal)
btn7.frame = CGRectMake((bacViewTh.frame.size.width-90)/2, 5, 90, 90)
btn7.tag = 3
btn7.addTarget(self, action: #selector(ViewController.upcomingEvents(_:)), forControlEvents: UIControlEvents.TouchUpInside)
bacViewTh.addSubview(btn7)
let l3 = UILabel(frame: CGRectMake((bacViewTh.frame.size.width-100)/2, 100, 100, 21))
l3.textAlignment = NSTextAlignment.Center
l3.textColor = UIColor(red: 41/255.0, green: 43/255.0, blue: 64/255.0, alpha: 1)
l3.text = "Upcoming Events"
//l3.font = UIFont (name: "BakerSignetBT-Roman", size: 15)
bacViewTh.addSubview(l3)
l3.font = UIFont.systemFontOfSize(11)
self.view.addSubview(bacViewTh)
//8
let bacViewF=UIButton(frame: CGRectMake(170, 240, 130, 130))
bacViewF.backgroundColor=UIColor.whiteColor()
bacViewF.layer.cornerRadius=5.0
btn9 = UIButton(type: UIButtonType.Custom) as UIButton
btn9.setImage(UIImage(named: "Location.png"), forState: UIControlState.Normal)
btn9.frame = CGRectMake((bacViewF.frame.size.width-90)/2, 5, 90, 90)
btn9.tag = 4
btn9.addTarget(self, action: #selector(ViewController.userLocations(_:)), forControlEvents: UIControlEvents.TouchUpInside)
bacViewF.addSubview(btn9)
self.view.addSubview(bacViewF)
let l4 = UILabel(frame: CGRectMake((bacViewF.frame.size.width-100)/2, 100, 100, 21))
l4.textAlignment = NSTextAlignment.Center
l4.textColor = UIColor(red: 41/255.0, green: 43/255.0, blue: 64/255.0, alpha: 1)
l4.text = "User Locations"
bacViewF.addSubview(l4)
l4.font = UIFont.systemFontOfSize(11)

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

iOs Swift Table View Problems

I have created an app which table can take multiple button button that can be scrolled in the row.
It is working but i have noticed when i scroll down that it mixes my values.
Lets say in the first row i have 3 button than in the 5-6 and sixth one i also have the last two information from the buttons added to it.I have no idea why is this happening.When in try to print the number of buttons,and positions of them it gives me a correct value but when i run it another sorry is happening.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return roundNumber
}
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 == 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]
}
}else if(indexPath.row == 3){
for countMe in 0..<self.round_4_exercises.count {
if(countMe<1){
roundPosition4.append(5)
}else{
roundPosition4.append(115+roundPosition4[countMe-1])
}
scrollerSize = 115+roundPosition4[countMe]
}
}else if(indexPath.row == 4){
for countMe in 0..<self.round_5_exercises.count {
if(countMe<1){
roundPosition5.append(5)
}else{
roundPosition5.append(115+roundPosition5[countMe-1])
}
scrollerSize = 115+roundPosition5[countMe]
}
}else if(indexPath.row == 5){
for countMe in 0..<self.round_6_exercises.count {
if(countMe<1){
roundPosition6.append(5)
}else{
roundPosition6.append(115+roundPosition6[countMe-1])
}
scrollerSize = 115+roundPosition6[countMe]
}
}else if(indexPath.row == 6){
for countMe in 0..<self.round_7_exercises.count {
if(countMe<1){
roundPosition7.append(5)
}else{
roundPosition7.append(115+roundPosition7[countMe-1])
}
scrollerSize = 115+roundPosition7[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)
}
}else if(indexPath.row == 2){
for index in 0..<self.round_3_exercises.count {
print("Round position 3 \(self.roundPosition3[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition3[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:roundPosition3[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_3_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition3[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_3_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_3_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:roundPosition3[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_3_decoration[index] as? String
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
}else if(indexPath.row == 3){
for index in 0..<self.round_4_exercises.count {
print("Round position 4 \(self.roundPosition4[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition4[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:roundPosition4[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_4_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition4[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_4_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_4_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:roundPosition4[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_4_decoration[index] as? String
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
}else if(indexPath.row == 4){
for index in 0..<self.round_5_exercises.count {
print("Round position 5 \(self.roundPosition5[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition5[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:roundPosition5[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_5_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition5[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_5_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_5_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:roundPosition5[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_5_decoration[index] as? String
cell.RoundExercise_Cell_ScrollView.addSubview(label)
}
}else if(indexPath.row == 5){
for index in 0..<self.round_6_exercises.count {
print("Round position 6 \(self.roundPosition6[index])")
var imageView : UIImageView
imageView = UIImageView(frame:CGRect(x:roundPosition6[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:roundPosition6[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_6_exercises[index] as! String)
cell.RoundExercise_Cell_ScrollView.addSubview(label1)
let frame1 = CGRect(x:roundPosition6[index]+10,y:25, width:90, height: 90 )
let button = UIButton(frame: frame1)
button.backgroundColor = UIColor.redColor()
button.setBackgroundImage(UIImage(named: (self.round_6_exercises[index] as? String)!) as UIImage?, forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.setTitle(self.round_6_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:roundPosition6[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_6_decoration[index] as? String
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)
}

Creating and Setting title of UIButton in FOR loop breaks loop

In my app I'm creating a paged slider (UISlider + UIPageControl). The app reaches out to CoreData to get the array of Entities to create a "page" for.
I build the paginated scroller n the following loop:
for i in 0..<features.count {
var pageWidth = Int(view.frame.width)*i
var pageView = UIView(frame: CGRectMake(CGFloat(pageWidth), 0, scrollView.frame.width, scrollView.frame.height))
pageView.backgroundColor = UIColor.clearColor()
pageView.clipsToBounds = true
//Background image
var imageView = UIImageView(frame: CGRectMake(0, 0, scrollView.frame.width, scrollView.frame.height))
var image:UIImage!
imageView.contentMode = .ScaleAspectFill
pageView.addSubview(imageView)
if fileManager.fileExistsAtPath(features[i].coverImage){
//The background image
image = UIImage(contentsOfFile: self.features[i].coverImage)
imageView.image = image
}
else if !fileManager.fileExistsAtPath(features[i].coverImage) && !features[i].coverImage.isEmpty {
FileStoreClient.downloadFileIfNotExists(features[i].cover, completion: { (success, error) -> Void in
if error == nil {
image = UIImage(contentsOfFile: self.features[i].coverImage)
imageView.image = image
}
else {
println("There was an error during the download")
}
})
}
//The background cover
var coverView = UIView(frame: CGRectMake(0, 0, view.frame.width, 250))
coverView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
pageView.addSubview(coverView)
//The title
var titleLabel = UILabel(frame: CGRectMake(10, 40, view.frame.width-20, 25))
titleLabel.font = UIFont(name: "Haymaker", size: 24)
titleLabel.textColor = UIColor.whiteColor()
titleLabel.layer.shadowColor = UIColor.blackColor().CGColor
titleLabel.layer.shadowOffset = CGSizeMake(1, 1)
titleLabel.layer.shadowRadius = 1
titleLabel.layer.shadowOpacity = 1
titleLabel.textAlignment = .Center
titleLabel.text = features[i].title
pageView.addSubview(titleLabel)
//The text
var textLabel = UILabel(frame: CGRectMake(10, titleLabel.frame.origin.y+titleLabel.frame.height+5, view.frame.width-20, 60))
textLabel.numberOfLines = 0
textLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
textLabel.font = UIFont(name: "OpenSans", size: 13)
textLabel.textColor = UIColor.whiteColor()
textLabel.textAlignment = .Center
textLabel.text = features[i].summary
pageView.addSubview(textLabel)
//The button
var readMoreButton = UIButton(frame: CGRectMake(0, pageView.frame.height - 90, 200, 80))
readMoreButton.setAttributedTitle(NSAttributedString(string: Strings.readMoreButtonTitle, attributes: Fonts.featureButtonText), forState: UIControlState.Normal)
//readMoreButton.addTarget(self, action: "readArticle", forControlEvents: .TouchUpInside)
readMoreButton.layer.cornerRadius = 6
readMoreButton.layer.borderColor = UIColor.whiteColor().CGColor
readMoreButton.layer.borderWidth = 1
readMoreButton.center.x = pageView.center.x
pageView.addSubview(readMoreButton)
println(i)
scrollView.addSubview(pageView)
}
Everything works exactly as it should, except that the moment I try to assign a title to the new button, the loop turns into an infinite loop. If I print out the current index of the loop, it keeps cycling through endlessly. Example:
0
1
2
0
1
2
0
1
2
If I comment out the myButton.setTitle() method, the problem goes away and the indexes print out like the following:
0
1
2
I have tried setTitle and setAttributedTitle, both of which have the same effect. I have tried dispatching different queues and nothing seems to be working.
Again, everything works for the background image, the two labels, views, etc. Problem only exists when a button is brought into the mix. The issue exists even if I remove the FileStoreManager code.
Something about a button in a for loop isn't happy.
EDIT #1
I decided to try and create a new project just to test button creation in a for loop. This works perfectly fine.
var x = 20
var y = 20
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...10 {
var myview = UIView(frame: CGRectMake(CGFloat(x), CGFloat(y), 100, 50))
var button = UIButton(frame: CGRectMake(0, 0, 100, 50))
button.setTitle("Test", forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.layer.borderColor = UIColor.blackColor().CGColor
button.layer.borderWidth = 2
myview.addSubview(button)
view.addSubview(myview)
x = x+20
y = y+20
println(i)
}
}
You can also try fast enumeration in case something is somehow getting messed up in your range.
for feature in features { ... }
or if you need the index:
for (index, features) in features.enumerate() { ... }
Not sure it will resolve the issue, but it might increase readability.
It turns out it was because I had the above code in the viewDidLayoutSubviews() function. Something about setting a buttons title triggers the method, it seems.
As I needed to use this method due to dynamic sizes, I simply added a "hasLoaded:Bool" to check if the function has already fired.
This resolved the issue.

Resources