Set Title to UIBarButtonItem - ios

I have UIBarButtonItem and whenever I try to set title to the button, its not working.
#IBOutlet weak var barButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
barButton.title = "AB"
}
But if I try to create Action of UIBarButtonItem and then do sender.setTitle() then it works. But not at viewDidLoad. I don't want to set title when user taps on the button.

Change title or image and then resign it back to navigationItem:
class AnotherViewController: UIViewController {
#IBOutlet weak var myBarButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let barButton = myBarButton
barButton?.title = "Anther Title"
navigationItem.rightBarButtonItem = barButton
}
}
Apple document: https://developer.apple.com/reference/uikit/uibaritem/1616412-title
You should set this property before adding the item to a bar. The default value is nil.

If you already have an IBOutlet for the barButton, why not just set the title in the storyboard? I think this is the easiest way unless you have some other reason for doing it programmatically.

When I try this, it works. Maybe there is a bug with Xcode, delete your button and connections then try again.
class ViewController: UIViewController {
#IBOutlet weak var barButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
barButton.title = "MyButton"
}

Try this instead
#IBOutlet weak var barButton: UIBarButtonItem! {
didSet {
barButton.title = "AB"
}
}

Related

Why button changes after the click?

I want to set a custom font to UIButton. I need to set it programmatically because the font is not applied otherwise. The problem is that it changes back to the built-in font after the click. What am I doing wrong?
import UIKit
class LoginViewController: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var eyeButton: UIButton!
#IBOutlet weak var loginButton: UIButton!
var iconClick = true
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
loginButton.titleLabel?.font = UIFont(name: "Capitana-Bold", size: CGFloat(16))
}
#IBAction func iconAction(sender: AnyObject) {
if (iconClick == true) {
passwordTextField.isSecureTextEntry = false
eyeButton.setImage(UIImage(named: "eye-closed"), for: .normal)
} else {
passwordTextField.isSecureTextEntry = true
eyeButton.setImage(UIImage(named: "eye-open"), for: .normal)
}
iconClick = !iconClick
}
#IBAction func onLoginClicked(_ sender: Any) {
}
}
In iOS 15 you need to use configuration for button. This should work:
loginButton.configuration?.attributedTitle?.font = UIFont(name: "Capitana-Bold", size: CGFloat(16))
This is an iOS 15 Filled button. You cannot configure it by saying
loginButton.titleLabel?.font = ...
That was possible (but wrong) in iOS 14 and before, but with an iOS 15 button it is impossible. To configure a Filled button programmatically, you must set its configuration object.
https://developer.apple.com/documentation/uikit/uibutton/configuration
In particular you want to set the button configuration attributed title.
https://developer.apple.com/documentation/uikit/uibutton/configuration/3750779-attributedtitle

Place references to IBOutlet and IBAction inside viewDidLoad or just before?

I understand that viewDidLoad is where you are supposed to put any set up code in relation to buttons, color, and other view related code. However, in a code sample I have just seen, a reference to IBOutlet and to IBAction are not written inside of viewDidLoad but rather, just before this method, as below. Are these not set up related code, as in creating a label and a method to manipulate it?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
#IBAction func showName(sender: AnyObject) {
nameLabel.text = "my name is Cyril"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
ViewDidLoad is only one method of setup. You can put some code here, local variables, ets. #IBOutlet and #IBAction are links of Interface Builder and nameLabel. And this outlet and action suppose to be global, so you could use them in other functions, not only in viewDidLoad.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
nameLabel.text = "my name is Cyril"
}
}

Change image color with tapGesture on different viewController

I am trying to get the UIImageView wCircle to change to red when the UIImageView on a different viewController rDot is tapped. The problem is, when I tap rDot I get the error Thread 1: EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP subcode = 0x0) I made wCircle a global variable so it could be reached in the other viewController.
First viewController
weak var wCircle: UIImageView!
class SecondViewController: UIViewController {
#IBOutlet weak var wCircle: UIImageView!
}
Second viewController
class ProgressViewController: UIViewController {
#IBOutlet weak var rDot: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
rDot.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(rdotimageTapped(tapGestureRecognizer:)))
rDot.addGestureRecognizer(tapGestureRecognizer)
}
func rdotimageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
wCircle.image = wCircle.image!.withRenderingMode(.alwaysTemplate) //error on this line
wCircle.tintColor = UIColor.red
}
}
you code is not organized and indicate nothing Any way
change this line of code
replace weak var wCircle: UIImageView!
with
weak var wCircle = UIImageView()
and this
func rdotimageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
wCircle?.image = whiteDot.image!.withRenderingMode(.alwaysTemplate) //error on this line
wCircle?.tintColor = UIColor.red
}
wCircle is weak variable and it is optional value.So when you are calling it from other class it can't be optional. Also make it strong variable

Linking text views to scroll together

I have two side by side text views. How can I link them so that if one is scrolled down other automatically scrolls the same as first one in swift 2.
Set your viewController conforms to UITextViewDelegate,then set textView delegate to self,then in scrollViewDidScroll sync both contentOffSet
For example
Gif
Code
class ViewController: UIViewController,UITextViewDelegate {
#IBOutlet weak var textview2: UITextView!
#IBOutlet weak var textview1: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textview1.delegate = self
textview2.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView == textview1{
textview2.contentOffset = textview1.contentOffset
}else{
textview1.contentOffset = textview2.contentOffset
}
}
}

Array of UIButtons or method UIButton(named: "\(string)")

Is it possible to make an array of UIButtons?
let buttonArray: [UIButton] = [UIButton(Button1)!, UIButton(Button2)!, UIButton(Button3)!]
To reference later as
buttonArray[0].setImage(UIImage, forState: UIControlState.Normal)
Or somehow set a
var button = UIButton.whoseName = "Specific String"
button.setImage(UIImage, forState: UIControlState.Normal)
VC1:
import UIKit
class VC1: UIViewController {
#IBOutlet weak var Card1: UIButton!
#IBOutlet weak var Card2: UIButton!
#IBOutlet weak var Card3: UIButton!
let Cards: [UIImage] = [UIImage(named: "Default")!, UIImage(named: "2s")!,UIImage(named: "2h")!,UIImage(named: "2c")!,UIImage(named: "2d")!,]
// var CardCaller: Array<UIButton> = [Card1, Card2, Card3]
let CardCallers: [UIButton] = [Card1, Card2, Card3] //ERROR: 'VC1.Type' does not have a member named 'Card1'
var caller = ""
var Index2 = Int()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let KVC = segue.destinationViewController as VC2
KVC.source = segue.identifier!
}
#IBAction func unwind(unwindSegue: UIStoryboardSegue){
//Card1.setImage(Cards[Index2], forState: UIControlState.Normal)
//let button = UIButton(named: "Card1")!
if caller == "Card1" {Card1.setImage(Cards[Index2], forState: UIControlState.Normal)} else if caller == "Card2" {Card2.setImage(Cards[Index2], forState: UIControlState.Normal)} else if caller == "Card3" {Card3.setImage(Cards[Index2], forState: UIControlState.Normal)}
}
#IBAction func text(sender: AnyObject) {
println(caller)
println(Index2)
}
}
The IBOutlets are wired properly to Storyboard buttons; I created them with control/drag to the view controller.
This shouldn't be a problem, but it may have something to do with when you're accessing the buttons. Try creating the array globally and adding the buttons to it once they've loaded:
class VC1: UIViewController {
#IBOutlet weak var Card1: UIButton!
#IBOutlet weak var Card2: UIButton!
#IBOutlet weak var Card3: UIButton!
var CardCallers: [UIButton] = [UIButton]() // Empty UIButton array
override func viewDidLoad() {
self.CardCallers = [self.Card1, self.Card2, self.Card3] // Buttons have now loaded in the view
}
}
You can.
Two ways to do it:
var buttonsArray: Array<UIButton> = [button1, button2]
Or
#IBOutlet var buttonsArray: Array<UIButton> = []
For the later one, it can be filled from the storyboard as an IBOutletCollection
Please note that views can be assigned to an IBOutlet and an IBOutletCollection at the same time.

Resources