Latest web development tutorials

Swift tectonic processes

Construction process is to use an instance of a class, structure, or enumeration type carried out the preparation process. This process involves setting initial values ​​for each attribute and the instance for the preparation and implementation of the necessary initialization tasks.

Swift constructor init () method.

And Objective-C in different constructor, the constructor Swift does not need to return a value, their main task is to ensure that the new instance is completed before the first use proper initialization.

Class instances may be defined destructor (deinitializer) memory cleanup work before class instance is released.


The initial assignment of the storage-type property

Classes and structures when an instance is created, it must set appropriate initial value for all storage-type attributes.

When storing property assignment in the constructor, their values ​​are set directly and does not trigger any property observer.

Storage property assignment process in the constructor:

  • Creating the initial value.

  • In the attribute definition specifies the default property values.

  • Initializes an instance, and calls the init () method.


Constructor

The constructor is called when you create a new instance of a particular type. Its simplest form is similar to an instance method without any parameters, the keyword init name.

grammar

init()
{
    // 实例化后执行的代码
}

Examples

The following structure defines the init a constructor with no arguments, and inside the storage type attribute length and breadth of the initialization value of 6 and 12:

struct rectangle {
    var length: Double
    var breadth: Double
    init() {
        length = 6
        breadth = 12
    }
}
var area = rectangle()
print("矩形面积为 \(area.length*area.breadth)")

The above program execution output is:

矩形面积为 72.0

Default property values

We can set the initial values ​​for the storage-type property in the constructor; Also, can set a default value when a property declaration.

It allows you to use the default constructor cleaner, clearer, and can automatically inferred by the default value type attribute.

The following example we want to set the default value when a property declaration:

struct rectangle {
	// 设置默认值
    var length = 6
    var breadth = 12
}
var area = rectangle()
print("矩形的面积为 \(area.length*area.breadth)")

The above program execution output is:

矩形面积为 72

Configuration parameters

You can define the constructor provided the init () constructor parameter, as follows:

struct Rectangle {
    var length: Double
    var breadth: Double
    var area: Double
    
    init(fromLength length: Double, fromBreadth breadth: Double) {
        self.length = length
        self.breadth = breadth
        area = length * breadth
    }
    
    init(fromLeng leng: Double, fromBread bread: Double) {
        self.length = leng
        self.breadth = bread
        area = leng * bread
    }
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("面积为: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("面积为: \(are.area)")

The above program execution output is:

面积为: 72.0
面积为: 432.0

Internal and external parameter name

Functions and methods with the same parameters, structural parameters there are also the name of a parameter in the constructor for internal use and external parameter names used when calling a constructor.

However, the configuration is not as before there is a recognizable name in brackets, like functions and methods. So call the constructor, the constructor is determined mainly by the need to call the constructor parameter names and types.

If you do not provide arguments when you define the constructor external name, Swift will automatically generate a name with the same external internal name for each constructor parameter.

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
    }
}

// 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

print("red 值为: \(magenta.red)")
print("green 值为: \(magenta.green)")
print("blue 值为: \(magenta.blue)")

// 创建一个新的Color实例,通过三种颜色的外部参数名来传值,并调用构造器
let halfGray = Color(white: 0.5)
print("red 值为: \(halfGray.red)")
print("green 值为: \(halfGray.green)")
print("blue 值为: \(halfGray.blue)")

The above program execution output is:

red 值为: 1.0
green 值为: 0.0
blue 值为: 1.0
red 值为: 0.5
green 值为: 0.5
blue 值为: 0.5

No external parameter name

If you do not want to provide external name for a constructor parameter, you can use an underscore _ to describe its external display name.

struct Rectangle {
    var length: Double
    
    init(frombreadth breadth: Double) {
        length = breadth * 10
    }
    
    init(frombre bre: Double) {
        length = bre * 30
    }
    //不提供外部名字
    init(_ area: Double) {
        length = area
    }
}

// 调用不提供外部名字
let rectarea = Rectangle(180.0)
print("面积为: \(rectarea.length)")

// 调用不提供外部名字
let rearea = Rectangle(370.0)
print("面积为: \(rearea.length)")

// 调用不提供外部名字
let recarea = Rectangle(110.0)
print("面积为: \(recarea.length)")

The above program execution output is:

面积为: 180.0
面积为: 370.0
面积为: 110.0

Optional Attributes Type

If your custom type contains a logical argument to allow empty storage-type attributes, you need to define it as an optional Type optional type (optional attribute type).

When storing property declaration is optional, it will be automatically initialized to empty nil.

struct Rectangle {
    var length: Double?
    
    init(frombreadth breadth: Double) {
        length = breadth * 10
    }
    
    init(frombre bre: Double) {
        length = bre * 30
    }
    
    init(_ area: Double) {
        length = area
    }
}

let rectarea = Rectangle(180.0)
print("面积为:\(rectarea.length)")

let rearea = Rectangle(370.0)
print("面积为:\(rearea.length)")

let recarea = Rectangle(110.0)
print("面积为:\(recarea.length)")

The above program execution output is:

面积为:Optional(180.0)
面积为:Optional(370.0)
面积为:Optional(110.0)

Modify Constant Property construction process

Just before the end of the construction process can determine the value of a constant, you can change the value of the constant attributes at any point in the construction process.

For a class instance, its constant attribute can only be defined in its class construction process modifications; can not be changed in a subclass.

Despite the length property is now is a constant, we can still set its value in the constructor of its class:

struct Rectangle {
    let length: Double?
    
    init(frombreadth breadth: Double) {
        length = breadth * 10
    }
    
    init(frombre bre: Double) {
        length = bre * 30
    }
    
    init(_ area: Double) {
        length = area
    }
}

let rectarea = Rectangle(180.0)
print("面积为:\(rectarea.length)")

let rearea = Rectangle(370.0)
print("面积为:\(rearea.length)")

let recarea = Rectangle(110.0)
print("面积为:\(recarea.length)")

The above program execution output is:

面积为:Optional(180.0)
面积为:Optional(370.0)
面积为:Optional(110.0)

The default constructor

The default constructor will simply create all of the property values ​​are set to the default instance:

The following examples, all properties ShoppingListItem class has a default value, and it is not the father of the base class, it will automatically get a can set default values ​​for all properties of the default constructor

class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem()


print("名字为: \(item.name)")
print("数理为: \(item.quantity)")
print("是否付款: \(item.purchased)")

The above program execution output is:

名字为: nil
数理为: 1
是否付款: false

Each member of the constructor structure

If the structure of all storage-type properties provide default values ​​and do not provide their own custom builder, they automatically get each member of a constructor.

When we call to each member of the constructor, by performing traditional values ​​and the members of the same name attribute parameter name to complete the initial assignment of member properties.

The following example defines a structure Rectangle, which contains two attributes length and breadth. Swift can be assigned according to the initial 100.0 of these two properties, 200.0 automatically derive their type Double.

struct Rectangle {
    var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("矩形的面积: \(area.length)")
print("矩形的面积: \(area.breadth)")

Since the two-storage properties have default values, structures Rectangle automatically a member of each constructor init (width: height :). You can use it to create a new instance of Rectangle.

The above program execution output is:

名字为: nil
矩形的面积: 24.0
矩形的面积: 32.0

Value type constructor Agent

Constructor by calling other constructors to complete part of the construction process instance. This process is called structure agent, it can reduce code duplication between multiple constructors.

The following examples, Rect structure called construction process and Point Size of:

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)
    }
}


// origin和size属性都使用定义时的默认值Point(x: 0.0, y: 0.0)和Size(width: 0.0, height: 0.0):
let basicRect = Rect()
print("Size 结构体初始值: \(basicRect.size.width, basicRect.size.height) ")
print("Rect 结构体初始值: \(basicRect.origin.x, basicRect.origin.y) ")

// 将origin和size的参数值赋给对应的存储型属性
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
    size: Size(width: 5.0, height: 5.0))

print("Size 结构体初始值: \(originRect.size.width, originRect.size.height) ")
print("Rect 结构体初始值: \(originRect.origin.x, originRect.origin.y) ")


//先通过center和size的值计算出origin的坐标。
//然后再调用(或代理给)init(origin:size:)构造器来将新的origin和size值赋值到对应的属性中
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
    size: Size(width: 3.0, height: 3.0))

print("Size 结构体初始值: \(centerRect.size.width, centerRect.size.height) ")
print("Rect 结构体初始值: \(centerRect.origin.x, centerRect.origin.y) ")

The above program execution output is:

Size 结构体初始值: (0.0, 0.0) 
Rect 结构体初始值: (0.0, 0.0) 
Size 结构体初始值: (5.0, 5.0) 
Rect 结构体初始值: (2.0, 2.0) 
Size 结构体初始值: (3.0, 3.0) 
Rect 结构体初始值: (2.5, 2.5) 

Constructor proxy rules

Value Type Class Type
It does not support inheritance, so the process is relatively simple structure agent, as other agents they can only constructor to provide itself. You can use self.init reference other constructor belonging to the same type of value in a custom constructor. It can inherit from other classes, which means that class has a responsibility to ensure all of its inherited properties when the storage-type structure can be properly initialized.

Inheritance and construction process of the class

Swift provides two types of class constructor to ensure that all instances of the class-storage properties can be obtained in the initial values, which are specified constructor and convenience constructor.

Specifies the constructor Convenience constructor
The main class constructor Class relatively minor, assisted constructor
All property is initialized class offered up and call the constructor of the parent class based on the parent chain to achieve the initialization of the parent class. You can define convenience constructor to call the same class as specified in the constructor, and provides default values ​​for parameters. You can also define convenience constructor to create an instance of a particular purpose or specific inputs.
Each class must have at least a specified constructor Only when necessary to facilitate the class constructor
Init(parameters) {
    statements
}
convenience init(parameters) {
      statements
}

Specifies the instance constructor

class mainClass {
    var no1 : Int // 局部存储变量
    init(no1 : Int) {
        self.no1 = no1 // 初始化
    }
}
class subClass : mainClass {
    var no2 : Int // 新的子类存储变量
    init(no1 : Int, no2 : Int) {
        self.no2 = no2 // 初始化
        super.init(no1:no1) // 初始化超类
    }
}

let res = mainClass(no1: 10)
let res2 = subClass(no1: 10, no2: 20)

print("res 为: \(res.no1)")
print("res2 为: \(res2.no1)")
print("res2 为: \(res2.no2)")

The above program execution output is:

res 为: 10
res 为: 10
res 为: 20

Examples of convenience constructor

class mainClass {
    var no1 : Int // 局部存储变量
    init(no1 : Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass : mainClass {
    var no2 : Int
    init(no1 : Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 便利方法只需要一个参数
    override convenience init(no1: Int)  {
        self.init(no1:no1, no2:0)
    }
}
let res = mainClass(no1: 20)
let res2 = subClass(no1: 30, no2: 50)

print("res 为: \(res.no1)")
print("res2 为: \(res2.no1)")
print("res2 为: \(res2.no2)")

The above program execution output is:

res 为: 20
res2 为: 30
res2 为: 50

Inheritance and constructor overloading

Swift sub-class does not inherit the default constructor of the parent class.

The constructor of the parent class is inherited only in the case determination and security.

When you override a parent class specified constructor, you need to write an override modifier.

class SuperClass {
    var corners = 4
    var description: String {
        return "\(corners) 边"
    }
}
let rectangle = SuperClass()
print("矩形: \(rectangle.description)")

class SubClass: SuperClass {
    override init() {  //重载构造器
        super.init()
        corners = 5
    }
}

let subClass = SubClass()
print("五角型: \(subClass.description)")

The above program execution output is:

矩形: 4 边
五角型: 5 边

Specifies the constructor and convenience constructors examples

The following example will demonstrate the operation specified in the constructor, constructors and facilitate automatic constructor inheritance.

It contains two classes defined MainClass, SubClass class hierarchy, and demonstrate how their constructors interaction.

class MainClass {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[匿名]")
    }
}
let main = MainClass(name: "w3big")
print("MainClass 名字为: \(main.name)")

let main2 = MainClass()
print("没有对应名字: \(main2.name)")

class SubClass: MainClass {
    var count: Int
    init(name: String, count: Int) {
        self.count = count
        super.init(name: name)
    }
    
    override convenience init(name: String) {
        self.init(name: name, count: 1)
    }
}

let sub = SubClass(name: "w3big")
print("MainClass 名字为: \(sub.name)")

let sub2 = SubClass(name: "w3big", count: 3)
print("count 变量: \(sub2.count)")

The above program execution output is:

MainClass 名字为: w3big
没有对应名字: [匿名]
MainClass 名字为: w3big
count 变量: 3

The class constructor can fail

If a class, object, structure, or enumeration type, it is possible to structure itself in the process fails, the failure to define a constructor.

Variable initialization failed Possible reasons are:

  • Incoming Invalid parameter value.

  • Missing some external resources required.

  • It did not meet certain conditions.

In order to properly handle the case of this configuration process may fail.

You can in a class, or enum type definition of the structure, add one or more failed constructor. The syntax is a question mark after the init keyword Jiatian (init?).

Examples

In the following example, the definition of a structure called Animal, which has named the species, String type attribute constants.

Meanwhile, the structure also defines a with a String type parameter species can fail constructor. The constructor can fail, is used to check whether the argument passed to an empty string, an empty string, the constructor can fail, the failure to build an object, otherwise success.

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

//通过该可失败构造器来构建一个Animal的对象,并检查其构建过程是否成功
// someCreature 的类型是 Animal? 而不是 Animal
let someCreature = Animal(species: "长颈鹿")

// 打印 "动物初始化为长颈鹿"
if let giraffe = someCreature {
    print("动物初始化为\(giraffe.species)")
}

The above program execution output is:

动物初始化为长颈鹿

Enumerated type constructor can fail

You can with one or more parameters can be configured by the constructor failed to get an enumerated type specific enumeration members.

Examples

In the following example, the definition of an enumerated type named TemperatureUnit. Which contains three possible enum member (Kelvin, Celsius, and Fahrenheit) and a failure can be used to find the constructor Character values ​​corresponding enumeration members:

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("这是一个已定义的温度单位,所以初始化成功。")
}

let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
    print("这不是一个已定义的温度单位,所以初始化失败。")
}

The above program execution output is:

这是一个已定义的温度单位,所以初始化成功。
这不是一个已定义的温度单位,所以初始化失败。

The class constructor can fail

Value types (such as structures or enumerated type) may fail constructor, when and where to trigger construction fails without any limitation of this behavior.

However, the class constructor can fail and the agent can only call the constructor among all classes occurred in all class properties are initialized after ignition failure behavior.

Examples

By example, the definition of a class called StudRecord because studname property is a constant, so once StudRecord class constructor success, studname property must have a non-nil value.

class StudRecord {
    let studname: String!
    init?(studname: String) {
        self.studname = studname
        if studname.isEmpty { return nil }
    }
}
if let stname = StudRecord(studname: "失败构造器") {
    print("模块为 \(stname.studname)")
}

The above program execution output is:

模块为 失败构造器

Covering a constructor can fail

Like other constructors, like, you can also override the base class constructor can fail with the subclass constructor can fail.

You can also override by a base class constructor can fail with the failure of non-constructor subclass.

You can use a non-failed constructor covering a constructor can fail, but in turn, it does not work.

A non-failed constructor can never call an agent may fail constructor.

Examples

The following example describes a failure and non-failure Constructor:

class Planet {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[No Planets]")
    }
}
let plName = Planet(name: "Mercury")
print("行星的名字是: \(plName.name)")

let noplName = Planet()
print("没有这个名字的行星: \(noplName.name)")

class planets: Planet {
    var count: Int
    
    init(name: String, count: Int) {
        self.count = count
        super.init(name: name)
    }
    
    override convenience init(name: String) {
        self.init(name: name, count: 1)
    }
}

The above program execution output is:

行星的名字是: Mercury
没有这个名字的行星: [No Planets]

May fail constructor init!

Generally, we add a question mark after the keyword init way (init?) May fail to define a constructor, but you can also use the init by adding an exclamation point after the way to define a failed constructor (init!) . Examples are as follows:

struct StudRecord {
    let stname: String
    
    init!(stname: String) {
        if stname.isEmpty {return nil }
        self.stname = stname
    }
}

let stmark = StudRecord(stname: "w3big")
if let name = stmark {
    print("指定了学生名")
}

let blankname = StudRecord(stname: "")
if blankname == nil {
    print("学生名为空")
}

The above program execution output is:

指定了学生名
学生名为空