UIButton not working loaded in a child ViewController - ios

I've got a MainViewController where I'm loading a slideout-menu. The MainViewController contains a static TopView and a ContentView where different child controllers or views are loaded, depending on which menu entry was selected.
There is a button inside one of the children is loaded, but it is not working.
When I start the app with the ViewController including the button, set to "is initial View Controller", everything works properly.
When starting the app with the MainViewController as initial View Controller with a loaded child, the button is not working (it is loaded in the view, but not reacting).
Any suggestions how I can make this work?
MainViewController loading of Child View
class MainViewController: UIViewController, SideBarDelegate {
var contentView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
....
contentView.backgroundColor = UIColor(red: 70/255, green: 174/255, blue: 253/255, alpha: 1)
contentView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(contentView)
contentView.topAnchor.constraint(equalTo: statusBarView.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
contentView.layoutIfNeeded()
}
func sideBarDidSelectButtonAtIndex(_ index: Int) {
...
if index == 0{
statusBarLabel.text = "First"
let controller:FirstViewController = storyboard!.instantiateViewController(withIdentifier: "First") as! FirstViewController
controller.view.frame = ContentView.bounds
controller.willMove(toParentViewController: self)
contentView.addSubview(controller.view)
controller.didMove(toParentViewController: self)
print("touched index 0")
} else if index == 1{
// index is 1
}
}
FirstViewController
class FirstViewController: UIViewController, UIScrollViewDelegate {
let addButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 230/255, green: 230/255, blue: 230/255, alpha: 1)
addButton.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 60)
addButton.clipsToBounds = true
addButton.setTitleColor(UIColor.white, for: .normal)
addButton.backgroundColor = UIColor(red: 102/255, green: 204/255, blue: 255/255, alpha: 1)
addButton.setTitle("add feed", for: .normal)
addButton.titleLabel?.font = UIFont.systemFont(ofSize: 20, weight: UIFontWeightRegular)
self.view.addSubview(AddButton)
addButton.layoutIfNeeded()
addButton.addTarget(self, action: #selector(touchUpAddButton), for: UIControlEvents.touchUpInside)
addButton.addTarget(self, action: #selector(touchDownAddButton), for: UIControlEvents.touchDown)
func touchUpAddButton() {
addButton.backgroundColor = UIColor(red: 102/255, green: 204/255, blue: 255/255, alpha: 1)
}
func touchDownAddButton() {
addButton.backgroundColor = UIColor(red: 70/255, green: 174/255, blue: 253/255, alpha: 1)
}
}

While adding the view in the container you don't have to use addSubview function, that the FirstViewController functionality is not working.
Use below code:
let newViewController:FirstViewController = storyboard!.instantiateViewController(withIdentifier: "First") as! FirstViewController
let oldViewController = childViewControllers.last! as UIViewController
oldViewController.willMove(toParentViewController: nil)
addChildViewController(newViewController)
transition(from: oldViewController, to: newViewController, duration: 0.25, options: .transitionCrossDissolve, animations:{ () -> Void in
// nothing needed here
}, completion: { (finished) -> Void in
oldViewController.removeFromParentViewController()
newViewController.didMove(toParentViewController: self)
})
You can change the duration, it used for animation

Update your functions to these
func TouchUpAddButton(sender: UIButton){
addButton.backgroundColor = UIColor(red: 102/255, green: 204/255, blue: 255/255, alpha: 1)
}
func TouchDownAddButton(sender: UIButton) {
addButton.backgroundColor = UIColor(red: 70/255, green: 174/255, blue: 253/255, alpha: 1)
}
And change your code of adding the target to
addButton.addTarget(self, action: #selector(FirstViewController.touchUpAddButton(_:)), for: .touchDown)
addButton.addTarget(self, action: #selector(FirstViewController.touchDownAddButton(_:)), for: .touchDown)

First solution:
Remove an autolayout constrains
Second solution:
Button is not performing an action because a child view controller view should be added directly to a container controller view (in your case: MainViewController view) and not via an intermediate view (in your case: contentView)

Related

Color of label does not change when used in animation

#IBAction func firstButton(_ sender: UIButton) {
if textLabel.text == "Cat" {
textLabel.backgroundColor = .green
view.backgroundColor = .green
secondButtonOutlet.isHidden = false
firstButtonOutlet.isHidden = true
picker.isHidden = true
buttonBackOutlet.isHidden = false
} else {
secondButtonOutlet.isHidden = true
countMistakes += 1
view.backgroundColor = .systemRed
textLabel.backgroundColor = .systemRed
UIView.animate(withDuration: 0, delay: 1, options: .allowAnimatedContent, animations: {
() -> () in
self.view.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
self.textLabel.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
}, completion: nil)
}
}
I have this code. My goal is to make an animation of red screen blinking. Everything goes well until textLabel. It doesn't want to change its color at all. Can anyone help me how to fix it ? (Background color is changing, so the code should be correct in overall).

Adding UIButton to toolbar swift 5

so I have read other stack overflow ages and none seem to help me. I have a piece of code that creates my UIButton which is here:
let haveAccountButton: UIButton = {
let HColor = UIColor(red: 89/255, green: 156/255, blue: 120/255, alpha: 1)
let HFont = UIFont.systemFont(ofSize: 16)
let HSColor = UIColor(red: 239/255, green: 47/255, blue: 102/255, alpha: 1)
let HButton = UIButton(type: .system)
let attributedTitle = NSMutableAttributedString(string:
NSLocalizedString("Already have an account?", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray, NSAttributedString.Key.font: HFont])
attributedTitle.append(NSAttributedString(string: NSLocalizedString(" Sign In", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: HSColor, NSAttributedString.Key.font: HFont]))
HButton.addTarget(self, action: #selector(signinAction), for: .touchUpInside)
HButton.setAttributedTitle(attributedTitle, for: .normal)
return HButton
}()
I already set navigationController?.isToolbarHidden = false in viewDidLoad. my question is how do I make the button appear in the toolbar?
UPDATE: The way this code will run currently without the toolbar is as follows:
import Foundation
import UIKit
class SignUpControllerSave: UIViewController {
let haveAccountButton: UIButton = {
let HColor = UIColor(red: 89/255, green: 156/255, blue: 120/255, alpha: 1)
let HFont = UIFont.systemFont(ofSize: 16)
let HSColor = UIColor(red: 239/255, green: 47/255, blue: 102/255, alpha: 1)
let HButton = UIButton(type: .system)
let attributedTitle = NSMutableAttributedString(string:
NSLocalizedString("Already have an account?", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray, NSAttributedString.Key.font: HFont])
attributedTitle.append(NSAttributedString(string: NSLocalizedString(" Sign In", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: HSColor, NSAttributedString.Key.font: HFont]))
HButton.addTarget(self, action: #selector(signinAction), for: .touchUpInside)
HButton.setAttributedTitle(attributedTitle, for: .normal)
return HButton
}()
//potential gradient background if wanted
func setGradientBackground() {
let top_Color = UIColor(red: 203/255, green: 215/255, blue: 242/255, alpha: 1.0).cgColor
let bottom_Color = UIColor(red: 181/255, green: 199/255, blue: 242/255, alpha: 1.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [top_Color, bottom_Color]
gradientLayer.locations = [0, 1]
gradientLayer.frame = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at: 0)
}
override func viewDidLoad() {
super.viewDidLoad()
//view.backgroundColor = .yellow
navigationController?.isNavigationBarHidden = true
navigationController?.isToolbarHidden = false
navigationItem.title = NSLocalizedString("Membership", comment: "")
setupHaveAccountButton()
}
override func viewWillAppear(_ animated: Bool) {
navigationController?.isNavigationBarHidden = true
navigationController?.isToolbarHidden = false
setGradientBackground()
super.viewWillAppear(animated)
}
#objc func signinAction() {
navigationController?.popViewController(animated: true)
}
fileprivate func setupHaveAccountButton() {
view.addSubview(haveAccountButton)
haveAccountButton.anchors(top: nil, topPad: 0, bottom: view.safeAreaLayoutGuide.bottomAnchor,
bottomPad: 8, left: view.leftAnchor, leftPad: 0, right: view.rightAnchor,
rightPad: 0, height: 20, width: 0)
}
}
UPDATE: The previous answer did allow for the button to now be on the toolbar, but the button target action does not work. I have tried adding .sizeToFit() where I can and looked at a lot of websites all to no avail. Anyone know how I can go about solving the button target issue?
This code should work the way you want:
class SignUpControllerSave: UIViewController {
/* the other code you posted can be used without changes */
fileprivate func setupHaveAccountButton() {
toolbarItems = [
UIBarButtonItem(customView: haveAccountButton)
]
}
}
As this seems to cause problems with regards to the click handler, try this (which looks almost the same – except for the font size):
class SignUpControllerSave: UIViewController {
fileprivate func setupHaveAccountButton() {
let haveAccountLabel = UILabel()
haveAccountLabel.font = UIFont.systemFont(ofSize: UIFont.buttonFontSize)
haveAccountLabel.text = NSLocalizedString("Already have an account?", comment: "")
haveAccountLabel.textColor = .lightGray
toolbarItems = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(customView: haveAccountLabel),
UIBarButtonItem(title: "Sign In", style: .plain, target: self, action: #selector(self.signinAction)),
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
]
navigationController?.toolbar.tintColor = UIColor(red: 239/255, green: 47/255, blue: 102/255, alpha: 1)
}
}

How to hide elements in a Stack View

I have 4 separate views and I want to hide the other 3 of them when one of the buttons is pressed.
I have them in a UIStackView but .isHidden = true does not hide the views for some reason.
It works fine when they're not in a stack view.
#IBAction func qbpressed(_ sender: Any) {
QBContainer.isHidden = false
WRContainer.isHidden = true
RBContainer.isHidden = true
QBIndicator.isHidden = false
WRIndicator.isHidden = true
RBIndicator.isHidden = true
TEIndicator.isHidden = true
QBButton.setTitleColor(#colorLiteral(red: 0, green: 0.5008062124, blue: 1, alpha: 1), for: .normal)
WRButton.setTitleColor(#colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 1), for: .normal)
RBButton.setTitleColor(#colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 1), for: .normal)
TEButton.setTitleColor(#colorLiteral(red: 0.7540688515, green: 0.7540867925, blue: 0.7540771365, alpha: 1), for: .normal)
if intersitial.isReady{
intersitial.present(fromRootViewController: self)
}
}
isHidden property doesn't work, but you can use alpha and achieve the same result,
QBIndicator.alpha = 1.0 will work for QBIndicator.isHidden = false and
QBIndicator.alpha = 0.0 will work for QBIndicator.isHidden = true
setting a view to hidden should make it no longer visible, regardless of whether or not it inside a UIStackView.
The benefit of UIStackView is that it provides free animation through the isHidden property, like so:
// Assuming stackViewSubView.isHidden == false here
UIView.animate(withDuration: 0.25, animations: {
self.stackViewSubView.isHidden = true
self.view.layoutIfNeeded()
})

Sigabrt when trying to display another view controller

I want to go to another view controller when pressing button my btnSignUp, If I write code like this I have error "sigabrt". What I should do?
import UIKit
import SnapKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
createTop()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func createTop() {
let topView = UIView()
self.view.addSubview(topView)
topView.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
topView.snp_makeConstraints { (make) -> Void in
make.width.equalTo((self.view.frame.width/10)*8)
make.height.equalTo(self.view.frame.height/5)
make.centerX.equalTo(self.view)
make.top.equalTo(self.view).offset(self.view.frame.height/15)
}
let btnSignUp = UIButton()
self.view.addSubview(btnSignUp)
btnSignUp.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
btnSignUp.layer.borderColor = UIColor.whiteColor().CGColor
btnSignUp.layer.borderWidth = 1
btnSignUp.layer.cornerRadius = 6
btnSignUp.setTitle("Sign Up", forState: UIControlState.Normal)
btnSignUp.titleLabel?.font = UIFont(name: "AvenirNext-Regular", size: 17)
btnSignUp.snp_makeConstraints { (make) -> Void in
make.width.equalTo(((self.view.frame.width/10)*7)+40)
make.height.equalTo(self.view.frame.height/13)
make.top.equalTo(ORView.snp_bottom).offset(20)
make.centerX.equalTo(self.view)
}
btnSignUp.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
func buttonAction(sender:UIButton!)
{
let signUpVC = SignUpViewController()
self.presentViewController(signUpVC, animated: true, completion: nil)
}
}
}
Your action selector buttonAction doesn't match your function declaration - It takes an argument, so the selector will be buttonAction:
btnSignUp.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
Additionally, check your parentheses. It appears that your buttonAction function is declared inside func createTop()
func createTop() {
let topView = UIView()
self.view.addSubview(topView)
topView.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
topView.snp_makeConstraints { (make) -> Void in
make.width.equalTo((self.view.frame.width/10)*8)
make.height.equalTo(self.view.frame.height/5)
make.centerX.equalTo(self.view)
make.top.equalTo(self.view).offset(self.view.frame.height/15)
}
let btnSignUp = UIButton()
self.view.addSubview(btnSignUp)
btnSignUp.backgroundColor = UIColor(red: 15/255, green: 52/255, blue: 100/255, alpha: 1)
btnSignUp.layer.borderColor = UIColor.whiteColor().CGColor
btnSignUp.layer.borderWidth = 1
btnSignUp.layer.cornerRadius = 6
btnSignUp.setTitle("Sign Up", forState: UIControlState.Normal)
btnSignUp.titleLabel?.font = UIFont(name: "AvenirNext-Regular", size: 17)
btnSignUp.snp_makeConstraints { (make) -> Void in
make.width.equalTo(((self.view.frame.width/10)*7)+40)
make.height.equalTo(self.view.frame.height/13)
make.top.equalTo(ORView.snp_bottom).offset(20)
make.centerX.equalTo(self.view)
}
btnSignUp.addTarget(self, action: "buttonAction", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonAction(sender:UIButton!) {
let signUpVC = SignUpViewController()
self.presentViewController(signUpVC, animated: true, completion: nil)
}
Finally, I doubt that you want to get your new view controller by SignUpViewController() - if you are using a storyboard you want to call instantiateViewControllerWithIdentifier

Swift adding button into view programatically with action

I am trying to add button to the programatically created view that I add to main view. I can't make action to work on a button. This is what I tried so far:
itemView = UIImageView(frame:CGRect(x:0, y:0, width:240, height:375))
itemView.backgroundColor = UIColor(red: 255.0/0.0, green: 255.0/0.0, blue: 255.0/0.0, alpha: 0.05)
itemView.contentMode = .Center
buttonConnect = UIButton(frame: CGRect(x:0, y:335, width:120, height:40))
buttonConnect.backgroundColor = UIColor(red: 0.8, green: 0.6, blue: 0.2, alpha: 1.0)
buttonConnect.setTitle("Connect", forState: .Normal)
buttonConnect.tag = 3
buttonConnect.addTarget(itemView, action: "btnConnectTouched:", forControlEvents:.TouchDown)
itemView.addSubview(buttonConnect)
self.addSubview(itemView)
Method on button click looks like this:
func btnConnectTouched(sender:UIButton!)
{
print("button connect touched")
}
Can someone advice what is the problem? Thanks!
I don't understand why you are adding a button inside a UIImageView. Even this is what you need, take a UIView and then put all other controls inside it. The reason your button is not clicking is that you have put it inside a UIImageView and for UIImageView , default value for userInteractionEnabled is false. so you need to enable it i.e.
itemView.userInteractionEnabled = true;
Also set button target to 'self' rather than itemView.
Try change the tarjet and the event
buttonConnect.addTarget(itemView, action: "btnConnectTouched:", forControlEvents:.TouchDown)
into
buttonConnect.addTarget(self, action: "btnConnectTouched:", forControlEvents:. TouchUpInside)
You are wrong at the target:
// buttonConnect.addTarget(itemView, action: "btnConnectTouched:", forControlEvents:.TouchDown)
// using
buttonConnect.addTarget(self, action: "btnConnectTouched:", forControlEvents:.TouchDown)
// or buttonConnect.addTarget(self, action: "btnConnectTouched:", forControlEvents:.TouchUpInside)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let buttonConnect = UIButton()
buttonConnect = UIButton(frame: CGRect(x:0, y:335, width:120, height:40))
buttonConnect.backgroundColor = UIColor(red: 0.8, green: 0.6, blue: 0.2, alpha: 1.0)
buttonConnect.setTitle("Connect", forState: .Normal)
buttonConnect.tag = 3
buttonConnect.addTarget(self, action: "btnConnectTouched:", forControlEvents: .TouchUpInside)
self.view.addSubview(buttonConnect)
}
func btnConnectTouched(sender: UIButton!) {
print("button connect touched");
}
try buttonConnect.addTarget(itemView, action: "btnConnectTouched", forControlEvents:.TouchUpInside) without the : after "btnConnectTouched"
If you can make following two changes in your code, it will work.
Replace UIImageView with UIView for itemView type and
Replace self.addSubview(itemView) with self.view.addSubview(itemView)
Your final code should look like....
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var itemView = UIView(frame:CGRect(x:0, y:0, width:240, height:375))
itemView.backgroundColor = UIColor(red: 255.0/0.0, green: 255.0/0.0, blue: 255.0/0.0, alpha: 0.05)
itemView.contentMode = .Center
var buttonConnect = UIButton(frame: CGRect(x:0, y:335, width:120, height:40))
buttonConnect.backgroundColor = UIColor(red: 0.8, green: 0.6, blue: 0.2, alpha: 1.0)
buttonConnect.setTitle("Connect", forState: .Normal)
buttonConnect.tag = 3
buttonConnect.addTarget(self, action: "btnConnectTouched:", forControlEvents:.TouchDown)
itemView.addSubview(buttonConnect)
self.view.addSubview(itemView)
}
func btnConnectTouched(sender:UIButton!)
{
print("button connect touched")
}
Try this one.... It's working for me....

Resources