How to connect multiple buttons in a storyboard to a single action, by code not drag&drop? - swift

I'm currently using Xcode 7.3 and I'm simply wondering how to select multiple buttons across different UIViews, but under a single view controller. CMD clicking doesn't seem to work. I need this functionality because in Xcode 7.3 the only way to let two buttons on IB to share the same action is to select them at once and then drag the action to your view controller. I'm doing this by code and no drag & drop
class LogIn: UIViewController {
var mail_tf : UITextField!
var pass_tf : UITextField!
var btnL : UIButton!
var btnC : UIButton!
let cl1 = UIColor (red: 255/255.0, green: 258/255.0, blue: 196/255.0, alpha: 1)
let cl2 = UIColor (red: 238/255.0, green: 233/255.0, blue: 191/255.0, alpha: 1)
override func loadView() {
super.loadView()
let backgroundView = UIImageView(image: UIImage(named: "4")!)
//backgroundView.layer.cornerRadius = backgroundView.frame.size.width / 2
backgroundView.frame = CGRectMake(0, 0, 900, 900)
//backgroundView.clipsToBounds = true
//backgroundView.layer.borderColor = UIColor.whiteColor().CGColor
// backgroundView.layer.borderWidth = 1
self.view.addSubview(backgroundView)
mail_tf = UITextField()
mail_tf.frame = CGRectMake(95, 90, 190, 60)
mail_tf.layer.cornerRadius = 10
mail_tf.layer.borderWidth = 1
mail_tf.layer.borderColor = UIColor.blackColor().CGColor
mail_tf.placeholder = "e-mail"
mail_tf.textColor = UIColor.redColor()
mail_tf.backgroundColor = cl1
mail_tf.borderStyle = UITextBorderStyle.RoundedRect
self.view.addSubview(mail_tf)
pass_tf = UITextField()
pass_tf.frame = CGRectMake(95, 190, 190, 60)
pass_tf.layer.cornerRadius = 10
pass_tf.layer.borderWidth = 1
pass_tf.layer.borderColor = UIColor.blackColor().CGColor
pass_tf.placeholder = "password"
pass_tf.secureTextEntry = true
pass_tf.textColor = UIColor.redColor()
pass_tf.backgroundColor = cl1
pass_tf.borderStyle = UITextBorderStyle.RoundedRect
self.view.addSubview(pass_tf)
btnL = UIButton()
btnL.frame = CGRectMake(195, 260, 90, 40)
btnL.setTitle("Log In ", forState: UIControlState.Normal)
btnL.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
btnL.layer.borderWidth = 1
btnL.layer.borderColor = UIColor.blackColor().CGColor
btnL.layer.cornerRadius = 10
btnL.backgroundColor = cl1
self.view.addSubview(btnL)
btnL.addTarget(self , action: #selector(self.action(_:)), forControlEvents: UIControlEvents.TouchUpInside)
btnC = UIButton()
btnC.frame = CGRectMake(228, 350, 150, 40)
btnC.setTitle("Create new account ", forState: UIControlState.Normal)
btnC.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
btnC.layer.borderWidth = 1
btnC.layer.borderColor = UIColor.blackColor().CGColor
btnC.layer.cornerRadius = 10
btnC.backgroundColor = cl1
self.view.addSubview(btnC)
btnC.addTarget(self , action: #selector(self.action(_:)), forControlEvents: UIControlEvents.TouchUpInside)
}
func action (sender: UIButton!) {
// btnL & btnC open the Logged_in file . there is the problem
let vc = Logged_In()
let navigation = UINavigationController(rootViewController:vc)
self.navigationController?.presentViewController(navigation, animated: true, completion: nil)
let vc1 = create()
let navigation1 = UINavigationController(rootViewController:vc1)
self.navigationController?.presentViewController(navigation1, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Log in"
self.navigationController?.navigationBar.barTintColor = UIColor.blackColor()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: cl1]
}
}

EDITED ANSWER:
Okay, I think I understand what you are asking now. You want to have the same function action(sender: UIButton) do a different action depending on the button that calls it.
You can actually set a variable called tag and set a number to make it unique. For example btnL.tag = 0 and btnC.tag = 1
So then your function action would look like this:
func action (sender: UIButton!) {
if sender.tag == 0 {
let vc = Logged_In()
let navigation = UINavigationController(rootViewController:vc)
self.navigationController?.presentViewController(navigation, animated: true, completion: nil)
} else if sender.tag == 1 {
let vc1 = create()
let navigation1 = UINavigationController(rootViewController:vc1)
self.navigationController?.presentViewController(navigation1, animated: true, completion: nil)
}
}
A UIButton has a function that does this, specifically:
public func addTarget(target: AnyObject?, action: Selector, forControlEvents controlEvents: UIControlEvents)
The buttons need to be declared like this: #IBOutlet var button: UIButton above the class.
To add an action we call the above function in your class (viewController) that has access to variable button:
button.addTarget(self, action: #selector(self.sender(_:)), forControlEvents: .TouchDown)
You'll need to repeat this for each UIButton but the selector function will just be the same (ei, button1.addTarget(...), button2.addTarget(...), etc).
Your function will look something like this:
func sender(sender: UIButton) { }

You can probably iterate through all the buttons you want to add action to
for button in [button1, button2, button3, button4] {
button.addTarget(self, action: #selector(self.someFunction), forControlEvents: .TouchUpInside)
}

Search for all of your buttons and add the same target:
override func viewDidLayoutSubviews() {//This cannot be view did load; it can be view did appear or view will appear
super.viewDidLayoutSubviews()
for subview in self.view.subviews {
if let button = subview as? UIButton {
button.addTarget(target: self, action: #selector(self.someFunc), forControlEvents: .touchUpInside)
}
}
}

Related

How to create action for UIButton in UIKit

I just created a UIButton and I want to do some action when I click on it i don't know how to do it , here is my way to just create uibutton only !!!:
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
return seeMoreBtn
}()
The modern way is to add the action as a UIAction.
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
let action = UIAction { action in
print("howdy!")
}
test.addAction(action, for: .touchUpInside)
return test
}()
Nicer syntax can be achieved through an extension, as I demonstrate here.
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
test.addTarget(self, action: #selector(self.buttonPressedAction), for: .touchUpInside) // add target
return seeMoreBtn
}()
#objc func buttonPressedAction() {
//This function will get called when u press the button.
//include here what u want to do.
}
#objc func buttonAction() {
print("Button Tapped")
}
test.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
I have given the example for create the custom button and the custom label and set constraint in coding. The below code also contains the programmatically button action.
import UIKit
class ViewController: UIViewController {
let button = UIButton(frame: CGRect(x: 100,y: 400,width: 200,height: 60))
var label = UILabel(frame: CGRect(x: 100, y: 200, width: 200, height: 60))
var count : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
button.setTitle("Click Button",for: .normal)
button.backgroundColor = UIColor.blue
button.setTitleColor(.white, for: .normal)
button.addTarget(self,action: #selector(buttonAction),for: .touchUpInside)
label.font = .systemFont(ofSize: 50)
label.backgroundColor = UIColor.gray
label.textAlignment = .center
self.view.addSubview(button)
self.view.addSubview(label)
}
#objc
func buttonAction() {
self.count += 1
self.label.text = "\(count)"
}
}
Output :-
Value of label increases when the button is click.

swift playgrounds display uiview with nonstop looping

I create and display uiview in live view windows, when i create the button and add to the uiview , the program fail with nonstop looping which continuously load addbutton . Did somebody meet this problem and please tell me why :-)
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
var label1 : UILabel?
override func loadView() {
let view = UIView()
view.backgroundColor = .white
print("code run here ")
let label = UILabel()
label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.text = "Hello World!"
label.textColor = .black
label1 = label
view.addSubview(label)
let k1:UIButton = addnewbutton() as! UIButton
//view.addSubview(k1)
self.view = view
}
#objc func buttonPressed(sender: UIButton!) {
var alertController = UIAlertController(title: "title", message: "message", preferredStyle: UIAlertControllerStyle.alert)
self.present(alertController, animated: true, completion: nil)
}
func addnewbutton() -> UIView{
var btn : UIButton
btn = UIButton()
btn.frame = CGRect(x:200,y:300,width:100,height:25)
btn.setTitle("clickme",for: UIControlState.normal)
//btn.titleLabel?.text = "clickme"
btn.backgroundColor = UIColor.black
btn.titleLabel?.textColor = UIColor.white
btn.titleColor(for: UIControlState.normal)
btn.addTarget(self, action: #selector(buttonPressed), for: UIControlEvents.touchUpInside)
view.addSubview(btn)
return btn
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
You add the button here
view.addSubview(btn)
inside addnewbutton
which recursively searches for the parent view of the VC and it's not yet setted inside loadView so control calls it again and the problem happens to infinite loop , so comment that line and uncomment this
view.addSubview(k1) // which is inside loadView
BTW make the return of addnewbutton to UIButton directly instead of a cast

Create segue objects programmatically

I created a single view app with 2 view controllers. In the first view controller, I have a label and 2 buttons that were programmatically created. I have 2 segues from these buttons to the second view controller. I wish that each button carries different information to the second view controller. From creating these buttons and segues programmatically, I haven’t been able to assign the identifier to the segues. So, I can’t use performSegue(withIdentifier: sender:).
How can I do this?
First ViewController:
import UIKit
class ViewController: UIViewController {
var myLabel: UILabel!
var leftButton: UIButton!
var rightButton: UIButton!
// bellow are the 2 variable which I’d like to transport into the second ViewController
var leftButtonText = "I'm the left button."
var rightButtonText = "I'm the right button."
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let homeNavBar = UINavigationBar()
homeNavBar.frame = CGRect(x: 0, y: 0, width: 320, height: 45)
homeNavBar.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(homeNavBar)
let homeNavItem = UINavigationItem(title: "Home")
homeNavBar.setItems([homeNavItem], animated: false)
myLabel = UILabel()
myLabel.frame = CGRect(x: 165, y: 150, width: 200, height: 42)
myLabel.text = "Press one of the button bellow!"
self.view.addSubview(myLabel)
leftButton = UIButton(type: .custom)
leftButton.frame = CGRect(x: 80, y: 300, width: 70, height: 70)
leftButton.backgroundColor = UIColor.cyan
leftButton.setTitleColor(UIColor.black, for: .normal)
leftButton.setTitle("Left Button", for: .normal)
leftButton.layer.cornerRadius = 20
leftButton.layer.borderWidth = 1
leftButton.layer.masksToBounds = true
leftButton.addTarget(self, action: #selector(ViewController.leftButtonAction(_:)), for: .touchUpInside)
self.view.addSubview(leftButton)
rightButton = UIButton(type: .custom)
rightButton.frame = CGRect(x: 240, y: 300, width: 70, height: 70)
rightButton.backgroundColor = UIColor.cyan
rightButton.setTitleColor(UIColor.black, for: .normal)
rightButton.setTitle("Right button", for: .normal)
rightButton.layer.cornerRadius = 20
rightButton.layer.borderWidth = 1
rightButton.layer.masksToBounds = true
rightButton.addTarget(self, action: #selector(ViewController.rightButtonAction(_:)), for: .touchUpInside)
self.view.addSubview(rightButton)
let margins = self.view.layoutMarginsGuide
homeNavBar.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
homeNavBar.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
homeNavBar.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
myLabel.topAnchor.constraint(equalTo: homeNavBar.bottomAnchor).isActive = true
leftButton.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
leftButton.topAnchor.constraint(equalTo: myLabel.bottomAnchor).isActive = true
rightButton.topAnchor.constraint(equalTo: myLabel.bottomAnchor).isActive = true
rightButton.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
}
#objc func leftButtonAction (_ sender: UIButton) {
let segueSecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "idSecond")
self.show(segueSecondViewController, sender: nil)
print("I'm activated by the left button.")
}
#objc func rightButtonAction (_ sender: UIButton) {
let segueSecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "idSecond")
self.show(segueSecondViewController, sender: nil)
print("I'm activated by the right button.")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Second ViewController:
import UIKit
class SecondViewController: UIViewController {
var mySecondLabel: UILabel!
var mySecondLabelText = "I'm the second page."
var closeButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let secondNavBar = UINavigationBar()
secondNavBar.frame.size = CGSize(width: 320, height: 45)
secondNavBar.translatesAutoresizingMaskIntoConstraints = false
let secondNavItem = UINavigationItem(title: "Second page")
secondNavBar.setItems([secondNavItem], animated: false)
self.view.addSubview(secondNavBar)
mySecondLabel = UILabel()
mySecondLabel.frame = CGRect(x: 165, y: 200, width: 200, height: 42)
mySecondLabel.backgroundColor = UIColor.yellow
mySecondLabel.textColor = UIColor.black
mySecondLabel.text = "\(mySecondLabelText)"
mySecondLabel.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(mySecondLabel)
closeButton = UIButton(type: .custom)
closeButton.frame = CGRect(x: 10, y: 50, width: 50, height: 50)
closeButton.backgroundColor = UIColor.red
closeButton.setTitleColor(UIColor.black, for: .normal)
closeButton.setTitle("Close", for: .normal)
closeButton.layer.cornerRadius = 30
closeButton.layer.borderWidth = 1
closeButton.layer.masksToBounds = true
closeButton.addTarget(self, action: #selector(SecondViewController.closeButtonAction(_:)), for: .touchUpInside)
self.view.addSubview(closeButton)
let margins = self.view.layoutMarginsGuide
secondNavBar.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
secondNavBar.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
secondNavBar.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
closeButton.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
closeButton.topAnchor.constraint(equalTo: secondNavBar.bottomAnchor).isActive = true
mySecondLabel.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
mySecondLabel.topAnchor.constraint(equalTo: closeButton.bottomAnchor).isActive = true
mySecondLabel.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
}
#objc func closeButtonAction (_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
print("Second page closed.")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
You can do it by giving your View Controller an Identifier. This isn't a segue, but it will Instantiate your target VC:
let vc = UIStoryboard(name:"Main", bundle:nil).instantiateViewControllerWithIdentifier("identifier") as! SecondViewController
self.navigationController?.pushViewController(vc, animated:true)
You can set the VC Identifier on the Identity Inspector tab on the StoryBoard.
I just read in the documentation that you can't call the performSegue method if you don't have a segue with an identifier in the Storyboard, so WRT your requirement, you can't do it programmatically.
identifier The string that identifies the triggered segue. In
Interface Builder, you specify the segue’s identifier string in the
attributes inspector.

swift hiding label when a button is pressed

I have created my own label and my own button. Now when the page loads the label hides as I want but when i click the button it does not show up as it supposed to do, in fact it does not do anything. How can I fix this problem which is making label show when i press the button?
#IBOutlet var thumbsUpButtonaPressed : UIButton!
#IBOutlet weak var label : UILabel!
override func viewDidLoad() {
var label = UILabel(frame: CGRectMake(0, 0, 200, 21))
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = "00000"
self.view.addSubview(label)
label.hidden = true
let buttona = UIButton()
buttona.frame = CGRectMake(0.772 * view.bounds.width, 0.32 * view.bounds.height, 22, 22)
buttona.layer.cornerRadius = 0.04 * view.bounds.width
buttona.backgroundColor = UIColor.greenColor()
buttona.setImage(UIImage(named:"A.png"), forState: .Normal)
buttona.addTarget(self, action: "thumbsUpButtonaPressed", forControlEvents: .TouchUpInside)
view.addSubview(button)
func thumbsUpButtonaPressed(sender: UIButton!) {
label.hidden = false
}
}
I am using below code on swift 3
label.isHidden = true // hide
label.isHidden = false // show
you can use isHidden with other ui objects, see that answer also
Unless I am missing something in viewDidLoad you are creating a new label
var label = ...
you are not using the IBOutlet Property like
label = ...
Also are you sure your brackets are correct because it looks like your buttonPressed method is nested inside viewDidLoad.
Create an IBAction:
#IBAction func thumbsUpButtonaPressed(sender: UIButton) {
label.hidden = false
}
Then connect it with your button by cmd + drag on the button to the action:
Swift 5 Update
#IBAction func thumbsUpButtonaPressed(sender: UIButton) {
label.isHidden = false
}
You can also change:
label.alpha = 1.0 // show
label.alpha = 0.0 // hide
Try to correct your function with:
func thumbsUpButtonaPressed(sender: UIButton!) {
print("button was pressed")
label.hidden = false
label.setNeedDisplay()
}
Create normal IBAction for your button:
#IBAction func thumbsUpButtonaPressed(sender: UIButton!) {
label.hidden = false
}

Swift ERROR- [__NSCFData gotoShowChannel11] When i create button in Delegate and add view on tabbar

I am gating my problem in IOS 8 but my code working in IOS 9 . I have create one Transparent button and add subview in Tabbar method. The Problem is button event not working when tabar load second time and this is problem in IOS 8 , but its working good in ISO 9. Here is my code
Delegate
var button_ofTabbar = UIButton();
//var button_ofTabbar:UIButton!;
//UIButton();= UIButton(type: UIButtonType.System)
In Tabbar
class tabbar: UITabBarController,UITabBarControllerDelegate {
//let button_ofTabbar = UIButton();
var delegate1: AppDelegate!
let aDataBase : databaseinit = databaseinit()
override func viewDidLoad() {
super.viewDidLoad()
UITabBar.appearance().tintColor = UIColor(red: 242/255.0, green: 134/255.0, blue: 55/255.0, alpha: 1.0)
self.delegate=self;
delegate1 = UIApplication.sharedApplication().delegate as! AppDelegate
UITabBar.appearance().barTintColor = UIColor.whiteColor()
if(delegate1.tag_jive_channel_tab == 0)
{
// delegate1.button_ofTabbar.removeFromSuperview();
// delegate1.button_ofTabbar.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
delegate1.button_ofTabbar.hidden = false;
let widthofbtn:CGFloat = self.tabBar.frame.size.width/5;
delegate1.button_ofTabbar.frame = CGRectMake(0, self.tabBar.frame.origin.y, widthofbtn, self.tabBar.frame.size.height)
delegate1.button_ofTabbar.backgroundColor = UIColor.redColor()//clearColor()
//delegate1.button_ofTabbar = UIButton(type: UIButtonType.System)
delegate1.button_ofTabbar.tintColor = UIColor.redColor()//clearColor()
delegate1.button_ofTabbar.addTarget(self, action: "gotoShowChannel11", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(delegate1.button_ofTabbar);
}
}
override func viewDidAppear(animated: Bool) {
}
func gotoShowChannel11() {
delegate1.button_ofTabbar.hidden = true;
//orangeColor tabbar
//self.tabBarController?.tabBar.tintColor = UIColor.redColor();
delegate1.tag_jive_channel_tab = 1;
NSNotificationCenter.defaultCenter().postNotificationName("update_tabbar", object: nil,
userInfo: nil);
//UIColor(red: 146/255.0, green: 146/255.0, blue: 146/255.0, alpha: 1.0)
}
When i use this line delegate1.button_ofTabbar = UIButton(type: UIButtonType.System) then my button is not show custom/System in both
i am also try this func gotoShowChannel11(sender: UIButton!)
Please help me . i am stuck in IOS 8 Problem . and Error is
ERROR- [__NSCFData gotoShowChannel11]
Please any one Help me .
Now I have found another solution . Thankyou .