Force unwrapping (UITextField().text!) Not Crash .But (UILabel().text!) Crash - ios

Check this please i need explain why texField.text! not crash and label.text! crash
And as we know UITextField has property open var text:String? and UILabel have open var text:String?
let texField = UITextField()
texField.text = nil
print(texField.text!) // not crash
let label = UILabel()
label.text = nil
print(label.text!) //crash

From the documentation of UITextField
Declaration
var text: String? { get set }
Discussion
This string is #"" by default.
From the documentation of UILabel
Declaration
var text: String? { get set }
Discussion
This property is nil by default.
Please note the subtle difference

As a general rule of thumb, you should never force-unwrap optional values like this.
You should use if-let or guard or any way provided by swift to handle optionals safely.
If a label has no text, then label.text will return nil.
However, if a text field has no text then textField will return "" (an empty string). That's why it will not crash if you force-unwrap the text property of a text field.
I'm not sure why it designed like this by Apple, but as I wrote above you should handle optionals safely.

Related

UIlabel text does not show "optional" word when setting optional text?

I have been using optional a lot.I have declared a string variable as optional
var str: String?
Now i set some value in this variable as str = "hello".Now if i print this optional without unwrapping then it print as
Optional("hello")
But if i set text on the label as self.label.text = str then it just display value as
hello
Please explain why it does not show text as on label
Optional("hello")
The text property of UILabel is optional. UILabel is smart enough to check if the text property's value is set to nil or a non-nil value. If it's not nil, then it shows the properly unwrapped (and now non-optional) value.
Internally, I imagine the drawRect method of UILabel has code along the lines of the following:
if let str = self.text {
// render the non-optional string value in "str"
} else {
// show an empty label
}
I knew I've seen optionals printed in UILabel, UITextView, UITextField. Rmaddy's answer wasn't convincing.
It's very likely that there is an internal if let else so if the optional has a value then it will unwrap it and show. If not then it would show nothing.
However there's a catch!
let optionalString : String? = "Hello World"
label.text = "\(optionalString)" // Optional("Hello World")
label.text = optionalString // Hello World
let nilOptionalString : String?
label.text = "\(nilOptionalString)" // `nil` would be shown on the screen.
label.text = nilOptionalString // no text or anything would be shown on the screen . It would be an empty label.
The reason is that once you do "\(optionalVariable)" then it would go through a string interpolation and once its a String and not String? then the result of the interpolation would be shown!

How can i get the data from Swift based IBOutlet UITextField?

#IBOutlet var firstName:UITextField?
#IBOutlet var lastName:UITextField?
let string = firstName!.text
print(string)
The output is like as below:
Optional("ohh")
How can I get the data without optional text and double quotes?
Your issue is that the text attribute of a UITextField is an Optional - this means it must be unwrapped. To do that, you add a ! to the end, which produces a String instead of a String?.
You can also conditionally unwrap an optional using the syntax if let, so here it would be
if let string = firstName!.text{
print(string) //outputs if text exists
}else{
//text didn't exist
}

UILabel AutoResize Swift

I'm learning Swift, but I Have two "stupid" Problems.
the first, I'd like autosize my UILabel
The second, I have another UIlabel and I want to put name and surname in it's field
I tried with
#IBOutlet weak var title: UILabel!
title.text = currentPerson?.name+""+currentPerson?.surname
But I have this error
Value of optional type 'String?' not unwrapped; did you mean to use
"!" or "?" ?
Generally advised to ask 1 question per post so you get clear responses & don't mix topics, but...
In XCode storyboard "Attributes Inspector" you can change "Autoshrink" from "Fixed Font Size" to minimum font size or scale. Also change "Lines" from default 1 to 0. You'd also need to set some AutoLayout constraints to pin the label to superview or other elements in a way that will allow it to scale. Can't say more w/o seeing storyboard.
By using optional chaining to set the label text you're trying to set the label's .text property to an optional type String? instead of a String. Those aren't equivalent. An optional of type String? might contain a String, or it might be nil. The UILabel expects you to use a String instance, so it's complaining about the mismatch.
One approach is to explicitly check the optional value against nil:
if currentPerson != nil {
title.text = "\(currentPerson.name) \(currentPerson.surname)"
}
else {
title.text = ""
}
Swift's optional binding is similar to the first option, but you create a temporary constant and can reference its properties. If currentPerson is not nil, then the if block executes.
// current convention would be to use "currentPerson" on both sides, which can be confusing. The left side is a temporary constant & the right side is the optional property you've declared somewhere above
if let aPerson = currentPerson {
title.text = "\(aPerson.name) \(aPerson.surname)"
}
else {
title.text = ""
}
Alternatively, as the error message suggests, you could Force Unwrap the optional value to access the name properties:
title.text = currentPerson!.name + " " + currentPerson!.surname
This assumes that currentPerson is never nil. If it is nil, your app will crash here.
Also note you can concatenate using + and " " or with string interpolation.

Weird error in accessing the text of UIButton in swift

When I write a simple function such as this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel.text);
}
It gives me an error: UILabel doesn't have a label called text.
However, when I change it to this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel?.text);
}
It works fine, but it prints out something like this:
Optional("1");
What I am doing wrong? I am expecting a value of 1. But it is printing out Optional("1") and secondly, it is working fine when println(theButton.titleLabel?.text);
You can get directly from
let title = theButton.currentTitle!
Optional chaining makes the result optional, so you are printing optional value: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/OptionalChaining.html
With optional binding you can print the value only if it exits.
if let text = theButton.titleLabel?.text {
println(text)
} else {
// text doesn't have value
}
#Kirsteins's answer shows how to obtain the button label text in a safe manner.
Remember that:
UIButton has a titleLabel, which is an optional UILabel.
UILabel has a text property, which is an optional String
so there are 2 optionals in the chain. You can use optional binding as in #Kirsteins's answer, or use forced unwrapping:
let text = theButton.titleLabel!.text!
which however I discourage using, because if any of the 2 is nil you'll have a runtime exception. But for completeness it's worth mentioning.
The buttons titleLabel property returns an optional UILabel, that means it's possible that the button doesn't have a titleLabel.
var titleLabel: UILabel? { get }
If you don't set a title to the button, then the button doesn't have a titleLabel property, the iOS framework adds the titleLabel only if the button has a title, I think this happens to reduce memory.
This is why you have to put the "?" (is called optional chaining you can read about it here http://bit.ly/1vrSOi1) in that line, but this usually get auto completed by Xcode itself.
Kirsteins answers it correctly but misses one small detail
if your object can be nil (optional) you need to check first if it exists to then access its value, like this:
if let text = theButton.titleLabel?.text {
println(text)
}
but you can also ignore the if and just call it like this:
let text : String = theButton.titleLabel?.text
// If theButton.titleLabel don't exists then text will be nil
this happen if the IBOutlet was declared with ? but if you declare with ! that means you know that it could be nil, but you never want it to be nil, for a IBOutlet i prefer this approach since if the IBOutlet is not connected then maybe something is worn with my code.
#IBOutlet var theButton : UIButton!
// and get text value as
theButton.titleLabel!.text
this will ensure theButton.titleLabel could be nil, but in this part of code it is required, hope this helps to understand the difference between optional (?) and optional required (!)

Difference between UIButton! and UIButton? in swift IOS

Now only i am start working with swift language. I have initialize the button as follows
#IBOutlet weak var systemTextButton: UIButton!
after that i can set the title using .setTitle() property.
If i use ? instead of ! while initialize then showing the error on .setTitle() as
UIButton? does not have a member named 'setTitle'
So, Anyone please tell me the difference between UIButton! and UIButton? .
Both of them are optional types. But UIButton! is implicitly unwrapping optional type. You don't have to unwrap it manually. Take a not that your app will crash if you try to access value of UIButton! while its nil.
For more info read "Implicitly Unwrapped Optionals" section in Apple's "The Swift Programming Language" book.
The button is optional because it is not determined from the beginning if the button will be found in the interface builder document. So either
you are sure it will be there, in which case you unwrap it right in the declaration,
or it is really an optional - then you have to unwrap it each time you want to use it.
Maybe the existence of the button in interface builder is somehow dynamic, then you would keep it optional (UIButton?) to allow a nil value. In this case you have to either check for its existence before you use it, or unwrap it with myButton!. You do this at your own risk because if you try it on a nil value your program will crash.
Both variants are dealing with optionals (variables that may be nil).
#IBOutlet weak var systemTextButton: UIButton!
This is an implicitly unwrapped optional. The exclamation mark states that you (the programmer) are absolutely sure that this variable is not nil when using. You set the title via
systemTextButton.setTitle(...)
If systemTextButton is nil at that point the application crashes.
The questionmark states that this variable may be nil, so you have to use:
systemTextButton?.setTitle(...)
Now, setTitle() is only executed if systemTextButton is not nil.
Hope that helps.
For further reference on optionals see The Swift Programming Language
In this two examples the UIButton is declared as optional.
The difference is that when you declare it as UIButton! it's unwrapped for you automatically, you don't have to check is it nil, you should be sure that the button will not be nil.
The other declaration UIButton? doesn't unwrap this optional for you, you have to do it manually when you want to access it (or access it's properties).
You can do it in two way. If you are sure that the object is not nil you can use this:
button!.setTitle()
but if you are not sure about state of this optional, use this:
if let btn = button {
btn.setTitle()
}
else {
// button is nil
}
When you declare the variable of type UIButton?, you are saying to compiler that that variable could be nil (NULL in Objective-C world). So, it becomes an "optional", and all subsequent actions an that object are skipped if it's nil.
For example:
class MyClass {
var property: String?
}
let myInstance = MyClass()
if let testVar = myInstance.property {
println("Hello world")
} else {
println("Property unset")
}
You can find more info in the official swift documentation:
https://developer.apple.com/librarY/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html
These kinds of optionals are defined as implicitly unwrapped optionals. You write an implicitly unwrapped optional by placing an exclamation mark (String!) rather than a question mark (String?) after the type that you want to make optional.
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark
Straight from Apple Developer Library

Resources