Generating UIButtons from a loop

This is a very useful technique and it’s pretty straight forward.
Let’s say we have an array of items or heroes and we want to dynamically create buttons that
will do something linked to the hero/item selected.
One example is if you have an array of saved games and you want to generate buttons to load each saved game.
In reality you’ll most likely be generating your array from dynamic content – plist or CoreData.

In our case, just for the sake of this example we’ll start off by creating a static array with some Strings:

Now we have our array to work with. Let’s generate some UIButtons:

First problem you are going to encounter here is that your buttons will overlap over each other, so you can only see one button on the screen ( the last one to add ):

Screen Shot 2015-01-28 at 1.15.44 PM
so we need to add an offset. So we’ll end up with this:

So at this point we should have all of our buttons generated.
You should see something like this:
Screen Shot 2015-01-28 at 1.17.10 PM
All good except nothing happens when you press them..wait !
Did I say nothing ? I meant this:
Screen Shot 2015-01-28 at 1.17.23 PM

Screen Shot 2015-01-28 at 1.17.28 PM

Here is the fix for that..we are going to create a function for the button taps:

You can also pass let’s say the UIButton’s tag instead.
If you only need Int’s you can use sender.tag, instead of the titleLabel.text .

Keep in mind that for this example you would put the generator for the Buttons in the viewDidLoad()

method ( or enclose it in a function and then call that function in viewDidLoad()  ), but the “villainButtonPressed function you will place outside of viewDidLoad.

And Voila, you should now have your dynamically generated UIButtons!

I’ve added a few more things, just so we can get some system messages, to make sure we have not gone completely crazy:

Screen Shot 2015-01-28 at 1.24.15 PM
Here is what your full code should look like:

Here is an addition on request. This will generate one button at the start and a new button on button click:

Here is a link to the second part: UIButtons From A loop – part 2

20 thoughts on “Generating UIButtons from a loop

  1. Razvigor Andreev says:

    Any questions or comments – let me know. Thanks!

    • Hey, awesome help there! Would just like to know on how do we generate the next button in the array every time the buttonPressed func is clicked, instead of generating all four buttons in the array at one go? Thanks!!!

      • Razvigor Andreev says:

        Hey, @bleeary_d:disqus, thanks! I made some changes and posted it at the bottom of the article. Let me know if that works. Cheers!

        • Heyy, wow that was amazing hahah that was what i wanted! Thanks so much for your help and cheers mate! (Y)

      • Razvigor Andreev says:

        Btw, if you don’t want the pressing of new buttons to generate more buttons too, just take the ‘.addTarget’ line out of the addNewFunction.

  2. Hi! I have noticed that you use subview to add the buttons to the view controller. I have tried the above codes for my project and it seems that every time i go into another view , the buttons i have created disappears. Is there any way to keep the buttons in the subview alive in that view even when i go into another view? Thanks!

    • Razvigor Andreev says:

      What do you mean go into another view ? Can you post your code somewhere ?

      • Hi thanks for replying! I am sorry that currently my project is under NDA. So apparently the view controller which i had use to generate buttons programatically (2nd VC) , was link to a navigation controller to another view controller(1st VC). After adding a plenty amount of buttons in the 2nd view controller, if i were to pressed press the back button (bar button item) to transit back to the 1st VC and then by clicking a button to show the 2nd VC, all the button previously created in the 2nd VC was gone. Cheers!

        • Razvigor Andreev says:

          That’s because you are adding the buttons to a UIView that is getting recreated every time you load the VC. You need to keep a reference of it and only create it once, not every time you load the VC.

          • Thanks! I know this is a silly question but how do you keep a reference of it so that it only create once? Sorry i am really new to swift and programming.

    • Razvigor Andreev says:

      Did you figure it out? I see your question is gone 🙂

    • Razvigor Andreev says:

      If you still need this I think the easiest solution for you, since you are using the nav. controller is this:

      add this line at the bottom of the addNewButton() func:

      arrayOfVillains.append(“New Button : (number)”)

      And then move the declaration of the array before the class, so it’s global, like this:

      import UIKit

      var arrayOfVillains = [“Main Button”]

      class ViewController: UIViewController {

      var number: Int = 1

      var buttonY: CGFloat = 80 // our Starting Offset, could be 0

      override func viewDidLoad() {

      super.viewDidLoad()

  3. Hey mate, i am a currently facing a small problem which is frustrating. What i did was i preset 6 buttons in an array and have an add button where every time the add button is pressed, the first button in the array will be set with an image and label and if i click add again, the second button’s image and label will appear and so on.. And so, i have a navigation controller and when i clicked back on the nav controller which leads me to another VC and when i come back to the initial VC, the buttons are gone! It will be great if you could help me and thanks and sorry for the trouble 🙂

    • Razvigor Andreev says:

      Hi, look at my answer below. SwiftNoob had a similar problem. I think the easiest solution would be to append them to the array, whenever you add a new button. So when you add 2 more , your array will then contain 8 buttons.

      • Hey, thanks for replying! I have tried the solution you gave SwiftNoob below but instead of getting the image button set, i got the addition of starting button instead (After going back to the previous VC and to this VC again)

        Here are the codes for my view controller

        func addStartingButtons()

        {

        for lockers in arrayOfLockers

        {

        let addLockerbtn = UIButton(frame: CGRect(x: 250, y: buttonY + 70, width: 120, height: 30))

        buttonY = buttonY + 80 // we are going to space these UIButtons 50px apart

        addLockerbtn.layer.cornerRadius = 10 // get some fancy pantsy rounding

        addLockerbtn.backgroundColor = UIColor.grayColor()

        addLockerbtn.setTitle(“Add New+”, forState: UIControlState.Normal) // We are going to use the item name as the Button Title here.

        addLockerbtn.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)

        addLockerbtn.addTarget(self, action: “ButtonPressed:”, forControlEvents: UIControlEvents.TouchUpInside)

        self.view.addSubview(addLockerbtn) // myView in this case is the view you want these buttons added

        }//end of startingButton

        }//end of addStartingButtons Func

        func addNewButton(sender: UIButton)

        {

        let image = UIImage(named: “lock.png”) as UIImage!

        sender.backgroundColor = UIColor.grayColor()

        sender.setImage(image, forState: UIControlState.Normal)

        sender.layer.cornerRadius = 10

        arrayOfLockers.append(“Add New+”)

        }

        func ButtonPressed(sender:UIButton!)

        {

        if number<7

        {

        if number == 1

        {

        addNewButton(btn1)

        }

        else if number == 2

        {

        addNewButton(btn2)

        }

        else if number == 3

        {

        addNewButton(btn3)

        }

        else if number == 4

        {

        addNewButton(btn4)

        }

        else if number == 5

        {

        addNewButton(btn5)

        }

        else if number == 6

        {

        addNewButton(btn6)

        }

        number++

        } //end of number less than 6

        else

        {

        let maxbtnAlert = UIAlertView()

        maxbtnAlert.title = "Exceed max buttons added"

        maxbtnAlert.message = "ERROR! Cannot add anymore buttons!"

        maxbtnAlert.addButtonWithTitle("Ok")

        maxbtnAlert.show()

        } //end of else

        }//end of buttonPressed func

        • Razvigor Andreev says:

          I see, so it really depends what exactly you are aiming at. I see a quick fix for your case.
          Just create a second array for the newly created buttons. Then append to it every time you create one.
          In the ViewDidLoad method add the Start buttons and then add the Newbuttons ( create a second func for the addNewButtons )

Leave a Reply

Your email address will not be published. Required fields are marked *