I'm very new to Swift development, so apologise if this is a really silly question - having read Apple's guide, I am surprised by the behaviour I have come across (and a little miffed).
I am creating a really simple class which defines a number of uninitialised constants at the beginning of the class. When the class is initialised, the values are set. It seems as though I cannot do this unless I declare the constants to be optional, even though they are not optional and are all set in the constructor. For example:
class TestClass {
private let urlAddress:String
init(urlAddress: String) {
self.urlAddress = getUrlAddressWithProto("http", urlAddress:urlAddress)
}
func getUrlAddressWithProto(proto: String, urlAddress:String) -> String {
return "\(proto)://\(urlAddress)/"
}
}
The function getUrlAddressWithProto returns a non-optional String but Xcode throws the error:
error: variable 'self.urlAddress' used before being initialized
Does anyone have any thoughts firstly on why this is the case and if there is a suitable alternative to declaring all my constants as optional?
The compiler probably wants to tell you that you are not allowed to call that function before all non-optional variables are initialized. Sometimes the error messages are not very obvious.
Swift prevents the use of instances that are in an inconsistent state. Swift does not know that the function you call doesn't rely on internal state, so you can't call instance functions before init is done at all.
You have a couple of options, besides marking the variable as optional.
Turn that function into a class function. Since class functions are not bound to an instance you can call them before the init of the instance is done
move the code from the function to the initializer
Turn the variable into an implicitly unwrapped optional. (i.e. let urlAddress: String!). You can use that variable as if it were a non-optional variable. Just make sure that you set it during init. If you do something with it while it is nil the program will abort.
Depending on your real code the last one is probably the only viable option.
Related
After reading Apple's ARC guide, I'm slowly attempting to get a grasp on retain cycles however what isn't clear to me is swift's type inference requires the optional question mark or forced unwrapping exclamation point when inferring a variable in the global scope of a class.
For example:
import XCTest
#testable import PassionProject
class ItemManagerTests: XCTestCase {
var sut: ItemManager!
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
sut = ItemManager()
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func tests_ToDoCount_Is_InitiallyZero() {
XCTAssertEqual(sut.toDoCount, 0)
}
func tests_DoneCount_Is_InitiallyZero(){
XCTAssertEqual(sut.doneCount, 0)
}
}
If I leave out the question mark or explanation point on the following line, it throws an error about the class not having initializers:
var sut: ItemManager
My question is, isn't type inference just simply saying this variable will be of this type? If so, why is Xcode considering it a property if we haven't given it an initial value? Also second, why does force unwrapping a inferred type compile if we never set its value?
If needed, here is the code for the object we're using as an example and thank you in advance for getting a better grasp:
import Foundation
class ItemManager {
let toDoCount = 0
let doneCount = 0
}
That's not type inference. If you declare a variable's type, inference doesn't happen. Inference is all about figuring (inferring) out what a type is if you don't say explicitly.
You're having a problem with Swift initializer rules. If you declare that a class has this property:
var sut: ItemManager
Then that's non-optional, which means it must have a value by the time initialization is complete. You're not doing that, so Swift is complaining about your initializers. You can either add an init method that assigns a value or you could declare it and assign a value at the same time-- which might look like this:
var sut: ItemManager = ItemManager()
If you declare it like this:
var sut: ItemManager?
Then it's optional, which means if you don't assign a value then it gets a value of nil. You don't have to assign a value during initialization because it already has one.
Swift, for safety reasons, requires all variables to always hold a value. This prevents that scenario where the value of a variable can be unknown. However, there are still cases in programming where one wants to represent the absence of a value. A great example of this is when performing a search. One would want to be able to return something from the search that indicates that no value was found.
Therefore in Swift,the class members must have a value at the time of declaration.By default a member of a specific type ,say, Int cannot be nil and it does not get a default value.If we know that the value of a variable may be nil then we define it as an Optional.
Now you have three options to provide an initial value to a class member :
By initialising it at the time of declaration
By providing it a value in the init method
By defining it as an optional or unwrapped optional which depends upon the use of the variable
I am learning the swift syntax and got a little confused with the optional type.
So, from the defination a swift type can not store the null value unless it is explicitly defined as an optional. So, what does the variable in the following line contains when it's declared.
var a:Int (declaring a variable without intializing it working fine in swift 3)
And also when we declare a variable as an optional with a "!",
var optionalSquare: Square! = Square(sideLength: 10, name: "Optional Square")
if we want to use the "optionalSquare" variable, we do not need to unwrap it cause we are sure(I think that is why we are using "!" instead of "?") it does not contain any null value. so why don't we declare it as a normal variable.
Please correct any false statements. Thank you.
what does [var a:Int] contains when it's declared
Nothing. Its value is undefined. Using it before assigning a value is a compilation error. You can declare it without initializing it, but you cannot use it.
This is part and parcel of Swift's philosophy of safety: in C, you could likewise leave a variable uninitialized, and its value would be undefined, but the compiler would not (by default) report error if you use it.
so why don't we declare it as a normal variable.
There's no reason that I can think of to make a local variable an implicitly unwrapped optional. The functionality is intended for properties ("ivars") on structs or classes. You should use them where it's impossible to set the property in the object's init, but it is certain that the value will be present before the object is used.
IBOutlets are probably the canonical use case. Another use that I find helpful is to allow setting a property by calling a method in init.
So, what does the variable in the following line contains when it's declared.
It does not matter, because you cannot access it anyway. A declaration like this tells Swift that you are going to decide on the value later. Reading the variable before assigning is an error that the compiler is going to catch.
why don't we declare [variables with forced unwrapping] it as a normal variables?
Because you may want to store nil in that variable at the times when it should not be used.
For example, you should make IB-assigned property implicitly unwrapped, because they need to be nil before NIB objects are "inflated", but after the init method has completed:
#IBOutlet private weak var myLabel: UILabel!
In order to make myLabel non-optional you would have to drop weak. On the other hand, you don't want to use exclamation point on each access of myLabel, because you know for sure that it must be initialized.
The same reasoning applies to other variables that you would like to make non-optional, but cannot assign in an initializer.
You can declare a non optional variable and not initialize it - the compiler doesn't complain as long as you do not use that variable. So this code
var num: Int
won't generate any error. However if you reference that variable before initializing, compilation fails
var num: Int
print(num)
In the former case there's no error because initialization can be deferred. You can declare a variable, and then initialize 100 lines after. As long as you don't reference it before initializing, you're ok.
To answer your second question, it's correct to say that in many cases it doesn't make much sense declaring and contextually initializing an implicitly unwrapped variable: a non optional variable is more appropriate.
I just started learning Swift and recently found out about
"Normal" variables (for lack of a better name):
ex: var test1: String
"Optional" variables
ex: var test2: String?
"Implicitly Unwrapped Optionals"
ex: var test3: String!
Lazy variables
ex: lazy var test4: String
My understanding is this:
Use "Optional" variables (?) when the variable may or may not be initialized at points in the future starting from initialization
Use "Implicitly Unwrapped Optionals" (!) when the variable is guaranteed to be initialized
Optionals can be converted to Implicitly Unwrapped Optionals via "Forced Unwrapping"
ex: let possibleString: String? = "Hello"
println(possibleString!)
Use "Lazy variables" when there is no need for something to be set until initialization (it seems these can be used with (?) or (!))
Therefore, my questions are:
When do I use option 1 - a variable without ? and without !
When do I use "lazy"
I read "lazy" is often used for singletons - why?
I have the most experience in Java and C++ terms, if that helps with my background for answering.
Edit: Here's everything I found (The main issue was "Normal" vs "Implicitly Unwrapped Optionals":
"Normal" variables must be initialized: (a) On the same line, (b) in the same scope before usage (Usage means some operation with the object), (c) by the end of the init iff the variable is a field. Note: The scope of init is everything in the scope of the class AND not in the scope of functions within the class.
Printing an Implicitly Unwrapped Optional will print "nil", but using the variable's functions will throw a runtime exception. Meanwhile, using (at all, including print) a Normal variable will not allow the program to compile at all
The purpose of using ! over "" (Nothing) is (a) More leniency since the program will compile (and run correctly given the variable is actually initialized) and (b) Lets you not initialize everything at the very beginning. Note: It is a compile time error to have any field undeclared if it is a Normal variable.
Not exactly that.
All variables must be initialised before the first use, and all class/struct stored properties must be assigned value in respective initialiser. Optionals are not about being allowed uninitalised at some point, but about being allowed to contain no value, which is represented by nil, which is still perfectly an initialised stated for such variable. Therefore, if something can not be known at the moment of initialisation then that's probably where you will use some sort of an optional (e.g. delegate for a view).
Implicitly unwrapped optionals is a sort of shorthand for cases when a variable might be empty, but we are absolutely sure that when we will be really using it it will hold an actual value (typical example is a property in a view controller that holds reference to a view).
Forced unwrapping does not convert optional into implicitly unwrapped optional, instead it gives you a value that is there if it's there (i.e. if optional is not nil), and throws an exception if it's not.
Lazy properties are used in cases when you want to defer their initialisation to a later stage, when the property is actually being used for first time. Usual case is if you need to access an expensive resource to do that (load huge file from disk, download it via network, etc), especially so if there might be cases when such property is not going to be used at all (why loading it from the disk if we will not use it probably?).
let's see Apple's example
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
Residence instances have a single Int property called numberOfRooms, with a default value of 1. Person instances have an optional residence property of type Residence?.
If you create a new Person instance, its residence property is default initialized to nil, by virtue of being optional.
1. If you need default value for property to be nil - use optional. Using variable without ? and ! - like 'numberOfRooms' -
You can set the initial value of a stored property from within an initializer, as shown above. Alternatively, specify a default property value as part of the property’s declaration. You specify a default property value by assigning an initial value to the property when it is defined.
NOTE
If a property always takes the same initial value, provide a default
value rather than setting a value within an initializer. The end
result is the same, but the default value ties the property’s
initialization more closely to its declaration. It makes for shorter,
clearer initializers and enables you to infer the type of the property
from its default value. The default value also makes it easier for you
to take advantage of default initializers and initializer inheritance.
2. ! is used to access the value wrapped inside variable when it is not nil, and throws exeption otherwise. So, you can use ! in order to make mark for users of you class - 'this value will not be nil at the time you unwrap it'
3. Lazy variable is used when you want to init it later, not at the time of whole object creation but exactly at the time you ask getter for data. this is useful when property stores an array, for example:
lazy var players: [String] = {
var temporaryPlayers = [String]()
temporaryPlayers.append("John Doe")
return temporaryPlayers
}()
When should I use lazy initialization?
One example of when to use lazy initialization is when the initial value for a property is not known until after the object is initialized.
Short explanation:
A non optional variable has always a value and can never be nil.
The variable must be initialized in the init method or in the declaration line.
var a : String
var b = "bar"
init {
a = "foo"
}
An implicit unwrapped optional variable must not be initialized in the init method
or in the declaration line but is guaranteed to have always a value when it's used
var a : String!
func viewDidLoad() {
a = "Hello"
a += " world!"
}
An optional variable may have a value and is nil at declaration
var a : String? // = nil
A lazy variable is initialized later at the moment it's used the first time
class foo {
lazy var bar : String = {
return "Hello"
}()
}
The Apple Swift Programming Language guide mentions the existence of the init! initializer, but does not provide any example for it. (Search for init! in this page)
I understand the use of a normal failable initializer declared with init?, but I fail to get the need of this other version. What is it needed for? Can somebody provide an example?
This serves two purposes:
When importing Cocoa APIs that Swift doesn't know about. If Swift does not know if an initializer can return nil or not, it annotates it with ! so that the developer knows there might be a nil hiding there, without forcing the dev to test for nil if there's actually no reason to.
For the same reasons implicitly-unwrapped optionals are used in other contexts (you may be willing to trade compile-time safety for added convenience in some cases).
I belive it's absolutely the same use of ! as in optionals. init? will return an optional. init! will return an implicitly unwrapped optional.
Implicitly unwrapped optionals are needed for calling Obj-C APIs where you are not sure whether it can return an optional or not. So you use an implicitly unwrapped optional and it behaves like a non-optional type but it will crash if an optional is returned.
Note that when Swift was introduced most Obj-C frameworks returned only implicitly unwrapped optionals but currently a lot of them return optionals or non-optional types because Apple is going through the code and checks whether they can return an optional or not. init! is needed everywhere where Apple hasn't tagged the initializers correctly yet.
Good question Matteo, I´m looking answer for the same question because init! don´t have sense (if it always init an object and we don´t need optional), but I haven´t found any clear answer.
I think that it´s because Apple haven´t finished his work: "...own Objective-C classes, and classes in frameworks that have not yet been audited, initializers are imported as init! ..."
Perhaps be util for you, the text in "Interacting with Objective-C APIs"(Apple)
"In Objective-C, initializers directly return the object they
initialize. To inform the caller when initialization has failed, an
Objective-C initializer can return nil. In Swift, this pattern is
built into the language feature called failable initialization. Many
Objective-C initializers in iOS and OS X system frameworks have been
audited to indicate whether initialization can fail. These
Objective-C initializers are imported as either init(...)—if
initialization cannot fail–or init?(...) if initialization can fail.
In your own Objective-C classes, and classes in frameworks that have
not yet been audited, initializers are imported as init!(...). For
example, the NSString(contentsOfFile:) initializer can fail to
initialize an NSString object if the file doesn’t exist at the
provided path. You can use optional binding to unwrap the result of
an failable initializer if initialization is successful."
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html
I'm going to take a stab at this even though this question has been around for a while because I think some example source code would be useful for understanding what init! is for (at least it was for me).
An implicitly unwrapped optional provides two things of value:
A convenience for the programmer (so you don't have to keep typing '?' at the end of your optional variables), and
Runtime efficiency because it allows you to test an optional for nil only once, and thereafter (as long as it is non-nil) use its unwrapped (i.e. direct) value.
The important part though is that an implicitly unwrapped optional is still an optional, which means it can be tested for nil.
Now, as to the utility of the init!-failable initializer, we can use it to get the two things I listed above (convenience and runtime efficiency), while still allowing an init function to fail (i.e. to return nil). This can happen, as others have noted, by calling into Objective-C API, but it can also happen directly from code you might choose to write. Here's an example:
class A {
init!() {
return nil // something happens that causes init to fail
}
}
var a:A! = A() // variable 'a' *is* an optional, and also nil
if a != nil { // and we can test it!
print( "a is not nil" )
} else {
print( "a is nil, better not use it." )
}
In this example, I gave myself a way to fail the initialization of class A, and yes, could as easily have done it with an init? method, but when I create an object of type A I'll probably only ever need to test that the initialization succeeded or failed once--after all, I either created an A or I didn't--and afterwards if it's not nil I'll just want to use the direct value. So in this case, using the init!-failable initializer turns out to be pretty handy.
It makes a difference in two situations:
If you write
let x: myclass = myclass(...)
then init? will not compile because init? returns an optional; init! will compile but crash if the init method returns nil.
If you write
let x = myclass(...)
then it will compile in either case, and it will not crash in either case. The difference is that in one case x has type myclass? and in the other case type myclass! with the obvious differences in behaviour.
If you write one of the following two:
let x: myclass? = myclass(...)
let x: myclass! = myclass(...)
then it doesn't matter whether init! or init? was used, because either can be assigned to an optional without crashing.
The init initializer is the same like the constructor for classes in other languages.
It sets initial values and performs some initial Operations (like checking wether a value is to big etc.).
Interesting: It also takes Parameters and can be overloaded.
Example:
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
So when when you call the struct it returns different values depending on your call parameters.
For more info: http://www.informit.com/articles/article.aspx?p=2246797
I've seen a lot of discussion regarding variables in Swift that are declared as var a: String? and var a: String! the former being an optional variable of type String and the latter being implicitly unwrapped optional String. From my understanding, when something is implicitly unwrapped there's an assumption being made that there's a value already included in the optional value. In order to use the syntax a!.toInt() there would have to be an outside check like so:
if a != nil {
a!.toInt()
}
As a side note, it seems better practice to just declare variables as an optional type and then use optional chaining to unwrap the value if it exists. Doing:
if let numberString = a?.toInt() {
numberString.toInt()
}
Is there a scenario in where accessing a variable like a!.toInt() should ever be used in practical applications? To me, it seems like you'd be asking for runtime errors.
Now for the actual question. I was looking through the documentation, specifically enumerateObjectsUsingBlock on NSArray and the block parameter is declared using an !. Does this mean that the writers of that function are assuming that the block parameter will be non-nil? If so, inside that function, what is the semantic difference between:
func someMethodWithBlock(block:((String!)-> Void)!) {
var a = "Hello"
block.(a) //first syntax example
block?.(a)//2nd
block!.(a)//3rd
}
Implicitly Unwrapped Optionals are used almost everywhere in the Cocoa APIs as they are imported into Swift — this is to maintain compatibility with the kind of pointer semantics that are ubiquitous in Obj-C, without requiring !s and ?s all over the place. That's why the NSArray method's block takes a String! argument.
In Swift, regular Optionals (Int?, etc.) are largely preferable for the reasons you specified: they are less prone to errors. Implicitly Unwrapped Optionals are mostly meant to be used only in certain cases, like when you need to pass self to a function before initialization is complete. (If you know a variable is not nil, unwrapping it like a!.toInt() is just fine. The danger with IUOs is that it would be written a.toInt(), and to a reader this looks completely safe, when in reality it's not.)