3

enter image description hereI have dynamically created buttons on a dynamic view and later I add that dynamic view to main view.
Everything is working well except that the selector method of UIButton is not called.

var baseView:UIView?
    override func viewDidLoad() {
        super.viewDidLoad()
        randomizeButtons()}
    func randomizeButtons(){


        baseView = UIView(frame:CGRectMake(view.bounds.origin.x + 10, view.bounds.origin.y + 50, view.bounds.size.width, view.bounds.size.height-20))
        let viewWidth = baseView.bounds.size.width;
        let viewHeight = baseView.bounds.size.height;

        baseView.userInteractionEnabled = true
        let  i = GlobalArrayofUsers.count
        var loopCount = 0
        while loopCount < i{

            let  userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
            print(userBaseView.frame)
            userBaseView.backgroundColor = UIColor.redColor()
            userBaseView.userInteractionEnabled = true

            userBaseView.layer.cornerRadius = 45
            userBaseView.clipsToBounds = true


            let button = UIButton(frame: userBaseView.bounds)
            button.backgroundColor = UIColor.greenColor()
            button.showsTouchWhenHighlighted = true
            button.addTarget(self, action: #selector(ViewController.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
            button.setTitle("hello", forState: .Normal)
            button.userInteractionEnabled = true
            userBaseView.addSubview(button)
            baseView.addSubview(userBaseView)
            print("button  frame is\(button.frame)")
            baseView.bringSubviewToFront(userBaseView)

            loopCount += 1

        }
    }
    baseView.subviews.forEach { (users) in
    UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat], animations: {
    users.center.y += 10
    }, completion: nil)
    }
    view.insertSubview(baseView, atIndex: view.subviews.count)

}

func handleTapEventofBtn(sender: UIButton!) {
    // handling code
}

Any idea why my selector method is not called? It is due to animation. How can i handle it.

SOLUTION: Allow userinteraction in UIAnimationOptions

ankit
  • 3,537
  • 1
  • 16
  • 32

4 Answers4

4

The problem is that you are trying to click an object that is being animated. From the docs:

During an animation, user interactions are temporarily disabled for the views being animated. (Prior to iOS 5, user interactions are disabled for the entire application.)

But worry not, the solution is very easy, just call your animation with the option .AllowUserInteraction. For example (with your code):

UIView.animateWithDuration(1, delay: 0, options: [.Autoreverse,.Repeat,.AllowUserInteraction], animations: {
    users.center.y += 10
}, completion: nil)
Daniel
  • 20,420
  • 10
  • 92
  • 149
0

Have you tried this way:

for _ in 0...5{
    // generate new view
    let userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % viewWidth - 90) , abs(CGFloat(arc4random()) % viewHeight - 120), 90, 90))
    userBaseView.backgroundColor = UIColor.redColor()
    // add button to view
    let button = UIButton(frame: userBaseView.bounds)
    button.backgroundColor = UIColor.yellowColor()
    button.showsTouchWhenHighlighted = true
    button.addTarget(self, action: #selector(self.handleTapEventofBtn(_:)), forControlEvents: .TouchUpInside)
    button.setTitle("hello", forState: .Normal)
    userBaseView.addSubview(button)
}
self.view.addSubview(userBaseView)

All you need is to create userBaseView before cycle, then create buttons in cycle and add them to userBaseView, after that just add userBaseView to self.view or where you need to add it. In your example you create userBaseView in every iteration of the loop.

I think the problem could be here:

userBaseView.addSubview(button)
    // add new view containing button to self.view
    self.view.addSubview(userBaseView)
}

userBaseView.addSubview(button)
baseView.addSubview(userBaseView)

First you add userBaseView to self.view in the loop:

// add new view containing button to self.view
self.view.addSubview(userBaseView)

then add it to baseView:

baseView.addSubview(userBaseView)

Can you post how it looks like in IB?

GottZ
  • 4,824
  • 1
  • 36
  • 46
Alex Kosyakov
  • 2,095
  • 1
  • 17
  • 25
0

// hi. your problem is in the selector line. try this:

for _ in 0...5 {
    // generate new view
    let  userBaseView = UIView(frame: CGRectMake(abs(CGFloat(arc4random()) % self.view.frame.size.width - 90) , abs(CGFloat(arc4random()) % self.view.frame.size.height - 120), 90, 90))
    userBaseView.backgroundColor = UIColor.redColor()
    // add button to view
    let button = UIButton(frame: userBaseView.bounds)
    button.backgroundColor = UIColor.yellowColor()
    button.showsTouchWhenHighlighted = true

    button.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)

    button.setTitle("hello", forState: .Normal)
    userBaseView.addSubview(button)
    self.view.addSubview(userBaseView)
}

// tested with xcode 7.2

func buttonAction() {
    print("working")
}
GottZ
  • 4,824
  • 1
  • 36
  • 46
Harris
  • 310
  • 3
  • 13
0

The action has a parameter so the selector signature is actually takeActionBtn:
(note the colon at the end).
You need to change that or the button will try to call a version of the function with no parameter which doesn't exist.

button.addTarget(self, action: "button:",forControlEvents: UIControlEvents.TouchUpInside)

func button(sender: UIButton!) {
    // handling code
    print("1")
}
GottZ
  • 4,824
  • 1
  • 36
  • 46
iParesh
  • 2,338
  • 1
  • 18
  • 30