When I change the text attribute of my UILabel, it only partially updates in the app.
I've tried putting it in the viewDidLoad function and in a separate dedicated function to no avail. If I print the Label.text to the console after the update it is correct, but it doesn't show up properly on screen.
The class in question:
#IBOutlet weak var PromptLabel: UILabel!
var labelText = "";
override func viewDidLoad() {
super.viewDidLoad()
print("view loaded")
self.PromptLabel.text = "Tell Us... " + labelText;
// Do any additional setup after loading the view.
}
Called by:
#IBAction func UsingButtonPressed(_ sender: Any) {
(sender as AnyObject).setTitleColor(UIColor.red, for: .normal)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil);
let secondController = storyBoard.instantiateViewController(withIdentifier: "Secondary View Controller") as! SecondaryViewController;
secondController.labelText = "What You're Using Today"
self.present(secondController, animated: true, completion: nil)
}
The label should display as "Tell Us... What You're Using Today" but it only shows "Tell U..." which makes no sense.
You need to make sure that the constraint for the UILabel's width is wide enough to accommodate the text. Otherwise, it is being cutoff and the ... you are seeing is because the label's line break is set to truncating tail, which means that the end of the string will be replaced with ... when the label is too narrow.
So this is an interface builder issue and not a Swift-specific issue. The label's text is being correctly updated, the UI is just not able to properly display it.
If you want the width constraint of the label to change dependent on the text, there are ways to calculate the width of the text and update the constraint's constant to accommodate that text's width.
Related
I am using Swift and have a UITextView that I wish to always keep scrolling as I add new text and the length of the text is greater than what the textView can display.
The following works perfectly as long as my textview does not contain any new lines "\n"
let range = NSMakeRange(textView.text.count - 1, 1)
textView.scrollRangeToVisible(range)
However, as soon as I add a return, the range no longer is valid for the scroll.
I have checked out as many of the related posts as I can, but none seem to address this problem. Can anyone help?
OK. I discovered what the issue was. if a UITextView is made unselectable, when you programatically add text to the view, the view will not scroll properly if there are returns in the text, whereas text without returns scrolled perfectly.
Here is a simple example. Create a Viewcontroller with one button and a UITextView.
Wire it up and play with the two Bools.
You will find that if isSelectable = false and isReturnText = true then it will not scroll, however if isReturnText = false, it scrolls find.
If I set isSelectable = true then both scroll perfectly as expected.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textView: UITextView!
var isSelectable:Bool = true
var isReturnText:Bool = true
let returnText = "These sentences are separated by returns.\n"
let nonReturnText = "These sentences are separated by space. "
override func viewDidLoad() {
super.viewDidLoad()
textView.isSelectable = isSelectable
}
#IBAction func addNoReturnText(_ sender: Any) {
textView.text += isReturnText ? returnText : nonReturnText
let range = NSMakeRange(textView.text.count - 1, 1)
textView.scrollRangeToVisible(range)
}
}
I have got a label that appears in the NavigationBar when the View of the FirstViewController opens for the first time. The label shows a number that should be able to change. If I click a button on the FirstViewController the View of the SecondViewController shows up in which's NavigationBar the label of the FirstViewController is still visible. When I change the number that is written in the label by clicking on a button in the SecondViewController the number of the label only changes when I go back to the View of the FirstViewController. That is because I update the title in the ViewDidLoad String loop.
Now my question is:
I want the number of the label to be changed at the moment when I click the button in the SecondViewController, although the label was defined in the Code of the FirstViewController. The number of the label shows an amount of money.
This is the Code of the FirstViewController:
var moneyLabel: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
setupNavigationLabel()
let newMoney:String = String(format: "%f", money)
updateTitle(title: "\(newMoney)")
}
func updateTitle(title: String) {
if let myTitleView = self.moneyLabel {
myTitleView.text = title
}
}
func setupNavigationLabel() {
let navigationBar = self.navigationController?.navigationBar
let moneyFrame = CGRect(x: 300, y: 0, width:
(navigationBar?.frame.width)!/2, height: (navigationBar?.frame.height)!)
moneyLabel = UILabel(frame: moneyFrame)
moneyLabel?.text = "\(money)"
navigationBar?.addSubview(moneyLabel!)
}
It seems that your problem is with the second ViewController but you are not sharing any code!!! Use the below to achieve your objective.
class secondViewControler:UIViewController{
var money:Int
var moneyLabel:UILAbel?
override func viewDidLoad(){
self.money= //pass the amount, i dont know which way you use to store and retrieve the amount
moneyLabel.text="\(money)"
}
#IBAction updateMoney(){
//get the amount from the textfield say the output is X
money=X
moneyLabel.text="\(money)"
}
}
I am trying to set the values of UILabel's on another view controller. However I keep getting a nil value when I am trying to set temp values for the other view controller's UILabels and such. This is the function that executes the segue:
func swipe(Sender: UISwipeGestureRecognizer!) {
print("swiped left")
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("OnDeck") as! OnDeck
vc.firstBase = UIView(frame: CGRectMake(178, 136, 10, 10))
vc.firstBase.backgroundColor = UIColor.redColor()
vc.firstBase.layer.cornerRadius = vc.firstBase.frame.size.width/2
self.presentViewController(vc, animated: true, completion: nil)
}
I am getting the following error on the line vc.firstBase.backgroundColor = UIColor.redColor()
fatal error: unexpectedly found nil while unwrapping an Optional value
is there something I am missing when attempting to declare the temp values for the outlets?
You should not set those related UI elements, because the UI haven't loaded yet. Instead, pass a value and set it in viewDidLoad of destination controller
class OnDeck: UIViewController {
var color = UIColor.white()
override func viewDidLoad() {
...
firstBase = color
}
}
Then in your swipe method, pass the value only rather than modify the unloaded UILabel or UIView. Else, move the UI related code to the destination viewDidLoad() such as the cornerRadius, frame size, etc
Hello I am trying to have a number pad appear after a timer is up. Then have my user type numbers on the pad and their input be saved to a variable in my code not a text box. I can't seem to find anything on popping up a number pad without using a text box. Any help is appreciated.
Ok I'm going to give you some code that will greatly help you. You need some sort of UITextView or UITextField to get the system keyboard. So essentially what we will do is have a textField without showing it, and then grab the info off it and store it into the variable.
//Dummy textField instance as a VC property.
let textField = UITextField()
//Add some setup to viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self //Don't forget to make vc conform to UITextFieldDelegateProtocol
textField.keyboardType = .phonePad
//http://stackoverflow.com/a/40640855/5153744 for setting up toolbar
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
let flexBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneBarButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard))
keyboardToolbar.items = [flexBarButton, doneBarButton]
textField.inputAccessoryView = keyboardToolbar
//You can't get the textField to become the first responder without adding it as a subview
//But don't worry because its frame is 0 so it won't show.
self.view.addSubview(textField)
}
//When done button is pressed this will get called and initate `textFieldDidEndEditing:`
func dismissKeyboard() {
view.endEditing(true)
}
//This is the whatever function you call when your timer is fired. Important thing is just line of code inside that our dummy code becomes first responder
func timerUp() {
textField.becomeFirstResponder()
}
//This is called when done is pressed and now you can grab value out of the textField and store it in any variable you want.
func textFieldDidEndEditing(_ textField: UITextField) {
textField.resignFirstResponder()
let intValue = Int(textField.text ?? "0") ?? 0
print(intValue)
}
I am using storyboard and this is what I did:
drag-drop a text field
On the storyboard, in the attributes inspector (having selected the text field), under "Drawing", select hidden
make an outlet for the text field in your view controller
make sure your view controller extends the UITextViewDelegate
make your current view controller the delegate
in the required location simply call <textfieldOutlet>.becomeFirstResponder()
Now that this is simply a textfield's data, u can always store the value and use it else where.
I created a navigation controller with a view controller inside, containing a label. This label should be changed, when the view controller is loaded on tapping a button.
class ViewController: UIViewController {
#IBOutlet weak var btnEmergency: UIButton!
override func viewWillAppear(animated: Bool) {
self.btnEmergency.backgroundColor = UIColor.redColor();
}
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnEmergencyTapped(sender: AnyObject) {
let emergencyViewController = storyboard?.instantiateViewControllerWithIdentifier("EmergencyViewController") as! EmergencyViewController
emergencyViewController.emergencyLabel?.text = "Notruf"
navigationController?.pushViewController(emergencyViewController, animated: true)
}
}
But the label text does not change when loaded. I am relatively new to SWIFT so I try to learn my ropes at the moment using optionals. So I guess the reason is, that the label is not yet instantiated when the view is being loaded on pressing the button. Therefore the default text is being shown and not the text I want to have appear on screen.
I am a little bit stuck at the moment, how to correctly change the label text, when this is an optional. So I guess I cannot expect the label to be there, when I call it. But how do I handle this correctly?
Instead of this, the correct way is to set a property of your emergencyViewController.
In your emergencyViewController viewDidLoad set your label text according to the property set previously.
Anything that you do between initialize of a viewController to viewDidLoad will not take effect.