I created a button in a supplementary collectionView cell as header and added a button with a target to it but it doesn't trigger the function when tapped. What am I doing wrong?
Below is the button I created and its target function in the cell class.
let dummyButton :UIButton = {
let button = UIButton(type: .system)
button.setTitle("Dummy", for: .normal)
button.layer.cornerRadius = 3
button.layer.borderWidth = 1
button.titleLabel?.font = UIFont.systemFont(ofSize: 12)
button.tintColor = UIColor.brown
button.addTarget(self, action: #selector(handleTrash), for: .touchUpInside)
return button
}()
#objc func handleTrash (){
print("It worked this time around so what was going on?")
}
I wrote all these in the collectionView Cell subclass. Please help
I found the solution. I had to declare the buttons as Lazy variables.
Add the sender
button.addTarget(self, action: #selector(handleTrash(_:)), for: .touchUpInside)
#objc func handleTrash (_ sender: UIButton){
print("It worked this time around so what was going on?")
}
Related
When I run this code by #selector(didTapRegister) I get a didTapRegister is not in scope. I have a bigger application I am using it in and on one page it works and another it won't, well it won't work anywhere else.
I am stuck on figuring out why. Can anyone help solve it? seems to be an Objective-C issue possibly because I have same issues trying to make IBOutlets, I have tried searching for answers and I just don't have enough knowledge to understand why it isn't working, I've tried moving the code to different scopes and still nothing. with the IBOutlets it's saying IBOutlet property cannot have non-object type UIButton?.Type
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let Button = UIButton.init(type: .custom)
Button.setTitle("Chat", for: .normal)
Button.layer.backgroundColor = CGColor.init(gray: 0.0, alpha: 0.0)
Button.setTitleColor(.white, for: .normal)
Button.setTitleColor(.red, for: .highlighted)
Button.layer.borderWidth = 1
Button.layer.cornerRadius = 5
Button.layer.borderColor = UIColor.white.cgColor
Button.isHighlighted = false
Button.showsTouchWhenHighlighted = true
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: Button)
Button.addTarget(self, action: #selector(didTapRegister), for: .touchUpInside)
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Do any additional setup after loading the view.
}
}
}
Maybe try what he said but
Just use SwiftUI it is much better
#objc and all of that is fine but in SwiftUI you can just right click and add buttons
There 2 mistakes in the code.
You have to create #objc function for the button action
In your code move viewWillAppear method outside the viewDidLoad
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.init(type: .custom)
button.setTitle("Chat", for: .normal)
button.setTitleColor(.white, for: .normal)
button.setTitleColor(.red, for: .highlighted)
button.layer.borderWidth = 1
button.layer.cornerRadius = 5
button.layer.borderColor = UIColor.white.cgColor
button.isHighlighted = false
button.showsTouchWhenHighlighted = true
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
button.addTarget(self, action: #selector(didTapRegister), for: .touchUpInside)
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
}
#objc func didTapRegister(_ sender: UIButton) {
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Do any additional setup after loading the view.
}
}
Note: button name start with lowercase.
I am trying create an app about social network. In there users can send two different type post (like image post or text post). Users selecting of their post type in another controller and create their post. I Created two different cell and want to call in cellForItemAt with if statement. The problem is how can I know users selection about post type ?
// there is users post type selection with button
let writeButton: UIButton = {
let wButton = UIButton()
wButton.layer.cornerRadius = 7
wButton.setBackgroundImage(#imageLiteral(resourceName: "writing"), for: .normal)
wButton.setTitle("Writing", for: .normal)
wButton.setTitleColor(UIColor.white, for: .normal)
wButton.titleLabel?.font = UIFont(name: "AvenirNext-DemiBoldItalic", size: 18)
wButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
wButton.layer.borderWidth = 1.5
wButton.addTarget(self, action: #selector(tappedWriteButton), for: .touchUpInside)
return wButton
}()
#objc func tappedWriteButton () {
let writePost = WriteTitlePost()
navigationController?.pushViewController(writePost, animated: true)
}
let mediaButton: UIButton = {
let mButton = UIButton()
mButton.layer.cornerRadius = 7
mButton.backgroundColor = UIColor.orange
mButton.setBackgroundImage(#imageLiteral(resourceName: "photography"), for: .normal)
mButton.setTitle("Media Post", for: .normal)
mButton.setTitleColor(UIColor.white, for: .normal)
mButton.titleLabel?.font = UIFont(name: "AvenirNext-DemiBoldItalic", size: 18)
mButton.layer.borderWidth = 1.5
mButton.layer.borderColor = UIColor.orange.cgColor
mButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
mButton.addTarget(self, action: #selector(tappedMediaButton), for: .touchUpInside)
return mButton
}()
#objc func tappedMediaButton() {
let layout = UICollectionViewFlowLayout()
let mediaPost = MediaPost(collectionViewLayout: layout)
let navController = UINavigationController(rootViewController: mediaPost)
present(navController, animated: true, completion: nil)
}
I am trying to disable my post button if the user has not selected a picture to post, so far, I've only managed to disable it if the textfields have not been edited. I also have two buttons, button one: lost, button two: found. The user needs to tap one or the other as well. Is it possible to also disable the post button if neither of these two buttons have been tapped?
Here's my code so far!
func handleBlancInformation(){
address.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
breed.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
phone.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
guard let address = address.text, !address.isEmpty, let breed = breed.text, !breed.isEmpty, let phone = phone.text, !phone.isEmpty
else {
postButton.setTitleColor(UIColor.lightText, for: UIControlState.normal)
postButton.isEnabled = false
return
}
postButton.setTitleColor(UIColor.white, for: UIControlState.normal)
postButton.isEnabled = true
}
func handleBlancInformation(){
address.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: .valueChanged)
breed.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: .valueChanged)
phone.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: .valueChanged)
}
try this code i have changed addTarget event so it will work :)
How can I make a UIButton change image from A to B and again B to A, every time it's pressed?
Not as .normal to .highlighted, but permanent.
I've tried the .highlighted method because I can't find the code for permanent, here's my code:
func ChangeButton() {
Button.setImage(A, for: .normal)
Button.setImage(B, for: .highlighted)
Thanks for mentions of setBackgroundImage to Xavier L. from the other answer.
Try the following code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var button: UIButton!
var buttonActive = false
override func viewDidLoad() {
super.viewDidLoad()
button.setBackgroundImage(UIImage(named: "apple"), for: .normal)
}
#IBAction func buttonPressed() {
if buttonActive {
button.setBackgroundImage(UIImage(named: "apple"), for: .normal)
} else {
button.setBackgroundImage(UIImage(named: "pineapple"), for: .normal)
}
buttonActive = !buttonActive
}
}
And your storyboard should look like that:
N.B. On Stack Overflow you should perform some actions before asking. Try to include some code you tried.
I recommend changing the backgroundImage because it's scaled automatically, and the button text in front won't get covered.
If it's a custom button, within its initializer:
self.addTarget(self, action: #selector(*yourfunctoswitchimages*), for: .touchUpInside)
... and then that yourfunctoswitchimages can just check what the current background image is, and switch it accordingly.
If it's not a custom button, add a target to it in viewDidLoad or something. Here's a lot of sample code.
In your viewDidLoad()
yourButt.addTarget(self, action: #selector(switcheroo), for: .touchUpInside)
Another func in your view controller:
func switcheroo()
{
if yourButt.currentBackgroundImage == image1
{
yourButt.setBackgroundImage(image2), for: .normal)
}
else { // ...set image to image1 }
}
yourButt would be a property of your view controller of course, that way it's accessible to the viewDidLoad() and to other funcs within it.
let playButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "VideoIcon.png") as UIImage?
button.backgroundImage(for: .normal)
button.addTarget(self, action: #selector(pressBackButton(button:)), for: .touchUpInside)
button.setImage(image, for: .normal)
return button
}()
func pressBackButton(button: UIButton) {
print("test")
if let playVideoButtonURL = post?.videourl {
let player = AVPlayer(url: playVideoButtonURL as URL)
let playerLayer = AVPlayerLayer(player:player)
playerLayer.frame = CGRect(x: 100, y: 200, width: 100, height: 100)
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
self.layer.addSublayer(playerLayer)
player.play()
}
}
even if the video code is wrong it should still print test but it doesn't which is strange. I feel like something may be wrong with the selector but i currently have no idea what could be wrong with it.
access function or property in self outside of initializer.
class TestViewController: UIViewController {
let playButton: UIButton = {
let button = UIButton()
let image = UIImage(named: "VideoIcon.png") as UIImage?
button.backgroundImage(for: .normal)
button.setImage(image, for: .normal)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(pressBackButton(button:)), for: .touchUpInside)
}
}
Instead of doing:
let playButton: UIButton = {
...
...
return button
}()
which won't work (because you're attempting to create playButton at the wrong time -- which is before the view is loaded or before it's about to appear)
In your viewDidLoad or viewWillAppear, create the button, define the target and simply add it as a subview.
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
if let image = UIImage(named: "VideoIcon.png") as UIImage?
{
button.backgroundImage(for: .normal)
button.addTarget(self, action: #selector(pressBackButton(button:)), for: .touchUpInside)
button.setImage(image, for: .normal)
}
self.addSubview(button)
}
Adding the button as a subview increments the retain count (i.e. it won't go away), but if you want to keep it around as a property simply declare it as:
var playButton : UIButton?
and then set playButton = button at the end of viewDidLoad.