Center words in Label which is in collection view - ios

I want to center the text of a label which is in a collection view. I was looking inside the storyboard label settings and couldn't find a way to do it. My code is
class SingleRowCell: UICollectionViewCell {
#IBOutlet weak var tImageView: PFImageView!
#IBOutlet weak var tLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}}
Is this done by code or from the storyboard? When I build the app the words in the label come from the left and want it to be aligned to the center.

Override layoutSubviews()
class SingleRowCell: UICollectionViewCell {
#IBOutlet weak var tImageView: PFImageView!
#IBOutlet weak var tLabel: UILabel!
override func layoutSubviews() {
super.layoutSubviews()
tLabel.textAlignment = NSTextAlignment.Center
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}

Related

Better way of handling xib button press than chained delegates?

I have implemented some code including protocols to chain the active instance up to the VC to allow for Segues and am wondering if there's a better way to solve this problem or if I'm handling the Segue the wrong way.
Segues within child classes do not work because they are not in the primary VC
Excerpt from VC file
class ViewController: UIViewController, UITableViewDelegate, TableViewControllerDelegate {
func didButtonPressed() {
performSegue(withIdentifier: "destStory", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
tableViewController.delegate = self
}
}
protocol TableViewControllerDelegate {
func didButtonPressed()
}
class TableViewController: UITableViewController, TableViewCellDelegate {
func didButtonPressed() {
delegate?.didButtonPressed()
}
let test = ["test1", "test2", "test3"]
var instanceOf = self
var delegate: TableViewControllerDelegate?
Excerpt from cell file
protocol TableViewCellDelegate {
func didButtonPressed()
}
class TableViewCell: UITableViewCell {
var delegate: TableViewCellDelegate?
#IBOutlet weak var labelOne: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var buttonOne: UIButton!
#IBAction func buttonOnePressed(_ sender: Any) {
delegate?.didButtonPressed()
}
This functions the way I'd expect but seems potentially confusing to work with.
Another option is using closures instead of delegate.
class TableViewCell: UITableViewCell {
var buttonPressedClosure: (() -> Void))?
#IBOutlet weak var labelOne: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var buttonOne: UIButton!
#IBAction func buttonOnePressed(_ sender: Any) {
buttonPressedClosure?()
}
}
Also, you can add target action for cell's button inside cellForRow UITableViewDelegate function directly, but it is a dirty way in my opinion.
let cell = ...
cell.button.addTarget(self, action: #selector(didButtonPressed), for: .touchUpInside)

Calling a function that will hide a button from another class - swift

I'm trying to create an IMDB-ish movie application where when the user doesn't login and presses a Skip button, a Favorite (add a movie to favourites) button would dissappear.
The LandingViewController is where the Skip button is and the MovieTableViewCell is where all the data is presented.
What must I do so that the hide action will work inside the function? what's the logic behind this? what am I missing?
Kindly check the below comments in the code. thanks !
import UIKit
class LandingViewController: UIViewController {
#IBOutlet weak var skipButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func didTapSkip(_ sender: Any) {
MovieTableViewCell().hideButton()
}
import UIKit
class MovieTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var ratingLabel: UILabel!
#IBOutlet weak var languageLabel: UILabel!
#IBOutlet weak var releaseYearLabel: UILabel!
#IBOutlet weak var posterImage: UIImageView!
#IBOutlet weak var favoriteButton: UIButton?
override func awakeFromNib() {
super.awakeFromNib()
favoriteButton?.isHidden = true // works here for some reason
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func hideButton() {
favoriteButton?.isHidden = true // doesn't work and If I unwrap it, the app will crash, because it will find the buttton as NIL for some reason
print("hidebutton") // the print works so the function works when the skip is pressed
}
Try using NSUserDefaults
In LandingViewController
#IBAction func didTapSkip(_ sender: Any) {
UserDefaults.standard.set(true, forKey: "didSkip")
}
In MovieTableViewCell
override func awakeFromNib() {
super.awakeFromNib()
if UserDefaults.standard.bool(forKey: "didSkip") {
favoriteButton?.isHidden = true
} else {
favoriteButton?.isHidden = false
}
}

"fatal error" when calling tableView.reloadData(), the tableView is properly connected

I am trying to dynamically update a tableView while the program is running. I believe I have updated the array that the data loads from correctly, but when I press the button that calls self.eventTable.reloadData() I receive the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the relevant code:
View Controller:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Timer view
#IBOutlet weak var playButton: UIBarButtonItem!;
#IBOutlet weak var pauseButton: UIBarButtonItem!;
#IBOutlet weak var refreshButton: UIBarButtonItem!;
#IBOutlet weak var timerLabel: UILabel!
var counter = 0
var timer = Timer()
var isTimerRunning = false
//testing view container
var viewShowing = 1;
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
pauseButton.isEnabled = false
hideAll();
self.basicContainer.isUserInteractionEnabled = true;
self.basicContainer.isHidden = false;
self.timerLabel.text = String("00:00:00");
eventTable.dataSource = self
eventTable.delegate = self
super.viewDidLoad()
loadEvents(event: "timer start")
}
...
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Add table to keep track of events
#IBOutlet weak var eventTable: UITableView!
var eventData = [Session]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
private func loadEvents(event: String) {
guard let event1 = Session(session: event) else {
fatalError("Unable to instantiate event")
}
eventData += [event1]
DispatchQueue.main.async() {
self.eventTable.reloadData()
}
}
func testPrint() {
loadEvents(event: "testing cell adding")
//self.eventTable.reloadData()
viewWillAppear(false)
print("This is a test print");
}
}
The function works fine when it is called in ViewDidLoad(), but not when it is called by the button in another class ("This is a test print" prints to console so I know the button call is going through).
Expected behavior is the tableView (eventTable) reloading showing two cells, "timer start" and "testing cell adding" (ideally with "testing cell adding" being at the top).
Also want to emphasize that eventTable is connected to the storyboard, which seems to be a common problem on here.
Here is the Session.swift file and the eventTableViewCell.swift file if those are helpful:
Session.swift
import Foundation
import UIKit
class Session {
//MARK: Properties
var session: String
//MARK: Initialization
init?(session: String) {
guard !session.isEmpty else {
return nil
}
self.session = session
}
}
eventTableViewCell.swift
import Foundation
import UIKit
class eventTableViewCell: UITableViewCell {
//MARK: Properties
#IBOutlet weak var eventLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Thanks!
Edit: The ViewController from where I call testPrint().
import UIKit
class BasicViewController: UIViewController {
var VC = ViewController();
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Basic buttons
#IBOutlet weak var warmButton: UIButton!
#IBOutlet weak var dryButton: UIButton!
#IBOutlet weak var stimulateButton: UIButton!
#IBOutlet weak var controlButton: UIButton!
#IBOutlet weak var bedButton: UIButton!
#IBOutlet weak var tempButton: UIButton!
#IBOutlet weak var pulseButton: UIButton!
#IBOutlet weak var ecgButton: UIButton!
#IBOutlet weak var apgarButton: UIButton!
#IBOutlet weak var helpButton: UIButton!
//APGAR options
#IBOutlet weak var skinColor: UIButton!
#IBOutlet weak var pulse: UIButton!
#IBOutlet weak var grimace: UIButton!
#IBOutlet weak var flexion: UIButton!
#IBOutlet weak var respiratoryEffort: UIButton!
#IBAction func warmButton(sender: AnyObject) {
VC.testPrint();
}
}
It would seem that you are all right in stating that I am instantiating a new ViewController which is causing the issue. How should I go about fixing this? Fairly new to Swift
I think, your problem is in this lines of codes:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
Can you check the cell identifier is same as your cell identifier
And number of rows in eventData array

Error when creating observer for textfield to enable/disable button (Swift 3, Xcode 8.x)

I am trying to create an observer for when the specified text field ends editing in order to disable/enable a button that forwards to a new segue.
In the end, I want to have a button that is only enabled when the the textfield is full and finished editing, which will allow it to move on to the next VC.
The error that is showing is:
Cannot call value of non-function type '((UITextFieldDelegate) -> (UITextField) -> Bool)?'
Here's my source code:
import UIKit
class EmailViewController: UIViewController, UITextFieldDelegate {
// Back Button Two
#IBOutlet weak var backButtonTwo: UIButton!
// Email Header
#IBOutlet weak var emailSloganLabel: UILabel!
#IBOutlet weak var emailDescSloganLabel: UILabel!
// Email Form Entries
#IBOutlet weak var emailAddressMiniHeader: UILabel!
#IBOutlet weak var emailAddressTextField: UITextField!
#IBOutlet weak var emailAddressLineBreak: UILabel!
// Bottom Bar 'Next' Navigation
#IBOutlet weak var bottomNextButtonTwo: UIButton!
#IBOutlet weak var bottomNextLineBreakTwo: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
emailAddressTextField.delegate = self
emailAddressTextField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing("textFieldDidChange:")), for: UIControlEvents.editingChanged)
}
internal func textFieldShouldEndEditing(_ emailAddressTextField: UITextField) -> Bool { if self.emailAddressTextField.text == "" {
self.bottomNextButtonTwo.isEnabled = false
} else {
self.bottomNextButtonTwo.isEnabled = true
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// Hide keyboard when user touches the outside keyboard
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
// Hides keyboard when user pressed the 'Return' Key
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
emailAddressTextField.resignFirstResponder()
return (true)
}
}
Thank you for any help, I truly appreciate it.
You should remove addTarget since it will conflict with the UITextFieldDelegate's textFieldShouldEndEditing and should use it directly to know when the textfield finish editting

Sending textbox values to UILabels

import UIKit
var typingSpace = 80
class ViewController: UIViewController {
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.
}
#IBOutlet weak var typingSpace: UIView!
#IBOutlet weak var displayLabel: UILabel!
}
Basically what I'm doing is this: when I type a certain number (let's say 70) in a text box, the label will display something (eg. Your number is 70). I honestly have no idea what I'm doing. Please help.
You need 4 things
Add a outlet for your text view so you'll have #IBOutlet weak var textView: UITExtView!
Make ViewController implement UITextViewDelegate
ViewController: UIViewController, UITextViewDelegate
Make self delegate of textView on viewDidLoad:
textView.delegate = self
Implement textViewDidChange and put your logic in there
func textViewDidChange(textView: UITextView) {
// change your label text
}
Here you have be a complete class example
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.textView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textViewDidChange(textView: UITextView) {
displayLabel.text = "your text"
}
#IBOutlet weak var textView: UITextView!
#IBOutlet weak var typingSpace: UIView!
#IBOutlet weak var displayLabel: UILabel!
}
Note: #Claudio Redi has supplied the correct answer, this is another way to populate a label from a UITextField.
This is one way of accomplishing your task:
class ViewController: UIViewController {
#IBOutlet weak var typingSpace: UITextField!
#IBOutlet weak var displayLabel: UILabel!
#IBAction func handleButtonPressed(sender: UIButton) {
displayLabel.text = typingSpace.text
}
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.
}
}

Resources