Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why was UITextField's text property changed to an optional in Swift 2?

According to the UIKit diff document, in ios9/Swift 2

var text: String! has become var text: String?

According to the documentation for UITextField it specficially says

This string is @"" by default.

I don't understand the purpose of this change. Shouldn't that property always be an empty string if the text field exists at all? At what point does this field return an empty string? Once the user interacts with it? Once it's been added to the view hierarchy? At what point does it return nil?

If the text field exists in the first place, is it always safe to assume the text property exists as well? This just seems like it's going to lead to a lot of find/replace .text to .text!

I don't see where it's mentioned in the docs so maybe someone has some backstory or help on why this changed.

like image 392
Will Avatar asked Sep 17 '15 00:09

Will


1 Answers

In short, (answer to the title) it wasn't.

In detail:

To me it makes a lot more sense to have it as an optional that isn't forced unwrapped. Apple is pushing devs to never just use optional! and it only makes sense that they apply the same rules to the API's.

The reason for this is that it can be nil, and it doesn't make any difference if it is declared with ? or ! for running the code. Using ! actually just removes the warnings in Xcode which are really handy, especially when it comes to API code. If you don't realise it actually is an optional you are just asking for trouble.

Checking for nil is also much nicer now with guard and you can chain this with a check for "" so it's not really more work.

In general optionals are better because something that is nil is not using memory. The more optionals we got, the lighter we can make our apps. Also it doesn't even look bad and doesn't add to the pyramid of doom.

This example will take both strings as arguments, remove the ? in the func parameter and Xcode will be there to warn you.

I forgot to answer this part directly : It becomes nil when you set it to nil, which you might do to save a little bit of memory. It just doesn't make sense to have the option to set it to nil and not have xcode warn you to handle it properly. => This is impossible...

var forcedUnwrappedString : String! = "" var optionalString : String? = ""  forcedUnwrappedString = nil optionalString = nil  func doSomethingWithString(string : String?) -> String? {     guard var unwrappedString = string else {         // error handling here         return nil     }     let tempString = unwrappedString + "!"      return tempString }  func doSomethingUnsafeWithString(string : String) -> String {      let tempString = string     return tempString  }  var newString = doSomethingWithString(optionalString) var newString2 = doSomethingWithString(forcedUnwrappedString)  newString = doSomethingUnsafeWithString(optionalString!) // this will crash without a warning fro xcode newString2 = doSomethingUnsafeWithString(forcedUnwrappedString) // this will crash without a warning fro xcode 

Update:

The text property of the UITextfield has a setter that always sets to "" in case of nil, no info on this anywhere in the docs or in the UIKit .h files.

var textField = UITextField(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) var string = textField.text // string = "" textField.text = nil string = textField.text // string = "" 
like image 122
R Menke Avatar answered Oct 20 '22 13:10

R Menke