Initialization
Apple Official document initialization
Apple document Chinese translation initialization
Class, struct, enumeration, the process of preparing an instance, called initialization . This process requires the initializer to ensure that the new instance is initialized correctly the first time it is used.
Set initialization values for storage properties
When you create an instance, you must set an initial value for the storage property, or assign a default property value.
Initialization device
When you create an instance of a specific type, the initializer is called. Use the init keyword.
init() { // perform some initialization here}
struct Fahrenheit { var temperature: Double init() { temperature = 32.0 }}var f = Fahrenheit()print("The default temperature is \(f.temperature)° Fahrenheit")// prints "The temperature is 32.0° Fahrenheit"
The default property value
The above example is abbreviated as:
struct Fahrenheit { var temperature = 32.0}
Custom initialization
Input parameters and optional types, which are assigned constant properties when the initialization process is defined or initialized.
Initialize formal parameters
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)// boilingPointOfWater.temperatureInCelsius is 100.0let freezingPointOfWater = Celsius(fromKelvin: 273.15)// freezingPointOfWater.temperatureInCelsius is 0.0
Formal parameter name and actual parameter name label
The parameter name and type of the initializer, which is important when the initializer is distinguished. If not, Swift is automatically provided.
struct Color { let red, green, blue: Double init(red: Double, green: Double, blue: Double) { self.red = red self.green = green self.blue = blue } init(white: Double) { red = white green = white blue = white }}let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)let halfGray = Color(white: 0.5)let veryGreen = Color(0.0, 1.0, 0.0)// this reports a compile-time error - external names are required
Initializer form parameter (no actual parameter label)
Do not want to write the actual parameter label, you can use the underscore _ instead.
struct Celsius { var temperatureInCelsius: Double init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32.0) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } init(_ celsius: Double) { temperatureInCelsius = celsius }}let bodyTemperature = Celsius(37.0)// bodyTemperature.temperatureInCelsius is 37.0
Optional attribute Types
The optional type attribute, automatically initialized to nil, indicates that the initialization was deliberately set to "no value yet."
class SurveyQuestion { var text: String var response: String? init(text: String) { self.text = text } func ask() { print(text) }}let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")cheeseQuestion.ask()// prints "Do you like cheese?"cheeseQuestion.response = "Yes, I do like cheese."
Assigning constant properties in initialization
In initialization, assigns a value to a constant property, guaranteeing that there is a definite value at the end of initialization.
For an instance, in initialization, the constant property can only be modified by the referenced class and cannot be modified by the quilt class.
class SurveyQuestion { let text: String var response: String? init(text: String) { self.text = text } func ask() { print(text) }}let beetsQuestion = SurveyQuestion(text: "How about beets?")beetsQuestion.ask()// prints "How about beets?"beetsQuestion.response = "I also like beets. (But not with cheese.)"
Default initializer
The initializer is not provided, and Swift provides a default initializer for all properties.
class ShoppingListItem { var name: String? var quantity = 1 var purchased = false}var item = ShoppingListItem()
Member initializers for struct types
If no custom initializers are defined in the struct, the member initializer is automatically obtained.
The struct accepts the member initializer even if the storage property does not have a default value.
struct Size { var width = 0.0, height = 0.0}let twoByTwo = Size(width: 2.0, height: 2.0)
Initializer delegates for value types
The initializer invokes a different initializer to perform the initialization of the partial instance, the initializer delegate .
Value type, when writing its own custom initializer, use self.init to refer to other initializers from the same value type. And can only be used in the initializer.
Write the custom initializer in the extension, and let the custom value type use the default initializer initialization, initialization of the member initializer, and custom initializer initialization.
struct Size { var width = 0.0, height = 0.0}struct Point { var x = 0.0, y = 0.0}struct Rect { var origin = Point() var size = Size() init() {} init(origin: Point, size: Size) { self.origin = origin self.size = size } init(center: Point, size: Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origin: Point(x: originX, y: originY), size: size) }}let basicRect = Rect()// basicRect‘s origin is (0.0, 0.0) and its size is (0.0, 0.0)let originRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0))// originRect‘s origin is (2.0, 2.0) and its size is (5.0, 5.0)let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))// centerRect‘s origin is (2.5, 2.5) and its size is (3.0, 3.0)
Inheritance and initialization of classes
Swift defines two types of initializers for class types to ensure that all storage properties receive an initial value.
Specifying initializers and convenient initializers
Specifies that the initializer is the primary initializer for the class, initializes all of the class reference properties, and invokes the parent class initializer. Usually there is only one class.
A handy initializer is a secondary initializer that supports an initializer for a class.
Specifying initializers and convenient initializer syntax
Specify the initializer:
init(parameters) { statements}
Handy initializer, with convenience modifier:
convenience init(parameters) { statements}
Initializer delegates for class types
Simple memory, the rules are as follows:
- Specifies that the initializer must always be delegated upward.
- A convenient initializer must always be a horizontal delegate.
Consult the documentation in detail.
Two-segment initialization
The first stage, the storage attribute introduces the class, assigns the initial value, the initial state determines.
The second stage is to customize its storage properties before the new instance is used.
Detailed explanations, and security checks, see the documentation
initializer inheritance and overrides
The subclass initializer can be overridden when the parent class specifies the initializer, using the override modifier. It is not necessary to write when matching the convenient initializer of the parent class.
class Vehicle { var numberOfWheels = 0 var description: String { return "\(numberOfWheels) wheel(s)" }}let vehicle = Vehicle()print("Vehicle: \(vehicle。description)")// Vehicle: 0 wheel(s)class Bicycle: Vehicle { override init() { super.init() numberOfWheels = 2 }}let bicycle = Bicycle()print("Bicycle: \(bicycle.description)")// Bicycle: 2 wheel(s)
Subclasses cannot modify inherited constant properties.
Inheritance of automatic initializers
If the new attribute introduced by the subclass has a default value,
- Rule one, the subclass does not define any of the specified initializers, and automatically inherits all the specified initializers of the parent class.
- In rule two, the subclass provides all the parent classes that specify the implementation of the initializer. Automatically inherits all the handy initializers of the parent class.
class Food { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[Unnamed]") }}let namedMeat = Food(name: "Bacon")// namedMeat‘s name is "Bacon"let mysteryMeat = Food()// mysteryMeat‘s name is "[Unnamed]"
class RecipeIngredient: Food { var quantity: Int init(name: String, quantity: Int) { self.quantity = quantity super.init(name: name) } override convenience init(name: String) { self.init(name: name, quantity: 1) }}let oneMysteryItem = RecipeIngredient()let oneBacon = RecipeIngredient(name: "Bacon")let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)
class ShoppingListItem: RecipeIngredient { var purchased = false var description: String { var output = "\(quantity) x \(name)" output += purchased ? " ?" : " ?" return output }}var breakfastList = [ ShoppingListItem(), ShoppingListItem(name: "Bacon"), ShoppingListItem(name: "Eggs", quantity: 6),]breakfastList[0].name = "Orange juice"breakfastList[0].purchased = truefor item in breakfastList { print(item.description)}// 1 x Orange juice ?// 1 x Bacon ?// 6 x Eggs ?
Fail-able initializer
Define a failed initializer and add a question mark after the INIT keyword?
struct Animal { let species: String init?(species: String) { if species.isEmpty { return nil } self.species = species }}let someCreature = Animal(species: "Giraffe")// someCreature is of type Animal?, not Animal if let giraffe = someCreature { print("An animal was initialized with a species of \(giraffe.species)")}// prints "An animal was initialized with a species of Giraffe"let anonymousCreature = Animal(species: "")// anonymousCreature is of type Animal?, not Animal if anonymousCreature == nil { print("The anonymous creature could not be initialized")}// prints "The anonymous creature could not be initialized"
Enumeration of failed initializers
enum TemperatureUnit { case Kelvin, Celsius, Fahrenheit init?(symbol: Character) { switch symbol { case "K": self = .Kelvin case "C": self = .Celsius case "F": self = .Fahrenheit default: return nil } }}let fahrenheitUnit = TemperatureUnit(symbol: "F")if fahrenheitUnit != nil { print("This is a defined temperature unit, so initialization succeeded.")}// prints "This is a defined temperature unit, so initialization succeeded." let unknownUnit = TemperatureUnit(symbol: "X")if unknownUnit == nil { print("This is not a defined temperature unit, so initialization failed.")}// prints "This is not a defined temperature unit, so initialization failed."
A failed initializer with an enumeration with raw values
An enumeration with the original value automatically obtains a failed initializer
enum TemperatureUnit: Character { case Kelvin = "K", Celsius = "C", Fahrenheit = "F"} let fahrenheitUnit = TemperatureUnit(rawValue: "F")if fahrenheitUnit != nil { print("This is a defined temperature unit, so initialization succeeded.")}// prints "This is a defined temperature unit, so initialization succeeded." let unknownUnit = TemperatureUnit(rawValue: "X")if unknownUnit == nil { print("This is not a defined temperature unit, so initialization failed.")}// prints "This is not a defined temperature unit, so initialization failed."
Failed to initialize delivery
A horizontal delegate to the same class, struct, or another failed initializer in an enumeration.
class Product { let name: String init?(name: String) { if name.isEmpty { return nil } self.name = name }} class CartItem: Product { let quantity: Int init?(name: String, quantity: Int) { if quantity < 1 { return nil } self.quantity = quantity super.init(name: name) }}if let twoSocks = CartItem(name: "sock", quantity: 2) { print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")}// prints "Item: sock, quantity: 2"if let zeroShirts = CartItem(name: "shirt", quantity: 0) { print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")} else { print("Unable to initialize zero shirts")}// prints "Unable to initialize zero shirts"
Override can fail initializer
Overriding the parent class with a non-writable initializer for a subclass can fail the initializer, and the only way to delegate up to the parent class initializer is to force the expansion of the parent class to fail the initializer result.
class Document { var name: String? // this initializer creates a document with a nil name value init() {} // this initializer creates a document with a non-empty name value init?(name: String) { self.name = name if name.isEmpty { return nil } }}class AutomaticallyNamedDocument: Document { override init() { super.init() self.name = "[Untitled]" } override init(name: String) { super.init() if name.isEmpty { self.name = "[Untitled]" } else { self.name = name } }}class UntitledDocument: Document { override init() { super.init(name: "[Untitled]")! }}
can fail initializer init!
You can use the fail initializer to create an implicitly-expanded optional instance with the appropriate type.
Add an exclamation point (init!) after Init can be associated with init? Or init to each other delegate invocation.
Necessary initializers
The initializer is added before the required modifier, and all such subclasses must implement the initializer.
class SomeClass { required init() { // initializer implementation goes here }}
The subclass must also add the required modifier When overriding the necessary initializer for the parent class.
class SomeSubclass: SomeClass { required init() { // subclass implementation of the required initializer goes here }}
Setting default values for properties by closures and functions
When an instance of this attribute is initialized, the closure or function is called, and its return value is used as the default value for the property.
class SomeClass { let someProperty: SomeType = { // create a default value for someProperty inside this closure // someValue must be of the same type as SomeType return someValue }()}
Note that the end of the parentheses does not have a parameter, and the closure is executed immediately. You cannot read other property values within a closure, you cannot use the implicit Self property, or you can invoke an instance method.
struct Chessboard { let boardColors: [Bool] = { var temporaryBoard = [Bool]() var isBlack = false for i in 1...8 { for j in 1...8 { temporaryBoard.append(isBlack) isBlack = !isBlack } isBlack = !isBlack } return temporaryBoard }() func squareIsBlackAt(row: Int, column: Int) -> Bool { return boardColors[(row * 8) + column] }}let board = Chessboard()print(board.squareIsBlackAt(row: 0, column: 1))// Prints "true"print(board.squareIsBlackAt(row: 7, column: 7))// Prints "false"
SWIFT4 initialization, document code.