What is the name of variable ending in = {} () Swift? - swift

I have been digging through the Swift documentation trying to find the name of the Swift syntax below.
static let taskDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
I do not know what to call this syntax. I am confused by the = {} () component. What is this called?

It's code that generates the default DateFormatter value for the taskDateFormat property.
As per the Swift manual (emphasis mine):
https://docs.swift.org/swift-book/LanguageGuide/Initialization.html
Setting a Default Property Value with a Closure or Function
If a stored property’s default value requires some customization or setup, you can use a closure or global function to provide a customized default value for that property. Whenever a new instance of the type that the property belongs to is initialized, the closure or function is called, and its return value is assigned as the property’s default value.
Note that the closure’s end curly brace is followed by an empty pair of parentheses. This tells Swift to execute the closure immediately. If you omit these parentheses, you are trying to assign the closure itself to the property, and not the return value of the closure.
Basically the code pre-initializes the taskDateFormat property to a new DateFormatter object and sets the dateStyle property before the taskDateFormat property is set.

The syntax = {}() means a block (a.k.a closure) , it can return anything.
Since your variable is DateFormatter Type, it will expect a DateFormatter instance being returned from the block.
That Type on the variable is mandatory, you can have a hint on it if you remove the variable Type, you will get the error:
Unable to infer complex closure return type; add explicit type to disambiguate

Related

What is the advantage of closure stored property Initialisation?

What is the difference and the advantages/disadvantages of this code when initialising a property of a class as:
1.
let menuBar:MenuBar = {
let mb = MenuBar()
return mb
}()
and:
2.
let menuBar = MenuBar()
Both of the code snippets declare and initialize stored properties, but in the first one it is initialized by closure. The reason why you should set a stored property with a closure is: there is a requirement(s) to do customization (calling a method for instance); Adapted from The Swift Programming Language (Swift 4.1) - Initialization: Setting a Default Property Value with a Closure or Function:
If a stored property’s default value requires some customization or
setup, you can use a closure or global function to provide a
customized default value for that property. Whenever a new instance of
the type that the property belongs to is initialized, the closure or
function is called, and its return value is assigned as the property’s
default value.
Which means that you would be able to do:
let menuBar:MenuBar = {
let mb = MenuBar()
// for example, you'd need to call "doSomething" method
// before returning the instance:
menuBar.doSomething()
return mb
}()
Note that in the body of the stored property closure, you would be not able to able to use the other properties in your class/struct since they considered as not being initialized yet. Example:
struct MyType {
let myString = "My String!"
let myInt: Int = {
let anInt = 101
// this won't work
print(myString)
return anInt
}()
}
The result of the above code snippet is getting a compile-time error:
error: instance member 'myString' cannot be used on type 'MyType'
print(myString)
Furthermore at some point, it would be recommended to declare your property as lazy:
lazy var menuBar:MenuBar = {
let mb = MenuBar()
// for example, you'd need to call "doSomething" method
// before returning the instance:
menuBar.doSomething()
return mb
}()
Means that:
A lazy stored property is a property whose initial value is not
calculated until the first time it is used. You indicate a lazy stored
property by writing the lazy modifier before its declaration.

Use value of variable for property lookup

I am trying to build a table of current locale properties in code, and have encountered issues with trying to pass the value of a variable to a function:
let currentLocale = Locale(identifier: "en_US")
let calendar1 = currentLocale.calendar // "gregorian (fixed)"
let propertyName = "calendar"
let calendar2 = currentLocale.propertyName // Error: Value of type 'Locale' has no member 'porpertyName'
In the last line of code above, the instance of Locale thinks I am passing it "propertyName" rather than the contents of the variable "calendar".
Is there any way to pass the value of propertyName ("calendar") to the instance of Locale? I know that in other languages, you can prepend the variable name like '$propertyName', and that tells it to read the value of the variable.
I want to keep this pure Swift if possible.
You are looking for some form of key-value coding.
It's a little tricky, in that this is a purely Objective-C feature of Cocoa, so it doesn't work with the Swift overlay class Locale; you will have to cast currentLocale to Objective-C NSLocale. Moreover, NSLocale exposes its attributes through special NSLocale.Key types. After a great deal of casting, I find that this works:
let calendar2 =
(currentLocale as NSLocale).object(forKey:NSLocale.Key(rawValue:propertyName))
calendar2 is typed as Any but you can cast it down to a String.

Why doesn't Swift allow setting value of an optional constant after object initialization?

The code below creates a compile error saying "error: return from initializer without initializing all stored properties ('self.response' not initialized)"
class Question {
let text: String
let response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
I want to make "response" constant and by the time I initialize, response will be unknown. Besides "return from initializer without initializing all stored properties", why do I have to make it "var"?
Because Swift tries to make you implement safe code, and having uninitialized stored properties is really not safe, because you or a client of your class may use that constant before it is properly set and the result will be undefined. This is a cause of a lot of bugs that may not be immediately caught.
Moreover, because an optional constant stored property is initialized as having a nil value, if you were able to change its value after initialization you would violate the "constantness" of your constant. That is why you need to declare it as a var.
Optional variables / properties are automatically set to nil by definition if no initial value is provided in the declaration line.
An optional constant is stuck to nil which makes no sense...
Therefore the compiler doesn't let you declare an optional constant this way.

Printing &self in swift, cannot assign to immutable value of type

This is just an exercise in pointers in swift, but I was trying to write a function that would print the pointer to self, but I kept getting an error "cannot assign to immutable value of type C". Is this something that is even possible in Swift?
class C {
static var c = C()
var a = 1
func printMyPointer() {
printPointer(&self) //cannot assign to immutable value of type C
}
func printPointer(ptr:UnsafePointer<C>) {
print(ptr)
}
}
C.c.printMyPointer()
As already explained in the other answer, you cannot pass a constant
as the argument for an in-out parameter. As a workaround, you can
pass an array, as this will actually pass the address of the first
element:
func printMyPointer() {
printPointer([self])
}
But even simpler, use unsafeAddressOf():
func printMyPointer() {
print(unsafeAddressOf(self))
}
Update for Swift 3: As of Xcode 8 beta 6, unsafeAddressOf
does not exist anymore. You can convert self to a pointer:
print(Unmanaged.passUnretained(self).toOpaque())
or
print(unsafeBitCast(self, to: UnsafeRawPointer.self))
From the Swift Docs:
You can only pass a variable as the argument for an in-out parameter. You cannot pass a constant or a literal value as the argument, because constants and literals cannot be modified. You place an ampersand (&) directly before a variable’s name when you pass it as an argument to an inout parameter, to indicate that it can be modified by the function.
Since self is immutable, you can't pass it as an inout parameter. Even though the method signature dosen't use inout, Swift treats pointer parameters like inout, according to the Swift blog:
Swift allows pointer parameters to be treated like inout parameters, so you can pass a reference to a var as a pointer argument by using the same & syntax.

Class instance variable initialization order?

Currently, I am seeing something strange behavior.
class DataManager1
{
let THE_ID = "SOME_ID_STRING"
let _con1 = CKContainer(identifier: THE_ID) // error
// error: 'DataManager1.Type' does not have a member named 'THE_ID'
}
class DataManager2
{
let THE_ID = "SOME_ID_STRING"
let _con1:CKContainer?
init()
{
_con1 = CKContainer(identifier: THE_ID) // no error.
}
}
In C++ we have a defined initialization order between instance member variables. I expected something similar, but actually I couldn't find a mention for that form the manual.
Does Swift has a defined initialization order of properties? If it does, what is the rule, and where can I find the rule?
This is due to the fact that you're using a Closure (a Function is just a special case of Closure that is unnamed) to initialize the _con1 property with a default value.
From the Apple provided iBook:
If you use a closure to initialize a property, remember that the rest
of the instance has not yet been initialized at the point that the
closure is executed. This means that you cannot access any other
property values from within your closure, even if those properties
have default values. You also cannot use the implicit self property,
or call any of the instance’s methods.
Even though the note above refers specifically to closures, it seems that trying to set the default value for a property to be that of another property directly also does not work.