Swift adding button into view programatically with action - ios

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....

Related

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 create multiple button on and off common codebase using Swift

In my case, I am trying to create multiple buttons using storyboard. Here, each buttons having on and off background and title color change. In this process as of now I am doing same logic repeated in each button action. Now, instead of that I have to create a common function within one time logics for all button action have to call and work like a on and off individually.
How to make this below logic in a common function and call it from multiple button actions.
Code Base
#IBAction func firstbuttonClick(_ sender: Any) {
if button_isActive {
self.tasktypeButton.backgroundColor = #colorLiteral(red: 0.1843137255, green: 0.6823529412, blue: 0.9764705882, alpha: 1)
self.tasktypeButton.setTitleColor(UIColor.white, for: .normal)
} else {
self.tasktypeButton.backgroundColor = #colorLiteral(red: 0.80803, green: 0.803803, blue: 0.805803, alpha: 1)
self.tasktypeButton.setTitleColor(UIColor.darkGray, for: .normal)
}
button_isActive = !button_isActive
}
You can connect all UIButton action in one like below code.
#IBAction func btnTapped(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
sender.setTitleColor(UIColor.white, for: .normal)
sender.backgroundColor = UIColor.red
}
else {
sender.setTitleColor(UIColor.black, for: .normal)
sender.backgroundColor = UIColor.white
}
//For identifing which button is tapped
if sender.tag == 1 {
// Do your task
}
else if sender.tag == 2 {
// Do your task
}
}
If you want to detect which button is tapped, you can set tag to UIButton from UIStoryBoard.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func btnactn(btnTag:Int)
{
print(btnTag)
switch btnTag {
case 0:
self.btn1.backgroundColor = #colorLiteral(red: 0.1843137255, green: 0.6823529412, blue: 0.9764705882, alpha: 1)
self.btn1.setTitleColor(UIColor.white, for: .normal)
case 1:
self.btn2.backgroundColor = #colorLiteral(red: 0.80803, green: 0.803803, blue: 0.805803, alpha: 1)
self.btn2.setTitleColor(UIColor.white, for: .normal)
default:
break
}
}
#IBAction func btnActn1(_ sender: UIButton)
{
self.btnactn(btnTag: sender.tag)
}
#IBAction func btnActn2(_ sender: UIButton)
{
self.btnactn(btnTag: sender.tag)
}}
its working i have tried this. you just need to connect button outlets and its functions.you can try this.
First of all connect all the UIButtons in the storyboard to the same #IBAction. Also, don't forget to select the UIButton as parameter type when creating the #IBAction.
Next, in the method sender is the UIButton that is clicked. So you can use that for further configuration.
#IBAction func buttonClicked(_ sender: UIButton) {
sender.backgroundColor = sender.isSelected ? #colorLiteral(red: 0.1843137255, green: 0.6823529412, blue: 0.9764705882, alpha: 1) : #colorLiteral(red: 0.80803, green: 0.803803, blue: 0.805803, alpha: 1)
sender.setTitleColor(sender.isSelected ? .white : .darkGray, for: .normal)
//User sender to get the button that is clicked...
let title = sender.titleLabel?.text
print(title)
sender.isSelected = !sender.isSelected
}
One more thing, use isSelected to manage the backgroundColor and titleColor of the button instead of a separate button_isActive property.
You can create only one function as below and connect all the button actions in storyboard to this function so that any button will update its state.
#IBAction private func buttonAction(_ sender: UIButton) {
if button_isActive {
sender.backgroundColor = #colorLiteral(red: 0.1843137255, green: 0.6823529412, blue: 0.9764705882, alpha: 1)
sender.setTitleColor(UIColor.white, for: .normal)
} else {
sender.backgroundColor = #colorLiteral(red: 0.80803, green: 0.803803, blue: 0.805803, alpha: 1)
sender.setTitleColor(UIColor.darkGray, for: .normal)
}
button_isActive = !button_isActive
// To differentiate different buttons
switch (sender.tag) {
case 0:
print(sender.title(for: .normal))
case 1:
print(sender.title(for: .normal))
default:
print(sender.title(for: .normal))
}
}
You can also set tag for each in the storyboard and differentiate in above method to know what button click is this.

can't set up UISwitch in Swift 4

Getting rustily back into iOS programming after some years away and am having trouble setting up a UISwitch. Here's my code:
#IBOutlet weak var firstConjugationVerbSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
firstConjugationVerbSwitch.addTarget(self, action: #selector(changeText), for: .valueChanged)
}
#objc func changeText() {
print("changeText function running.")
}
The error I get when I toggle the switch is
[Latin_Substitution_Drills.VerbOptionsViewController firstConjugationVerbSwitch:]: unrecognized selector sent to instance 0x7ffcea817600
Any thoughts about what I'm doing wrong?
let customSwitch = UISwitch(frame:CGRect(x: 20, y: 20, width: 0, height: 0))
customSwitch.isOn = false
customSwitch.onTintColor = UIColor(red: 10/255, green: 105/255, blue: 122/255, alpha: 1)
//customSwitch.setOn(true, animated: true)
customSwitch.transform = CGAffineTransform(scaleX: 0.60, y: 0.60)
customSwitch.addTarget(self, action: #selector(switchTarget(sender:)), for: .valueChanged)
let switchButton = UIBarButtonItem(customView: customSwitch)
#objc func switchTarget(sender: UISwitch!)
{
if sender.isOn {
// do something ..
} else{
// do something ..
}
}

UIButton not working loaded in a child ViewController

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)

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

Resources