UIButton property observers didset never called - ios

I have a simple button in a cocoapods library, I need to change the tintcolor when it is isHighlighted however isHighlighted gets called but didset or willset never get called.
I am ofcourse setting my button to be highlighted, and I call this function after I dequeue my tableview cell
func setupCell() {
let myCustomButton = UIButton.button(title: "Button")
myCustomButton.isHighlighted = true
}
My UIButton Extension
extension UIButton {
public static func button(title: String) -> UIButton {
let button = UIButton(type: .custom)
button.setTitle(title, for: .normal)
button.setTitleColor(UIColor.gray, for: .normal)
return button
}
override open var isHighlighted: Bool {
didSet {
print("Never gets here, ever!")
}
}
}
How can I trigger didSet? Is there any other way apart from setting isHighlighted to true?

Related

Custom anonymous closure navigation back button inside of UiView()

I have a question, how is it possible to implement the creation of a custom back navigation button inside an UIView(). I have a main controller which contains a collectionView, clicking on any cell goes to a second controller which contains a tableView. I created a separate custom view inside the tableView headers where I added labels, pictures, buttons. I need when clicking a backButton inside a custom view, it will go to the main controller. How can be implemented? I making app only programmatically - (No Storyboard)
CustomView.swift
lazy var backButton: UIButton = {
let button = UIButton(type: .system)
let image = UIImage(systemName: "chevron.left")
button.setImage(image, for: UIControl.State())
button.tintColor = .white
button.isHidden = true
button.addTarget(self, action: #selector(goToBack), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
#objc func goToBack() {
}
First add a callback function in the CustomView. Then call this callback closure from goToBack() method.
class CustomView: UIView {
var backButtonTapped: (() -> Void)?
lazy var backButton: UIButton = {
let button = UIButton(type: .system)
let image = UIImage(systemName: "chevron.left")
button.setImage(image, for: UIControl.State())
button.tintColor = .white
button.isHidden = true
button.addTarget(self, action: #selector(goToBack), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
#objc func goToBack() {
backButtonTapped?()
}
}
In UIViewController where you initialise this CustomView, give the action of the closure.
let view = CustomView()
view.backButtonTapped = { [weak self] in
self?.navigationController?.popViewController(animated: true)
}
You will need to create a delegate for this. In your CustomView make a property weak var delegate: ButtonDelegate
protocol ButtonDelegate: class {
func onTap()
}
And your ViewController holding the CustomView has do implement that protocol and do navigationController.popViewController() in the implemented onTap() method.
Call delegate?.onTap() in your CustomView goToBack() method.

swift cannot add target to UIButton

so this question is super simple, but i checked that like a 100 times but it still won't work.
Basically, when user taps on tableView cell, it open another VC with different views, depending whether or not user is owner of post.
First condition, works just fine, adding target to button, while when second is being executed, nothing happens
lazy var buttonsView = DetailButtonsView() // those are almost the same
lazy var addvertView = AdvertiseView()
// inside of buttonsView()
lazy var skipButton: UIButton = {
let button = UIButton()
button.setTitle("Пожаловаться", for: .normal)
button.setTitleColor(.mainColor, for: .normal)
button.titleLabel?.font = .getPoppinsMediumFont(on: 15)
return button
}()
override init(frame: CGRect) {
super.init(frame: .zero)
setupView() //set up constraints
}
//inside of AdvertiseView()
lazy var blackButton:UIButton = {
var button = UIButton()
button.layer.cornerRadius = 8
button.backgroundColor = .black
return button
}()
override init(frame: CGRect) {
super.init(frame: .zero)
setupView() //set up constraints
}
//
func setUpBottom() -> Void {
if dataInfo!.user_id! == UserSettings.userModel.id
{
self.backView.addSubview(addvertView) //also works
addvertView.snp.makeConstraints //works
{
(make) in
make.left.equalToSuperview()
make.top.equalTo(userView.snp.bottom).offset(24)
make.height.equalTo(450)
make.bottom.lessThanOrEqualTo(-34)
}
addvertView.blackButton.addTarget(self, action: #selector(blackButtonMethod), for: .touchUpInside) // does not add target
}
else {
backView.addSubview(buttonsView) //works
buttonsView.snp.makeConstraints { (make) in
make.left.right.equalToSuperview()
make.top.equalTo(userView.snp.bottom).offset(24)
make.bottom.lessThanOrEqualTo(-34)
}
buttonsView.skipButton.addTarget(self, action: #selector(toComplain), for: .touchUpInside) //works
}
#objc func toComplain(){ //works
let vc = ComplaintTypeViewController()
vc.advertID = dataInfo!.id!
navigationController?.pushViewController(vc, animated: true)
}
#objc func blackButtonMethod(){ //does not work
print("hello")
parameters["action"] = "hot"
parameters["advert_id"] = String(describing: dataInfo!.id)
updateAdvert(parameters: parameters)
}
The target is probably added, but you cannot interact with it. That usually happens when constraints/frame is not set right. I see that the skip button uses:
button.setTitle("Пожаловаться", for: .normal)
which will infer autolayout width/height.
I don't see black blackButton's autolayout constraints or label set anywhere.

Disable editing of UITextField Without disabling subviews [duplicate]

This question already has answers here:
Easy way to disable a UITextField?
(5 answers)
Closed 5 years ago.
I have UITextField and I put a UIButton in the left view of it. I want to disable editing of UITextField while my UIButton response to on click action. I tried textField.isUserInteractionEnabled and also textField.isEnabled but both of them also disable my UIButton. is there any way to do this? my custom UITextField class is like this
import UIKit
#IBDesignable
class UITextFieldWithButton: UITextField, UITextFieldDelegate {
private var happyButton: UIButton = UIButton(type: .system)
#IBInspectable
var buttonText: String {
get {
let string = happyButton.titleLabel!.text!
let start = string.index(string.startIndex, offsetBy: 2)
let end = string.endIndex
return String(happyButton.titleLabel!.text![start..<end])
}
set {
happyButton.setTitle(" " + newValue, for: .normal)
happyButton.sizeToFit()
self.leftView = happyButton
self.leftViewMode = .always
}
}
var isButtonEnable: Bool {
get {
return self.isButtonEnable
}
set {
happyButton.isEnabled = newValue
}
}
var buttonDelegate: UITextFieldWithButtonDelegate?
required override init(frame: CGRect) {
super.init(frame: frame)
delegate = self
happyButton.addTarget(self,action: #selector(pressButton(_:)), for: .touchUpInside)
happyButton.titleLabel?.font = UIFont(name: (font?.fontName)!, size: (font?.pointSize)!)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
delegate = self
happyButton.addTarget(self,action: #selector(pressButton(_:)), for: .touchUpInside)
happyButton.titleLabel?.font = UIFont(name: (font?.fontName)!, size: (font?.pointSize)!)
}
#objc private func pressButton(_ sender: UIButton){
if let click = buttonDelegate {
click.clickOnUITextFieldButton(self)
}
}
}
protocol UITextFieldWithButtonDelegate {
func clickOnUITextFieldButton(_ sender: UITextFieldWithButton)
}
"I tried textField.isUserInteractionEnabled and also textField.isEnabled but both of them also disable my UIButton" :your code is working fine you might have added button behind uitextfield try to move it forward in view hierarchy

isHighlighted called multiple times on UIButton

I have subclassed UIButton and want to call a delegate method just once when the button goes into the highlighted state and call it again just once when it goes into the unhighlighted state:
override var isHighlighted: Bool {
didSet {
if isHighlighted {
delegate?.buttonHighlightStateDidChange(highlighted: true)
} else {
delegate?.buttonHighlightStateDidChange(highlighted: false)
}
}
}
However when I touch down on the button it seems that didSet is getting repeatedly called. What am I doing wrong here? How can I call the delegate method just once?
I would recommend against using your subclass in this way. UIControl has a builtin mechanism for getting callbacks in response to control events:
func registerActions(for button: UIButton) {
button.addTarget(self, action: #selector(MyClass.buttonIsHighlighted(sender:)), for: .touchDown)
button.addTarget(self, action: #selector(MyClass.buttonIsUnHighlighted(sender:)), for: .touchUpInside)
button.addTarget(self, action: #selector(MyClass.buttonIsUnHighlighted(sender:)), for: .touchUpOutside)
}
func buttonIsHighlighted(sender: UIButton) {
// highlighted
}
func buttonIsUnHighlighted(sender: UIButton) {
// unhighlighted
}

how to create single selection check box in swift2?

import UIKit
class CheckBox: UIButton {
// Images
let checkedImage = UIImage(named: "check-sign.png")! as UIImage
let uncheckedImage = UIImage(named: "blank-square.png")! as UIImage
// Bool property
var isChecked: Bool = false {
didSet{
if isChecked == true {
self.setImage(checkedImage, forState: .Normal)
} else {
self.setImage(uncheckedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
self.isChecked = false
}
func buttonClicked(sender: UIButton) {
if sender == self {
isChecked = !isChecked
}
}
}
I was trying to implement checkboxes in Swift 2. I was referring to How to create radio buttons and checkbox in swift (iOS)?.
But my requirement is I want to implement single selection checkbox. I am not sure how to group the buttons via IB to make it single selectable.
Any suggestion?
Currently it is multiple selectable, I want to make it single selectable.
You can do it with UITableView and custom cells ,and change tableView.allowsMultipleSelection = flase.
Ex : You can do that by setting the accessoryType on the selected UITableViewCell instances to UITableViewCelAccessoryCheckmark.
To deselect the row, set it back to UITableViewCellAccessoryNone.

Resources