Add Target for UIButton Not Being Called - ios

I posted a similar post recently and I figured out what the problem is but I don't know how to fix the problem.
In my ImageViewerViewController, my cancelButtonTapped function is not being called. But I don't think the problem, necessarily, lies in this code. Here is the code:
var image: UIImage!
var imageView: UIImageView!
var scrollView: UIScrollView!
var disableSavingImage: Bool!
var pan: UIPanGestureRecognizer!
var cancelButton: UIButton!
var cancelButtonImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.0)
setCancelButton()
}
func setCancelButton() {
self.cancelButton = UIButton(type: UIButtonType.RoundedRect)
self.cancelButton.addTarget(self, action: "cancelButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
self.cancelButton.setImage(cancelButtonImage, forState: UIControlState.Normal)
self.cancelButton.tintColor = UIColor.whiteColor()
self.cancelButton.frame = CGRectMake(self.view.frame.size.width - (self.cancelButtonImage.size.width * 2) - 18, 18, self.cancelButtonImage.size.width * 2, self.cancelButtonImage.size.height * 2)
self.view.addSubview(self.cancelButton)
}
func cancelButtonTapped(sender: UIButton) {
print("cancelButtonTapped")
}
func centerPictureFromPoint(point: CGPoint, ofSize size: CGSize, withCornerRadius radius: CGFloat) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.view.backgroundColor = UIColor(colorLiteralRed: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}) { (finished: Bool) -> Void in
}
}
I think the problem lies in my CathyTaskLogMessageViewController, when I change the code from
self.view.addSubview(imageViewerViewController.view) to self.presentViewController(imageViewerViewController, animated: true, completion: nil), my add target function gets called. Here's the code:
func defaultPictureButtonTapped(sender: UIButton) {
let imageViewerViewController = ImageViewerViewController()
imageViewerViewController.image = self.defaultPictureButton.imageView!.image
imageViewerViewController.cancelButtonImage = UIImage(named: "cancelButtonImage")
self.view.addSubview(imageViewerViewController.view)
imageViewerViewController.centerPictureFromPoint(self.defaultPictureButton.frame.origin, ofSize: self.defaultPictureButton.frame.size, withCornerRadius: self.defaultPictureButton.layer.cornerRadius)
// self.presentViewController(imageViewerViewController, animated: true, completion: nil)
}
However, I don't want to present a view controller. I want to add it as a subview. Anybody have any idea to fix this? And thank you so much for your help in advance.

The issue is in how you add child view controller.
You need to call addChildViewController(imageViewerViewController) before self.view.addSubview(imageViewerViewController.view)

Once what happened to me while using subviews was that the view was in front of the subview and hence the button on the subview was not getting tapped.
Try this:-
imageViewerViewController.view.layer.zPosition = 2
//You can set any value in place of 2 which is greater than zposition value of the view
self.view.addSubview(imageViewerViewController.view)
Hope this works.

Related

Fade image of button from one image to another via a float value

In my use case, I have a slider that moves from 0.0 to 1.0. When moving that slider I want a button's image to fade from one image to another smoothly. The button will only transition between two images. As one fades in, the other fades out and vice-versa.
There are answers on SO on how to change the image of a button over a fixed duration but I can't find something based on a changing float.
So is there a way to change the image of a button over a duration from one image to another based on a float that changes from 0.0 to 1.0?
EDIT:
For example, imagine a button that transitions smoothly from an image of a red star to a green star as you move the slider back and forth. (I know you could accomplish this other ways but I want to use two images)
Give this a shot. It is doing what you want I think. The trick is to set the layer speed to 0 and just update the timeOffset.
import UIKit
class ViewController: UIViewController {
lazy var slider : UISlider = {
let sld = UISlider(frame: CGRect(x: 30, y: self.view.frame.height - 60, width: self.view.frame.width - 60, height: 20))
sld.addTarget(self, action: #selector(sliderChanged), for: .valueChanged)
sld.value = 0
sld.maximumValue = 1
sld.minimumValue = 0
sld.tintColor = UIColor.blue
return sld
}()
lazy var button : UIButton = {
let bt = UIButton(frame: CGRect(x: 0, y: 60, width: 150, height: 150))
bt.center.x = self.view.center.x
bt.addTarget(self, action: #selector(buttonPress), for: .touchUpInside)
bt.setImage(UIImage(named: "cat1"), for: .normal)
return bt
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(button)
self.view.addSubview(slider)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addAnimation()
}
func addAnimation(){
let anim = CATransition()
anim.type = kCATransitionFade
anim.duration = 1.0
button.layer.add(anim, forKey: nil)
button.layer.speed = 0
button.setImage(UIImage(named: "cat2"), for: .normal)
}
#objc func sliderChanged(){
print("value \(slider.value)")
button.layer.timeOffset = CFTimeInterval(slider.value)
}
#objc func buttonPress(){
print("pressed")
}
}
Here is the result:
For Swift 4
//This is slider
#IBOutlet weak var mSlider: UISlider!
//Add Target for valueChanged in ViewDidLoad
self.mSlider.addTarget(self, action: #selector(ViewController.onLuminosityChange), for: UIControlEvents.valueChanged)
//called when value change
#objc func onLuminosityChange(){
let value = self.mSlider.value
print(value)
if value > 0.5 {
btnImage.imageView?.alpha = CGFloat(value)
UIView.transition(with: self.btnImage.imageView!,
duration:0.3,
options: .showHideTransitionViews,
animations: { self.btnImage.setImage(newImage, for: .normal) },
completion: nil)
}else{
btnImage.imageView?.alpha = 1 - CGFloat(value)
UIView.transition(with: self.btnImage.imageView!,
duration:0.3,
options: .showHideTransitionViews,
animations: { self.btnImage.setImage(oldImage, for: .normal) },
completion: nil)
}
}
Or Inset an Action directly via Storyboard/XIB
This is another workaround, since i tired with single button but couldn't achieve the result, so what i did is i took two buttons overlaying each other, with same size, constraints and each with separate image.
var lastSlideValue : Float = 0.0
#IBOutlet weak var slideImage: UISlider!
#IBOutlet weak var btnImageOverlay: UIButton!
#IBOutlet weak var btnSecondOverlayImage: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
btnImageOverlay.imageView?.alpha = 1.0
btnSecondOverlayImage.imageView?.alpha = 0.0
}
#IBAction func sliderValueChanged(_ sender: Any) {//UIControlEventTouchUpInside connected method
let sliderr = sender as? UISlider
let value = sliderr?.value
if lastSlideValue < (sliderr?.value ?? 0.0) {
btnSecondOverlayImage.imageView?.alpha = CGFloat(value!)
btnImageOverlay.imageView?.alpha = 1 - CGFloat(value!)
} else if lastSlideValue == sliderr?.value {
print("equal")
} else {
btnImageOverlay.imageView?.alpha = CGFloat(value!)
btnSecondOverlayImage.imageView?.alpha = 1 - CGFloat(value!)
}
}
#IBAction func userTouchedSlider(_ sender: Any) { //UIControlEventValueChanged connected method
let sliderr = sender as? UISlider
lastSlideValue = (sliderr?.value)!
}
You could use cross fade animations with single button, but binding it with slider is difficult task. Let me know if you need any assistance with the same.

Resize UISwitch in Swift 4

I would like to change the default size of the UISwitch in Swift 4.
I have looked at various options but they all relate to v3 and do not work.
Please can someone suggest an example that does so programmatically in Swift 4?
Thank you,
Edit:
I have tried the following examples:
switchTest.transform = CGAffineTransformMakeScale(0.75, 0.75)
switchTest.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
UISwitch *switchTest = [UISwitch new];
switchTest.transform = CGAffineTransformMakeScale(0.75, 0.75);
The error message that I received is always the same and says this:
Expected declaration
Swift 4 Code
Method 1
Drag UISwitch Storyboard. Make an outlet of your UISwitch and replace ViewDidLoad method by this code.
#IBOutlet weak var switchDemo: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
switchDemo.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
}
Method 2
Make UISwitch through programmatically.
class ViewController: UIViewController {
let switchSwift4 = UISwitch(frame:CGRect(x: 150, y: 300, width: 0, height: 0))
override func viewDidLoad() {
super.viewDidLoad()
self.switchSwift4.isOn = true
switchSwift4.setOn(true, animated: false)
switchSwift4.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
switchSwift4.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
self.view!.addSubview(switchSwift4)
}
#objc func switchValueDidChange(_ sender: UISwitch) {
if switchSwift4.isOn == true {
print("On")
}
else {
print("Off")
}
}
}

Spawning UIView every second at random CGPoint in Swift

I am trying to "spawn" a UIView with a random UIColor as its background at a random CGPoint. I am using the code below which compiles fine with no bugs or anything but when it runs in the simulator I click start(the button on the first ViewController) but then go to ViewTwo but nothing happens(no "enemies" are spawned). Thank you for any help.
import UIKit
var randomPoint: CGPoint = CGPoint(x: Int(arc4random()%1000), y: Int(arc4random()%1000))
class ViewController: UIViewController {
#IBOutlet weak var startGameButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
class ViewTwo : UIViewController {
var timer = NSTimer()
func randomColor() -> UIColor {
let red = CGFloat(drand48())
let green = CGFloat(drand48())
let blue = CGFloat(drand48())
return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
func spawnEnemy() {
let enemy: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
enemy.backgroundColor = randomColor()
enemy.center = randomPoint
self.view.addSubview(enemy)
}
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("spawnEnemy"), userInfo: nil, repeats: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Your randomPoint needs to be recalculated in spawnEnemy, and is generating a random x y from 0 to 1000 (and should also be a float) It will likely be off the screen.

Add Target for UIButton Not Called

I have two view controllers that I am currently working with. In my CathyTaskLogMessageViewController, I have this code:
func defaultPictureButtonTapped(sender: UIButton) {
let imageViewerViewController = ImageViewerViewController()
imageViewerViewController.image = self.defaultPictureButton.imageView!.image
imageViewerViewController.cancelButtonImage = UIImage(named: "cancelButtonImage")
imageViewerViewController.centerPictureFromPoint(self.defaultPictureButton.frame.origin, ofSize: self.defaultPictureButton.frame.size, withCornerRadius: self.defaultPictureButton.layer.cornerRadius)
self.view.addSubview(imageViewerViewController.view)
}
And in my ImageViewerViewController, I have this code:
var image: UIImage!
var imageView: UIImageView!
var scrollView: UIScrollView!
var disableSavingImage: Bool!
var pan: UIPanGestureRecognizer!
var cancelButton: UIButton!
var cancelButtonImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.0)
setCancelButton()
}
func setCancelButton() {
self.cancelButton = UIButton(type: UIButtonType.RoundedRect)
self.cancelButton.addTarget(self, action: "cancelButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
self.cancelButton.setImage(cancelButtonImage, forState: UIControlState.Normal)
self.cancelButton.tintColor = UIColor.whiteColor()
self.cancelButton.frame = CGRectMake(self.view.frame.size.width - (self.cancelButtonImage.size.width * 2) - 18, 18, self.cancelButtonImage.size.width * 2, self.cancelButtonImage.size.height * 2)
self.view.addSubview(self.cancelButton)
}
func cancelButtonTapped(sender: UIButton) {
print("cancelButtonTapped")
}
func centerPictureFromPoint(point: CGPoint, ofSize size: CGSize, withCornerRadius radius: CGFloat) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.view.backgroundColor = UIColor(colorLiteralRed: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}) { (finished: Bool) -> Void in
}
}
Now, when I tap the cancel button, it should print "cancelButtonTapped" in the console. However, there is not output from the console.
I think the problem has to do with the button being in a different subview perhaps? I'm not exactly sure. Anybody have a solution to this problem?
Also, when the cancel button loads, it loads from the left and moves to the right. Is there a way that the button just appears on the top right hand corner?
Thank you in advance for your help.
change background color, so you can identify the problem.
put this line in viewDidLayoutSubviews() this method so it loads from the left and moves to the right can solve
code:
override func viewDidLayoutSubviews() {
self.cancelButton.frame = CGRectMake(self.view.frame.size.width - (self.cancelButtonImage.size.width * 2) - 18, 18, self.cancelButtonImage.size.width * 2, self.cancelButtonImage.size.height * 2)
}

animating button Allowuserinteraction not working

I have a UIbutton created in code in an NSObject class which controls a game in a UIViewController class. The button works fine throughout most of the game, but at a certain point I want the button to fadein/out. Once the fadein/out starts animating the button is no longer interactive. I have set the .AllowUserInteraction option, but still no luck. I am stumped on this one, so any help much appreciated!
Class GameController: NSObject {
var gameView: UIView!
var nextButton: UIButton!
func gameViewSetUp() {
// create the nextButton
let imageNextButton = UIImage(named: "rightArrow") as UIImage?
self.nextButton = UIButton(type: .Custom)
nextButton.frame = CGRectMake(ScreenWidth-100,ScreenHeight-250,60,60)
nextButton.setTitle("", forState: UIControlState.Normal)
nextButton.setImage(imageNextButton, forState: .Normal)
nextButton.contentMode = .ScaleAspectFill
nextButton.backgroundColor = UIColor.clearColor()
nextButton.layer.cornerRadius = 5.0
nextButton.layer.borderWidth = 2.5
nextButton.layer.borderColor = UIColor.clearColor().CGColor
nextButton.addTarget(self, action: "nextPressed", forControlEvents: .TouchUpInside)
nextButton.userInteractionEnabled = true
gameView.addSubview(nextButton)
func playStageX() {
nextButtonWink()
}
}
func nextButtonWink() {
UIView.animateWithDuration(1.5, delay: 0, options: [.AllowUserInteraction, .Repeat, .CurveEaseInOut, .Autoreverse],
animations: {
// self.nextButton.userInteractionEnabled = true // I tried this as well but no impact.
self.nextButton.alpha = 0
}, completion: nil)
}
class GameViewController: UIViewController {
private var controller: GameController
required init?(coder aDecoder: NSCoder) {
controller = GameController()
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
let gameView = UIView(frame: CGRectMake(0, 0, ScreenWidth, ScreenHeight))
self.view.addSubview(gameView)
controller.gameView = gameView
}
Take out self.nextButton.alpha = 0 to test this out, I believe that button events will not fire when alpha is zero. When it comes to animations, the actual object's alpha will get set to zero before the animation starts, and what you are seeing is like a rendered interactive screenshot of your view as it animates
If that is the case, then you need to set the alpha to something like 0.0100000003 or override the button to be interactive at alpha 0
Swift 3 Xcode 8:
AllowUserAction is now deprecated to allowUserAction.... go figure
func nextButtonWink() {
UIView.animateWithDuration(1.5, delay: 0, options: [.allowUserInteraction,
animations: {

Resources