Setting the background of an UIButton programmatically not working - ios

I'm just trying to simply set the background image of the button, but whatever I try it is doing nothing. I also put a UIImageView there to see if there's any issue with the image file, but the image view is set perfectly fine. Do I have to set something in the properties of the button?
Here the code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imageToSet = UIImage(named: "3-1")
b1.setBackgroundImage(imageToSet, for: .normal)
imageView.image = imageToSet
}
#IBOutlet weak var b1: UIButton!
#IBOutlet weak var imageView: UIImageView!
}
These are my setting for the button:

In Xcode 13 ,UIButton has four type are Plain,Grain,Tinted,Filled .When you create a button in storyboard , button type automatically set with Plain that means new UIButton configurations is on (If you set one of them 4).So when you try to use old behaviours like
setBackgroundImage(..)
setImage(..)
This functions not gonna effect on this button. So If you want to use old behaviours you need to set style Plain to Default

Related

Using UIColorPickerViewController to change the color of cell background color always returns black

I'm developing an app for my school that helps students better understand their grades by getting an analysis on their portfolio of assignments for each class. Right now I am at the point of letting the user create the classes they are in and customize the information within it that is displayed in a tableview with custom cells. The user gives the majority of the information in a child view where they input information such as class name, teacher, grade weighting, etc. I wanted to give the user the ability to change the color of the cell once they are viewing the TableView with all the cells - classes - they made. I decided to go about this by having the cells have a UIButton that they can click on for their determined cell to then pull up a UIColorPickerViewController.
What I wanted to happen was...
User taps button in cell
UIPickerViewController is pulled up
User selects their desired color
User exits UIPickerViewController
Cell is changed to the color
What is actually happening is this
User taps button in cell
Cell background becomes black right as UIPickerViewController is presented
User selects their desired color
User exits UIPickerViewController
Cell remains black
I used a delegate to send the information from the cells and then I used the "colorPickerViewControllerDidFinish()" function and it's still not working out. When I did some debugging I found that the value of the UIColorPickerViewController is actually being stored in the variable I am using, but only after I have already assigned it's value to the cell background so I'm unsure what to do. As you can probably tell, I'm new to swift so apologies for any stupid mistakes in my code.
Custom Cell File
// Protocol for VC's to conform to so they can distinguish which cell has a button being tapped
protocol newlyCreatedCellDelegate: AnyObject
{
func didTapButton(title: String, cellView: UIView)
}
class newlyCreatedClass: UITableViewCell {
// Telling the delegate what to do once they are assigned
weak var delegate: newlyCreatedCellDelegate?
#IBOutlet weak var classContentView: UIView!
#IBOutlet weak var classUIView: UIView!
#IBOutlet weak var classNameLabel: UILabel!
#IBOutlet weak var classTeacherNameLabel: UILabel!
#IBOutlet weak var pointType1NameLabel: UILabel!
#IBOutlet weak var pointType2NameLabel: UILabel!
#IBOutlet weak var pointType3NameLabel: UILabel!
#IBOutlet weak var percent1Label: UILabel!
#IBOutlet weak var percent2Label: UILabel!
#IBOutlet weak var percent3Label: UILabel!
#IBOutlet weak var colorButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
colorButton.layer.cornerRadius = 21
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
// Essentially creating the prep list for the delegate. If they are called - whoever it is - they will go through this 'checklist'
#IBAction func colorButtonTapped(_ sender: Any)
{
delegate?.didTapButton(title: classNameLabel.text!, cellView: classUIView)
}
}
ViewController Extensions
extension ClassSelection: newlyCreatedCellDelegate
{
func didTapButton(title: String, cellView: UIView)
{
let colorPickerVC = UIColorPickerViewController()
colorPickerVC.delegate = self
present(colorPickerVC, animated: true, completion: nil)
colorPickerViewControllerDidFinish(colorPickerVC)
// 'cellBackgroundColor' is a variable declared in the VC to transfer the UIColor value
cellView.backgroundColor = cellBackgroundColor
}
}
extension ClassSelection: UIColorPickerViewControllerDelegate
{
func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
cellBackgroundColor = viewController.selectedColor
}
}
You should implement one more UIColorPickerViewControllerDelegate method:
func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
cellBackgroundColor = viewController.selectedColor
}
It's a great start! As a really direct answer to your original question:
The reason for your problem is that in your didTapButton function you are presenting the color picker, but then immediately telling the app that the user is done with the picker, and then immediately setting the background color to cellBackgroundColor, which I assume has a default value of UIColor.black.
Instead you should delete those last 2 lines in your didTapButton function - just initialize the picker, set the delegate, and present the picker. Then the delegate method you chose - colorPickerViewControllerDidFinish isn't really the correct one for your purpose. Instead consider using the didSelect delegate method (see docs). When that method is called it will pass you the color the user selected, which you can simply use to set your background color and refresh your tableView cell if needed.
Since you mention you are a new Swift dev I will also mention that UITableView reuses its cells, so simply setting the background color of a cell once will not have the result you are expecting. You will see that as you scroll the cells up and down the colors will change in the various cells, so ultimately you'll need to store the color selections in another way so that each time a cell is being dequeued you can set the correct color based on user input. That part is outside of the scope of the original question, but just letting you know.

UIButton text content keeps resetting every second update

I am trying to update a button with a test value and I have noticed that every second update the button title text shows the test value for a fraction of a second but then resets to the Button's default value.
It seems to be a bug, but I wanted to see if there is a simpler explanation.
I have tried waiting up to 10 seconds before pushing the button but this seems to be consistently occurring.
Any ideas how to make UIButton function as expected?
import UIKit
class ViewController: UIViewController {
var testEntry = "its working"
#IBOutlet weak var testButton: UIButton!
#IBOutlet weak var testLabel: UILabel!
#IBAction func runTest(sender:
UIButton) {
// The button value should equal the value of the label value, but every 2nd button press of the test button results in the title of the button value resetting to the default value
dispatch_async(dispatch_get_main_queue()) {
self.testLabel.text = "\(self.testEntry)"
self.testButton.titleLabel?.text = "\(self.testEntry)"
}
}
Here is the github project.
You shouldn't be directly setting the text of the button title label, you should only set the font directly onto the label. The text should be set by calling
func setTitle(_ title: String?, forState state: UIControlState)
The text toggles because you're selecting and de-selecting the button, which is switching between some of its states which have different titles.
You should set the button title text by using the following method...
self.testButton.setTitle(self.testEntry, forState: .Normal)
instead of titleLabel property.
Swift 5
self.testButton.setTitle("hello", for: .normal)

How do I change the background color of a button within a custom UITableViewCell programatically in Swift?

I have a custom UITableViewCell and one of its subviews is a button (with the title "RSVP"):
It is connected to the following code:
class SelectedEventsTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet weak var attendanceLabel: UILabel!
#IBOutlet weak var attendanceButton: UIButton!
}
I am trying to change the background color of the button by adding this code to the SelectedEventsTableViewCell class:
override func awakeFromNib() {
super.awakeFromNib()
attendanceButton.backgroundColor = UIColor.greenColor()
}
However, it doesn't work. The button gets a white background:
Does anybody know why this is happening? It also doesn't work when I set the button's background color programmatically when the button is pressed.
Your help is appreciated.
Check somewhere you set the button background color white.
attendanceButton.backgroundColor = UIColor.whiteColor()
Check where you use SelectedEventsTableViewCell's object in TableView's data source or delegate methods in viewController.
ex.
cell.attendanceButton.backgroundColor = UIColor.whiteColor()
There are several possible reasons.
1.Did you make that outlet accessible? If not, CTRL-DRAG from storyboard.
2.Did you change that after awakeFromNib()? Maybe you set it again in cellForIndexPath(table view data source).
3.Cell was reused but awake once. It means you should recover its state after reuse. prepareForReuse() is designed for this.
I know this issue is old, but I ran into the same thing on iOS 15. The solution is to use the new UIButton.Configuration struct.
if #available(iOS 15.0, *) {
var config = UIButton.Configuration.filled()
config.baseBackgroundColor = UIColor.greenColor()
attendanceButton.configuration = config
} else {
attendanceButton.backgroundColor = UIColor.greenColor()
}
Run something like that in your prepareForReuse function or after you dequeue the cell and it should start working again. There are a lot more customisation options in iOS 15 using that configuration struct so have a dig into it for configuring all other aspects of your buttons.

How can I make a UIImage View clickable to segue to another view controller

I'm new in programming and I'm stuck with this little problem. I created a table view with several items, that passes data to a label and an image view through a segue. It all works fine, but now I want to make the image clickable, in order to segue to another view controller to show this image expanded. How can I do that?
class ViewController: UIViewController {
#IBOutlet var titleLabel: UILabel!
#IBOutlet var descLabel: UILabel!
#IBOutlet var imageView: UIImageView!
var titleName: String?
var descName: String?
var imageName: String?
func configureView() {
if let poster = self.imageName {
if let imagePoster = self.imageView {
imagePoster.image = UIImage (named: poster)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = titleName
descLabel.text = descName
self.configureView()
}
The easiest thing to do is to use a UIButton instead of an image view. Set it's type to custom and install the image into the button in IB (Interface Builder).
That way you can trigger an IBAction just like any other button. It also highlights on a touch like you'd expect, triggers on touch up rather than touch down, etc.
If you don't want to use a button-with-image, you have to set userInteractionEnabled = YES on the image view and install a tap gesture recognizer on it. See the docs on UITapGestureRecognizer for more information.

Working UIButton animations in Swift

I've been trying to get this snippit of code to work but I can't seem to get my UIButton to animate through images.
#IBOutlet weak var screenButton: UIButton!;
func animation(){
var animationButton : UIButton!;
var imageList = [UIImage]();
var image1:UIImage = UIImage(named:"3fingers-o-l-animation1.png")!;
var image2:UIImage = UIImage(named:"4fingers-o-l-animation1.png")!;
animationButtonscreenButton = screenButton;
imageList = [image1, image2];
animationButton!.imageView!.animationImages = imageList;
animationButton!.imageView!.animationDuration = 1.0;
animationButton!.imageView!.startAnimating();
}
After writing this code I've dragged a line from screenButton to the button I want to animate through the image in the Storyboard.
What am I doing wrong?
What you need to do is to not re-initialize the UIButton in the function animation; so, comment out this line:
//var animationButton : UIButton!
Besides just having an IBOutlet, we need also an IBAction to your function animation. Do the same thing as you do for your button by control dragging a "line" to the block of function (check IBAction, not IBOutlet).
A little walk-through while you are still in storyboard:
What you have is only one button named: animationButton, which is an IBOutlet from your storyboard to your code by control-dragging a "line".
For your animation function:
Control-drag also from storyboard from the button a "line" to the block of the animation function.
Set up an initial image for you button in storyboard as will be mentioned shortly below.
In addition, we need to set up an initial image in storyboard; otherwise, the image property of the button is nil.
Please do so in storyboard by clicking on the right hand side "Attributes Inspector" and then set an image where it says "image". As test, I set that up as "1.jpg".
Thus, you code should look like the following:
#IBOutlet weak var animationButton: UIButton!
#IBAction func animation()
{
print("button touched")
//var animationButton : UIButton!
var imageList = [UIImage]()
var image1:UIImage = UIImage(named:"1.jpg")!
var image2:UIImage = UIImage(named:"2.jpg")!
//animationButtonscreenButton = screenButton;
imageList = [image1, image2];
animationButton!.imageView!.animationImages = imageList
animationButton!.imageView!.animationDuration = 1.0
animationButton!.imageView!.startAnimating()
}
Just ran a quick test; it gets touch event and the images animate on the button. Hope this helps.

Resources