Swift: How to use buttons in Scroll View - ios

I have created a scroll view with "buttons". But the "buttons" actually don't do anything at the moment. So, I would like to know, how I can make the "buttons" usable. So when I press them they lead me to a different view controller. All the buttons will lead me to the same view controller just with different data (depending on what I want that button to represent) inside the view controller. Here's my code so far:
#IBOutlet weak var categoryScrollView: UIScrollView!
var categoryArr = ["Button1","Button2","Button3","Button4","Button5", "Button 6", "Button 7", "Button 8", "Button 9", "Button 10", "Button 11", "Button 12"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor(), UIColor.blackColor(), UIColor.brownColor()]
let kPadding:CGFloat = 20
override func viewDidLoad() {
super.viewDidLoad()
let buttonSize = CGSizeMake(categoryScrollView.bounds.size.width/2, categoryScrollView.bounds.size.height/2)//hal
let scrollingView = colorButtonsView(buttonSize, buttonCount: 12)
categoryScrollView.contentSize = scrollingView.frame.size
categoryScrollView.addSubview(scrollingView)
categoryScrollView.showsVerticalScrollIndicator = false
categoryScrollView.delegate = self
categoryScrollView.pagingEnabled = true
categoryScrollView.indicatorStyle = .Default
categoryScrollView.contentOffset = CGPointMake(0, 0)
}
func colorButtonsView(buttonSize:CGSize, buttonCount:Int) -> UIView {
let buttonView = UIView()
buttonView.frame.origin = CGPointMake(50,300)
let padding = CGSizeMake(kPadding, kPadding)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(buttonCount)
var buttonPosition = CGPointMake(0, padding.height)
let buttonIncrement = buttonSize.width + padding.width
for i in 0...(buttonCount - 1) {
let button = UIButton(type: .Custom)
button.frame.size = buttonSize
button.frame.origin = buttonPosition
buttonPosition.x = buttonPosition.x + buttonIncrement
button.setTitle(categoryArr[i], forState: UIControlState.Normal)
button.backgroundColor = buttonColors[i]
buttonView.addSubview(button)
}
buttonView.backgroundColor = UIColor.redColor()
return buttonView
}
}
extension ViewController:UIScrollViewDelegate{
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let index = round(scrollView.contentOffset.x / scrollView.frame.size.width)
print(index)
}
}

When you create your button you have to specify a target in order to have an action with it (add this in your for loop) :
button.addTarget(self, action: "myaction:", forControlEvents: .TouchUpInside)
then create the corresponding method
func myaction(sender: UIButton!) {
// navigation code here.
}
Please note that you don't have to create several method in order to have different actions for each button, all you have to do is something like this :
button.tag = i
and then in your action method :
switch sender.tag {
case 0 :
//do some stuff
case 1 :
//do some stuff
}

You have to add targets to button to fire some action methods. Like in your loop when you create UIButton, add
button.addTarget(self, action: "pressed:", forControlEvents: .TouchUpInside)
and implement one method like:
func pressed(sender: UIButton!) {
// navigation code here.
}

Related

Dynamically add buttons in swift

I am writing an iOS app. Server gives me buttons array to draw on view. So, the number of buttons can vary according to server response,
example:
let buttonArray=["Button 1","Button 2","Button 3"]
or
let buttonArray=["Button 1","Button 2","Button 3"," Button 4", "Button 5"]
I have to stack these buttons vertically.
I created a stackview, add constraints to it, and then add buttons to this stackview as arrangedsubviews.
Buttons should have gap of 5 points between them:
Using stackview:
func addButtonsUsingStackView()
{
//create stackview:
let stackView=UIStackView()
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 5
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
//stackview constraints:
let viewsDictionary = ["stackView":stackView]
let stackView_H = NSLayoutConstraint.constraints(
withVisualFormat: "H:|-20-[stackView]-20-|",
options: NSLayoutFormatOptions(rawValue: 0),
metrics: nil,
views: viewsDictionary)
let stackView_V = NSLayoutConstraint.constraints(
withVisualFormat: "V:|-30-[stackView]-30-|",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil,
views: viewsDictionary)
view.addConstraints(stackView_H)
view.addConstraints(stackView_V)
//adding buttons to stackview:
//let buttonArray=["Button 1","Button 2","Button 3"]
let buttonArray=["Button 1","Button 2","Button 3"," Button 4"]
for buttonName in buttonArray{
let button=UIButton()
button.setTitle(buttonName, for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.backgroundColor=UIColor.blue
button.translatesAutoresizingMaskIntoConstraints=false
stackView.addArrangedSubview(button)
}
}
Without stackview:
var buttonArray=["Button 1","Button 2","Button 3"," Button 4"," Button 5"," Button 6"," Button 7"]
func addButtonsLoop()
{
for _view in view.subviews{
_view.removeFromSuperview()
}
var i=0
var buttonY = 20
let buttonGap=5
for btn in buttonArray {
let buttonHeight=Int(Int(view.frame.height) - 40 - (buttonArray.count * buttonGap))/buttonArray.count
print(buttonHeight)
let buttonWidth=Int(view.frame.width - 40)
let button = UIButton()
button.backgroundColor = UIColor.orange
button.setTitle(btn, for: .normal)
button.titleLabel?.textColor = UIColor.white
button.frame = CGRect(x: 20, y: buttonY, width:buttonWidth , height:buttonHeight)
button.contentMode = UIViewContentMode.scaleToFill
buttonY += buttonHeight + buttonGap
button.tag = i
button.addTarget(self, action: #selector(self.buttonTapped(_:)), for: UIControlEvents.touchUpInside)
view.addSubview(button)
i+=1
}
}
func buttonTapped( _ button : UIButton)
{
buttonArray.remove(at: button.tag)
addButtonsLoop()
}
My question is that instead of above code, how to apply NSLayoutConstraints or LayoutAnchors to solve this?
Instead of stack view you can use a tableview with the tableview cell containing a button and the number of rows can be the buttonarray count. In cellForRowAtIndexPath delegate method set the button title from button array.
you can use scroll view to add buttons.
var btnY = 5
let btnHeight = 40
func addButtonsUsingStackView()
{
for view in self.view.subviews{
view.removeFromSuperview()
}
for i in 0..< buttonArray.count {
let btnFloor = UIButton()
btnFloor.backgroundColor = Orange
btnFloor.titleLabel?.textColor = UIColor.white
btnFloor.frame = CGRect(x: 10, y: btnY, width: Int(scrView.frame.width - 20), height: btnHeight)
btnFloor.contentMode = UIViewContentMode.scaleToFill
btnY += btnHeight + 5
btnFloor.tag = buttonArray.index(of: i)
btnFloor.addTarget(self, action: #selector(self.btnTappedFloor(_:)), for: UIControlEvents.touchUpInside)
self.view.addSubview(btnFloor)
}
return cell
}
func btnTappedFloor( _ button : UIButton)
{
buttonArray.remove(at: button.tag)
addButtonsUsingStackView()
}

Last Button in UIScrollView add target doesn't effect

I have a list of category add I created buttons for each category in a scroll view
and a last button is ALL button for all products. But some how it didn't have any action I added.
this is my code
First I make a function to create buttons to add to view
func catButtonView(buttonSize:CGSize) -> UIView {
let buttonView = UIView()
buttonView.backgroundColor = UIColor(colorLiteralRed: 1, green: 1, blue: 1, alpha: 0)
buttonView.frame.origin = CGPoint(x: 0,y: 0)
let padding = CGSize(width:0, height:0)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(categories.count)
buttonView.frame.size.height = (buttonSize.height + 2.0 * padding.height )
//add buttons to the view
var buttonPosition = CGPoint(x:padding.width * 0.5, y:padding.height)
let buttonIncrement = buttonSize.width + padding.width
let hueIncrement = 1.0 / CGFloat(categories.count)
var newHue = hueIncrement
for i in 0...(categories.count) {
let button = UIButton.init(type: .custom) as UIButton
button.frame.size = buttonSize
button.frame.origin = buttonPosition
button.setBackgroundImage(R.image.button(), for: .normal)
button.setBackgroundImage(R.image.button_selected(), for: .selected)
if(i==categories.count) {
button.setTitle("ALL", for: .normal)
} else {
button.setTitle(categories[i].name, for: .normal)
}
button.setTitleColor(UIColor.white, for: .normal)
buttonPosition.x = buttonPosition.x + buttonIncrement
newHue = newHue + hueIncrement
button.tag = i+1
button.addTarget(self, action: #selector(catButtonPressed(sender:)), for: .touchUpInside)
buttonView.addSubview(button)
}
return buttonView
}
this is action func
func catButtonPressed(sender:UIButton){
print(sender.tag)
if(self.selectedCat != sender.tag-1) {
let lastBtn = catScrollView.viewWithTag(selectedCat+1) as? UIButton
lastBtn?.setBackgroundImage(R.image.button(), for: .normal)
self.selectedCat = sender.tag-1
self.itemsCollection.reloadData()
sender.setBackgroundImage(R.image.button_selected(), for: .normal)
}
}
then add to scroll view
let catScrollingView = catButtonView(buttonSize: CGSize(width: 200.0, height:50.0))
catScrollView.contentSize = catScrollingView.frame.size
catScrollView.subviews.forEach({ $0.removeFromSuperview() })
catScrollView.addSubview(catScrollingView)
catScrollView.showsHorizontalScrollIndicator = true
catScrollView.indicatorStyle = .default
self.itemsCollection.reloadData()
Anyone know what I missed?
It is because the if statement in your catButtonPressed function is false with the last button's tag, which makes the code inside never be executed.
Let's say you have 5 categories so your categories.count = 5. So your self.selectedCat ranges from 0 to 4. In your for i in 0...(categories.count) the last button's tag is button.tag = 5
Now in your catButtonPressed function. If the last button is the last category, then your self.selectedCat will be 4 and sender.tag will be 5
func catButtonPressed(sender:UIButton){
print(sender.tag)
if(4 != 5-1) {
// Any code in here will never be executed because 4 != 4 is false
}
}

how to create radio buttons dynamically in swift?

I have the following buttons which are adding dynamically based on some condition. Now i need to change all added buttons behaviour as radio buttons. so that I can do some actions based on the selection..
var posX = 0
var posY = 0
if trim.contains("0"){
print("contaim 0")
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
posX = 60
}
if trim.contains("1") {
print("contaim 1")
let button2 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button2.setTitleColor(UIColor.blackColor(), forState: .Normal)
button2.setTitle("Less", forState: .Normal)
button2.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button2.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button2)
posX = posX + 60
}
if trim.contains("2"){
print("contaim 2")
let button3 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button3.setTitleColor(UIColor.blackColor(), forState: .Normal)
button3.setTitle("Half", forState: .Normal)
button3.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
button3.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button3)
posX = posX + 60
}
I have set the buttonAction methods as below buts its not working
func buttonAction(sender: UIButton!) {
print("Button tapped")
sender.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Normal)
}
let buttons = [UIButton]()
// create button1
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button1.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Selected)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
buttons.append(button1)
// create other buttons and add into buttons ...
func buttonAction(sender: UIButton!){
for button in buttons {
button.selected = false
}
sender.selected = true
// you may need to know which button to trigger some action
// let buttonIndex = buttons.indexOf(sender)
}
In case anyone finds this useful. Here is an example of how I use DLRadioButton library (https://github.com/DavydLiu/DLRadioButton) to create RadioButtons dynamically.
You can check a complete small project to show a working code in here https://github.com/omhack/DynamicRadioButtons
import UIKit
import DLRadioButton
//Delegate to manage the Polls
protocol QuestionsDialogDelegate : class{
func questionsAnswered(polls: [Poll])
}
class QuestionsDialog: UIViewController {
#IBOutlet weak var stackView: UIStackView!
#IBOutlet var rootView: UIView!
#IBOutlet weak var nestedView: UIView!
weak var delegate: QuestionsDialogDelegate?
var questions : [Question]!
var polls = [Poll]()
var serviceType : Int = 0
var indexView : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
//setting the stack view properties
stackView.alignment = UIStackViewAlignment.leading
stackView.axis = .vertical
}
//this is where the heavy logic, to create the dynamic radio buttons takes place
func showQuestions(){
if(questions.count <= 1){
rootView.frame.size.height = 200
nestedView.frame.size.height = 200
}else{
rootView.frame.size.height = 400
nestedView.frame.size.height = 400
}
for question in questions{
var otherButtons : [DLRadioButton] = []
let frame1 = CGRect(x: self.view.frame.size.width / 2 - 131, y: 350, width: 262, height: 17);
//we create a base radio button to use it as an anchor view
let firstRadioButton = createRadioButton(frame: frame1, title: "", color: UIColor.purple);
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 17.0)
label.textColor = UIColor.darkGray.withAlphaComponent(0.85)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
label.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
label.text = question.question
self.stackView.insertArrangedSubview(label, at: self.indexView)
self.indexView += 1
let poll = Poll()
poll.idQuestion = question.idQuestion
var i = 0;
for answer in question.answers{
let frame = CGRect(x: self.view.frame.size.width / 2 - 131, y: 380 + 30 * CGFloat(i), width: 300, height: 17);
let radioButton = createRadioButton(frame: frame, title: answer.answer! + " ", color: UIColor.purple)
radioButton.tag = answer.idAnswer
radioButton.params["poll"] = poll
otherButtons.append(radioButton)
self.stackView.insertArrangedSubview(radioButton, at: self.indexView)
i += 1;
self.indexView += 1
}
firstRadioButton.otherButtons = otherButtons
firstRadioButton.isHidden = true
firstRadioButton.otherButtons[1].isSelected = true
}
}
//Method to create a custom button
private func createRadioButton(frame : CGRect, title : String, color : UIColor) -> MyDLUIButton {
let radioButton = MyDLUIButton(frame: frame);
radioButton.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
radioButton.titleLabel!.font = UIFont.systemFont(ofSize: 14);
radioButton.setTitle(title, for: []);
radioButton.setTitleColor(UIColor.darkGray, for: []);
radioButton.iconColor = color;
radioButton.indicatorColor = color;
radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
radioButton.addTarget(self, action: #selector(QuestionsDialog.selectedAnswer(_:)), for: UIControlEvents.touchUpInside)
self.view.addSubview(radioButton);
return radioButton;
}
#objc func selectedAnswer(_ sender: MyDLUIButton){
let poll = sender.params["poll"] as? Poll
poll?.idAnswer = sender.tag
if let row = self.polls.index(where: {$0.idQuestion == poll?.idQuestion}) {
self.polls[row] = poll!
}else{
self.polls.append(poll!)
}
print("polls size: \(self.polls.count)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidDisappear(_ animated: Bool) {
if(self.polls.count < self.questions.count){
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "questionsDialogDismissed"), object: nil)
}
}
#IBAction func requestService(_ sender: UIButton) {
delegate?.questionsAnswered(polls: self.polls)
}
}
class MyDLUIButton: DLRadioButton{
var params: Dictionary<String, Any>
override init(frame: CGRect) {
self.params = [:]
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
self.params = [:]
super.init(coder: aDecoder)
}
}
I would create a tag for every UIButton, then add your UIButton to be send to your ButtonAction:
button.tag = 0
button.addTarget(object, action: #selector(YourViewController.buttonAction(_:)),
forControlEvents: .TouchUpInside)
func buttonAction(sender: UIButton!) {
let selectedButton = sender as! UIButton
print(selectedButton.tag) // here stands the correct button which is pressed
}
You could also create an Array containing all Buttons, for example:
let myButtons = [UIButton]()
let button1 = UIButton()...
button1.tag = 0
myButtons.add(button1)
And now change it like this way:
myButtons[0].setImage(.....)
Where 0 is your first button (so with tag 0) // you should set your tags in the same order in which you append it to your myButtons Array.

Button Not Firing Event Inside ScrollView

UIButtons inside scrollview are not firing event. I tried setting exclusiveTouch delaysTouchesEvent, but nothing helped.
class TestViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
var categoryArr = ["Jack","Mark","Down","Bill","Steve"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor()]
override func viewDidLoad() {
super.viewDidLoad()
let scrollingView = colorButtonsView(CGSizeMake(150,scrollView.frame.size.height), buttonCount: 5)
scrollView.contentSize = scrollingView.frame.size
scrollView.addSubview(scrollingView)
scrollView.showsVerticalScrollIndicator = false
scrollView.delegate = self
scrollView.pagingEnabled = true
scrollView.indicatorStyle = .Default
scrollView.canCancelContentTouches = false
scrollView.delaysContentTouches = false
scrollView.exclusiveTouch = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func colorButtonsView(buttonSize:CGSize, buttonCount:Int) -> UIView {
let buttonView = UIView()
buttonView.frame.origin = CGPointMake(0,0)
let padding = CGSizeMake(10, 10)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(buttonCount)
var buttonPosition = CGPointMake(padding.width * 0.5, padding.height)
let buttonIncrement = buttonSize.width + padding.width
for i in 0...(buttonCount - 1) {
var button = UIButton.buttonWithType(.Custom) as! UIButton
button.frame.size = buttonSize
button.frame.origin = buttonPosition
buttonPosition.x = buttonPosition.x + buttonIncrement
button.setTitle(categoryArr[i], forState: UIControlState.Normal)
button.addTarget(self, action: "showTheNextButton:", forControlEvents: UIControlEvents.TouchUpInside)
button.backgroundColor = buttonColors[i]
buttonView.addSubview(button)
}
return buttonView
}
func showTheNextButton(sender:UIButton){
print("ok show the next button")
}
}
extension TestViewController:UIScrollViewDelegate{
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let index = round(scrollView.contentOffset.x / scrollView.frame.size.width)
print(index)
}
}
A UIButton will not accept touches if it lies outside the bounds of one of its superviews. Make sure all your views are the size and position you expect them to be
Please make the following changes:
self.scrollView.canCancelContentTouches = true
self.scrollView.delaysContentTouches = true
In your for-loop, move your let buttonView = UIView() to:
#IBOutlet weak var scrollView: UIScrollView!
var categoryArr = ["Jack","Mark","Down","Bill","Steve"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor()]
let buttonView = UIView()
Then subsequently, change the following, again, in your for-loop:
Change this line: buttonView.frame.origin = CGPointMake(0,0) to
self.buttonView.frame = self.scrollView.bounds
self.buttonView.userInteractionEnabled = true
Addendum:
Comment this out: //self.scrollView.exclusiveTouch = true
I took the liberty of testing it; touches should get registered on the buttons and scrolling should also work horizontally. Enjoy.

Swift: Buttons not working inside UIScrollView

I have a ScrollView. You can scroll but the buttons don't allow you to press them(when you press them they don't do anything). Can you help fix this? Here is my current code:
PS: I'm checking this regularly so if you have a question I'll answer.
class ViewController: UIViewController {
#IBOutlet weak var categoryScrollView: UIScrollView!
var categoryArr = ["Button1","Button2","Button3","Button4","Button5", "Button 6", "Button 7", "Button 8", "Button 9", "Button 10", "Button 11", "Button 12"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor(), UIColor.blackColor(), UIColor.brownColor()]
var buttonImages = [UIImage(named: "One"), UIImage(named: "Two"), UIImage(named: "Three"), UIImage(named: "PlayButtonImage"), UIImage(named: "Triangle"), UIImage(named: "PlayButtonImage"), UIImage(named: "Triangle"), UIImage(named: "PlayButtonImage"), UIImage(named: "Triangle"), UIImage(named: "PlayButtonImage"), UIImage(named: "Triangle"), UIImage(named: "PlayButtonImage")]
let kPadding:CGFloat = 20
override func viewDidLoad() {
super.viewDidLoad()
let buttonSize = CGSizeMake(categoryScrollView.bounds.size.width/2, categoryScrollView.bounds.size.height/2)//hal
let scrollingView = ImageButtonsView(buttonSize, buttonCount: 12)
categoryScrollView.contentSize = scrollingView.frame.size
categoryScrollView.addSubview(scrollingView)
categoryScrollView.showsVerticalScrollIndicator = false
categoryScrollView.delegate = self
categoryScrollView.pagingEnabled = true
categoryScrollView.indicatorStyle = .Default
categoryScrollView.contentOffset = CGPointMake(0, 0)
categoryScrollView.delaysContentTouches = false
categoryScrollView.userInteractionEnabled = true;
categoryScrollView.exclusiveTouch = true;
categoryScrollView.canCancelContentTouches = true;
//categoryScrollView.clipsToBounds = true
}
func ImageButtonsView(buttonSize:CGSize, buttonCount:Int) -> UIView {
let buttonView = UIView()
buttonView.frame.origin = CGPointMake(50,142)
let padding = CGSizeMake(kPadding, kPadding)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(buttonCount)
var buttonPosition = CGPointMake(0, padding.height)
let buttonIncrement = buttonSize.width + padding.width
for i in 0...(buttonCount - 1) {
let button = UIButton(type: .Custom)
buttonView.userInteractionEnabled = true
button.frame.size = buttonSize
button.frame.origin = buttonPosition
buttonPosition.x = buttonPosition.x + buttonIncrement
button.setTitle(categoryArr[i], forState: UIControlState.Normal)
let buttonImagesOne = buttonImages[i]
button.setImage(buttonImagesOne, forState: .Normal)
button.layer.cornerRadius = 30
button.addTarget(self, action: "pressed:", forControlEvents: UIControlEvents.TouchUpInside)
buttonView.addSubview(button)
}
//buttonView.backgroundColor = UIColor.redColor()
categoryScrollView.bringSubviewToFront(buttonView)
return buttonView
}
}
extension ViewController:UIScrollViewDelegate{
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let index = round(scrollView.contentOffset.x / scrollView.frame.size.width)
print(index)
}
func pressed(/*sender: UIButton!*/) {
let vc = UIViewController(nibName: "GridViewController", bundle: nil)
self.presentViewController(vc, animated: true, completion:nil)
//viewController.hidden = true
}
}
Originally here, I thought the line
button.addTarget(self, action: "pressed:", forControlEvents: UIControlEvents.TouchUpInside)
should have said "pressed" without a ":". But that turned out to be a misunderstanding on my part, sorry. It should be "pressed:".
Instead, this may be related to Protocol extension and addTarget is crashing with NSInvalidArgumentException which is also very confusing.
It turned out my scrollview's layout was set to "Autoresizing Mask" instead of "Inferred (Constraints)". Although my layout looked good, my buttons were actually outside the bounds of the scrollview and therefore couldn't be clicked!
Have you tried adding a UITapGestureRecognizer to your button? You could try something like this:
let myTap = UITapGestureRecognizer(target: self, action: Selector("handleButtonTap:"))
myTap.delegate = self
//**Make your class inherit from UIGestureRecognizerDelegate otherwise an error will be thrown**
myButton.addGestureRecognizer(myTap)
Then write a function (the name of the function should be what you put in the action field above. So in this case the function would be called handleButtonTap. Here is the code:
func handleButtonTap() {
// Handle what happens when the button is tapped.
}
I hope I was able to help :).
This is my approach (Swift 2 / xCode 7.2.1):
I have 2 View Controllers:
“VC1” with the scrollview
Here I create the different views (instances of “VC2”) and add them to the scrollview:
scrollView.addSubview(pageStep.view)
addChildViewController(pageStep)
which I call page1, page2, page3 …
Then you can access the "page1.btn1" and do something like this
page1.nextBtn.addTarget(self, action: "nextPage:", forControlEvents: .TouchUpInside)
func nextPage(sender: UIButton!) {
let xPosition = (pageFraction + 1) * scrollSize
scrollView.setContentOffset(CGPoint(x: xPosition, y: 0), animated: true)
}
“VC2” With the outlets (each page) (UIImage, Buttons etc.)
I hope it helps !

Resources