I have a tableview in my view controller with a custom cell. in the cell I have a function that is suppose to do something. I have a print statement that is getting executed.
#objc func cellButtonTapped() {
cellText.backgroundColor = .red
print("cell button tapped")
}
when I tap the button I do see in my console the print statement, but its not changing the cell background color like I want it to.
this is the cellText in the tableViewCell
let cellText : UITextField = {
let cellText = UITextField()
cellText.isUserInteractionEnabled = false
return cellText
}()
this is how its layout is in the cell. I don't think its layout is important
override func layoutSubviews() {
super.layoutSubviews()
contentView.addSubview(cellText)
contentView.addSubview(cellButton)
cellText.frame = CGRect(x: 0,
y: 0,
width: contentView.width - 30,
height: contentView.height)
cellButton.frame = CGRect(x: cellText.right, y: 0, width: 30, height: contentView.height)
}
what I had to do is create a variable in the viewController with the value that the cell needs. in my case I wanted a bool value to be carried over.
var isBool : Bool = false
then I let the function for the button to change the variable value:
#objc func sendButtonTapped() {
isBool = !isBool
tableView.reloadData()
print("send button tapped")
}
the function here changes the value of my bool every time I click the button.
I transferred the value to the cell with the cellForRowAt in the tableview.
Related
I am seeing some weird behavior from an array of buttons I have built in storyboard. I have 4 buttons each of custom type TakesContainerButton and when a button is clicked it changes to the system font, but when a different button is clicked the previously button returns to the desired font, not sure what is going on here
The buttons are also embedded in a stack view, if that matters
Here is the the implementation when one of the buttons is pressed where buttons is an array of the 4 buttons
#IBAction func filterPressed(_ sender: TakesContainerButton) {
for button in buttons {
button.unclick()
}
sender.click()
}
here is the custom class
class TakesContainerButton: UIButton {
var bottom = UIView()
func click(){
self.setTitleColor(.darkGray, for: .normal)
let xOffset:CGFloat = 10
bottom = UIView(frame: CGRect(x: xOffset / 2, y: self.frame.height - 3, width: self.frame.width - xOffset, height: 3))
bottom.layer.cornerRadius = 1.5
bottom.backgroundColor = .darkGray
self.addSubview(bottom)
}
func unclick(){
bottom.removeFromSuperview()
self.setTitleColor(UIColor(hex: "8B8B8B"), for: .normal)
}
override func awakeFromNib(){
setFont()
}
func setFont(){
self.titleLabel?.font = UIFont(name: "Lato-Bold", size: 12)
}
}
In StoryBoard set button :
Type to Custom
Style to Default and
State Config to Default
you should have something like this
Is there any specific reason that you are calling setFont() on every click. As I am able to see that you are not changing the font you should set this font at the time of view loading and leave the font as it is.
When a user clicks on a collection view item, I want to change the UILabelView text property:
// This is another viewController not the one containing the label
// Handle collectionViewItem selection
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("INSIDE TableViewCell2.collectionView 3")
TabsBarController.sharedInstance.testTitle = "UILabelText"
print("didSelectItem\(indexPath)")
}
Once it's set, I try to update it here:
class TabsBarController: UIViewController {
static let sharedInstance = TabsBarController()
var movieTitle: UILabel? = UILabel(frame: CGRect(x: 0, y: 0, width: 300.00, height: 30.00));
var testTitle: String? = nil {
didSet {
print("testTitle.didSet: ",testTitle!) // logs the correct text
movieTitle?.text = testTitle
print(" movieTitle?.text : ", movieTitle?.text ) // logs the correct text
}
}
}
The problem here is that even though movieTitle?.text, in the UI, the movieTitle UILabel doesn't change.
I've read many answers to similar question, and all of them point to using the main thread, so I added this:
class TabsBarController: UIViewController {
static let sharedInstance = TabsBarController()
var movieTitle: UILabel? = UILabel(frame: CGRect(x: 0, y: 0, width: 300.00, height: 30.00));
var testTitle: String? = nil {
didSet {
// I added this but still nothing changed.
DispatchQueue.main.async {
// Run UI Updates
print("testTitle.didSet: ",testTitle!) // logs the correct text
movieTitle?.text = testTitle
print(" movieTitle?.text : ", movieTitle?.text ) // logs the correct text
}
}
}
}
But, still the UI doesn't get updated. Any idea why is this happening and how to solve it?
NOTE: This is the hierarchy :
The hierarchy is like this TabsBarViewController-> MoviesViewController -> UITableView->UitableViewCell->CollectionView
Based on the project hierarchy, I had to follow the instructions here in order to be able to access the UITabsBarController testTitle property from inside the tableViewCell.
Just one caveat, I had to do this casting:
// Handle collectionViewItem selection
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("INSIDE TableViewCell2.collectionView 3")
if let vc2 = self.viewController?.parent as? TabsBarController {
vc2.testTitle = "THIS WILL DEFINITELY ABSOLUTELY WORK I DONT CARE"
}
print("didSelectItem\(indexPath)")
}
I have been trying to fix an issue that I encountered with a tableviewcontroller.
The sections within the tableviewcontroller are views:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionLabel = UILabel()
sectionLabel.text = Catalog.sharedInstance.allSections[section - 1].name.localized(lang: defaults.string(forKey: "language")!)
sectionLabel.font = UIFont(name: "Centabel Book", size: 25)
sectionLabel.backgroundColor = UIColor.white
sectionLabel.clipsToBounds = true
return sectionLabel
}
If I try to add a button programatically to put it over the tableview
let actionButton = JJFloatingActionButton()
override func viewDidLoad() {
super.viewDidLoad()
// Configuration of the Floating Action Button
actionButton.buttonColor = .red
actionButton.addItem { item in
self.performSegue(withIdentifier: "goToSettings", sender: nil)
}
actionButton.display(inViewController: self)
actionButton.clipsToBounds = true
// This doesn't work. It is to bring the button to the front. Now it is hidden by the sections.
view.bringSubviewToFront(actionButton)
// Checks if the language setting is nil, which means it is the first time you run the application. If then... selects English as default.
if defaults.string(forKey: "language") == nil {
defaults.set("en", forKey: "language")
}
}
... I don't know why but the viewForHeaderInSection hides the button. You can check it in the picture below:
floating button hided by the headersection
I tried to use the method:
view.bringSubviewToFront(actionButton)
and also:
actionbutton.superview?.bringSubviewToFront(actionButton)
But none of this brings the button to the front.
I am using a floating action button from github called JJFloatingActionButton. But I tried to add a simple UIButton and I got the same error. This is the code that also gave me the same error inside viewDidLoad:
let button = UIButton(frame: CGRect(x: 100, y: 1000, width: 100, height: 50))
button.backgroundColor = .green
button.setTitle("Test Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
Again the same error. You can check the picture:
adding a simple UIButton happens the same problem
May be you can help me with that.
Thanks in advance.
You could try to use a regular UIViewController (not UITableViewController) and add the UITableView by hand.
Like that you would have better control over the view hierarchy.
I am very new to Swift and Xcode. I am trying to make a UIButton appear at the right side of a tableView cell once the user presses the return key. Right now I am just having problems having a button appear in general.
From my understanding here is my custom class TextInputTableViewCell which I believe should create a button:
class TextInputTableViewCell: UITableViewCell {
#IBOutlet weak var textField: UITextField!
var cellButton: UIButton!
func createCellButton()
{
let image = UIImage(named: "Completed Circle.png")
cellButton = UIButton(frame: CGRect(x: 340, y: 56, width: 30, height: 30));
cellButton.setBackgroundImage(image, for: UIControlState.normal)
addSubview(cellButton)
}
And then here is where I configure the properties of the cell in my ViewController class:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! TextInputTableViewCell
cell.textField.delegate = self
cell.backgroundColor = UIColor.clear //to get background image loaded
cell.createCellButton()
return cell
}
I know I am probably messing something up. Also, any tips on how to make the appear after the user presses enter would be appreciated. I have the textFieldShouldReturn function set up.
why do not you use storyboard to make a UIButton and make an Outlet. Then in cellForRowAt do cell.button.isHidden = true cell.button.isUserInteractionEnabled = false (or something similar, not sure about actual spelling). Then make your TextInputTableViewCell conform UITextFieldDelegate
class TextInputTableViewCell: UITableViewCell, UITextFieldDelegate { ..
inside cell:
func textFieldShouldReturn(textField: UITextField!) -> Bool { //delegate method
self.button.isUserInteractionEnabled = true
self.button.isHidden = false
return true
}
you might face some problems with reusability of cells, so better make some local variable like var userDidEnterText = false to check if user has changed something
Looking on the createCellButton() body I can tell that the value of x & y could be the source of the problem. I think that the button is created out of the cell frame. Try to use the following parameters:
cellButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30));
I am working on an application in Swift. At the beginning I provide number of inputs that I would like to add. In next view I create as many UITextFields as I defined in first view.I have a problem with storing of all this values from TextFields after pressing the button. It seems to me that the most effective solution is to create an array of UITextFields and add every value of TextField into array and then in action for button adding values which are in all TextFields into array. Unfortunately, it doesn't work. Any suggestions? Thanks in advance.
override func viewDidLoad() {
super.viewDidLoad()
var counter = 0
for i in 1...mainInstance.numberOfInputs
{
super.viewDidLoad()
array.insert(UITextField(frame: CGRect(x: 0, y: 50, width: 60, height: 20)), at: i)
array[i].center = CGPoint(x: 200,y: 50 + counter)
array[i].textAlignment = NSTextAlignment.center
array[i].layer.borderWidth = 1
array[i].layer.borderColor = UIColor.black.cgColor
self.outletScrollView.addSubview(array[i])
counter += 50
}
super.viewDidLoad()
let button = UIButton(type: .system) // let preferred over var here
button.frame = CGRect(x: 200, y: 50 + counter, width: 100, height: 20)
button.setTitle("Recalculate", for: UIControlState.normal)
button.addTarget(self, action: "actionRecalculate:", for: UIControlEvents.touchUpInside)
self.outletScrollView.addSubview(button)
outletScrollView.contentInset = UIEdgeInsetsMake(0, 0, CGFloat(counter+100), 0)
}
You could create easily with:
let textFields = [UITextField]()
You should consider using an UIScrollView, (like in your example) or (better idea in my opinon) a UITableView to add your UITextfields. So you have multiple Rows, and every row has one UITextField. The number of rows / Textfield can u easily customize (and get it from your FirstViewController for example).
Just create a custom UITableViewCell - add an UITextField and connect the IBOutlet. To get the values from every UITextField you could iterate through all cells, and read out the values. Just ask, if you need more help about doing that.
Creating array of UITextfield could be done this way
// Create an empty array of type UITextField
var listOfTextFields : [UITextField] = []
// In viewDidLoad, create a textfield and add it to the array
override func viewDidLoad() {
super.viewDidLoad()
for i in 0...mainInstance.numberOfInputs-1 {
let textField = UITextField((frame: CGRect(x: X, y: Y*i, width: yourWidth, height: yourHeight)))
textField.delegate = self
listOfTextFields.append(textField)
}
}
In this UITextField setup, I didn't account for any formatting to shorten the answer.
Though this might not be for the exact use case, it could help others with similar use cases (particularly programmatically created textfields or custom uicell).
txtfield.tag = indexPath.row // or other int
Then you implement textfield didEndEditing after array has been initialized and delegating
#IBAction func endedEditing(_ sender: UITextField) {
arr[sender.tag] = sender.text
}