Swift 常用的關鍵詞解釋和用法

deinit: 當一個類的實例即將被銷毀時,會調用這個方法。

class Person  
{  
    var name:String  
    var age:Int  
    var gender:String

    deinit  
    {  
        //從堆中釋放,并釋放的資源
    }  
}

extension:允許給已有的類、結構體、枚舉、協議類型,添加新功能。

class Person  
{  
    var name:String = ""  
    var age:Int = 0  
    var gender:String = ""  
}

extension Person  
{  
    func printInfo()  
    {  
        print("My name is \(name), I'm \(age) years old and I'm a \(gender).")  
    }  
}

inout:將一個值傳入函數,并可以被函數修改,然后將值傳回到調用處,來替換初始值。適用于引用類型和值類型。 其實就是聲明參數為指針

func dangerousOp(_ error:inout NSError?)  
{  
    error = NSError(domain: "", code: 0, userInfo: ["":""])  
}

var potentialError:NSError?
dangerousOp(&potentialError)

//代碼運行到這里,potentialError 不再是 nil,而是已經被初始化

internal:訪問控制權限,允許同一個模塊下的所有源文件訪問,如果在不同模塊下則不允許訪問。

public:可以被任何人訪問。但其他 module 中不可以被 override 和繼承,而在 module 內可以被 override 和繼承。

open:訪問控制權限,允許在定義的模塊外也可以訪問源文件里的所有類,并進行子類化。對于類成員,允許在定義的模塊之外訪問和重寫。

open var foo:String? //這個屬性允許在 app 內或 app 外重寫和訪問。在開發(fā)框架的時候,會應用到這個訪問修飾符。

private:訪問控制權限,只允許實體在定義的類以及相同源文件內的 extension 中訪問。

class Person  
{  
    private var jobTitle:String = ""  
}

// 當 extension 和 class 不在同一個源文件時
extension Person  
{
    // 無法編譯通過,只有在同一個源文件下才可以訪問
    func printJobTitle()  
    {  
        print("My job is \(jobTitle)")  
    }  
}

fileprivate:訪問控制權限,只允許在定義源文件中訪問。// 同文件中訪問

class Person  
{  
    fileprivate var jobTitle:String = ""  
}

extension Person  
{
    //當 extension 和 class 在同一個文件中時,允許訪問
    func printJobTitle()  
    {  
        print("My job is (jobTitle)")  
    }  
}

從高到低排序如下:
open > public > interal > fileprivate > private

static:用于定義類方法,在類型本身進行調用。此外還可以定義靜態(tài)成員。

class Person  
{  
    var jobTitle:String?

    static func assignRandomName(_ aPerson:Person)  
    {  
        aPerson.jobTitle = "Some random job"  
    }  
}

let somePerson = Person()  
Person.assignRandomName(somePerson)  
//somePerson.jobTitle 的值是 "Some random job"

在方法的 func 關鍵字之前加上關鍵字 static 或者 class 都可以用于指定類方法.不同的是用class關鍵字指定的類方法可以被子類重寫, 如下:
override class func work() { print("Teacher: University Teacher")}
但是用 static 關鍵字指定的類方法是不能被子類重寫的, 根據報錯信息: Class method overrides a 'final' class method.

我們可以知道被 static 指定的類方法包含 final 關鍵字的特性--防止被重寫.

struct:通用、靈活的結構體,是程序的基礎組成部分,并提供了默認初始化方法。與 class 不同,當 struct 在代碼中被傳遞時,是被拷貝的,并不使用引用計數。除此之外,struct 沒有下面的這些功能:

  • 使用繼承。
  • 運行時的類型轉換。
  • 使用析構方法。

數據類型:struct是值類型,class是引用類型。
值類型變量直接包含數據,賦值時也是值拷貝,或者叫深拷貝,所以多個變量的操作不會相互影響。
引用類型變量存儲的是對數據的引用地址,后者稱為對象,賦值時,是將對象的引用地址復制過去,也叫淺拷貝,因此若多個變量指向同一個對象時,操作會相互影響。
值類型數據沒有引用計數,也就不會因為循環(huán)引用導致內存泄漏,而引用類型存在引用計數,需要小心循環(huán)引用導致的內存泄漏
拷貝時,struct是深拷貝,拷貝的是內容,class則需要選用正確的深淺拷貝類型。

因為值類型數據是深拷貝,所以是線程安全的,而引用類型數據則不是

  • property的初始化:初始化屬性時,class 需要創(chuàng)建一個帶形參的constructor;struct可以把屬性放在默認的constructor 的參數里。
  • immutable變量:swift用var和let區(qū)分可變數據和不可變數據,struct遵循這個特性;對class則不適用。
  • mutating function:struct 的 function 改變 property 時,需加上 mutating,而 class 不用。
  • 速度:struct分配在棧中,class分配在堆中,也就意味著struct更迅速。
  • NSUserDefaults:struct 不能被序列化成 NSData 對象,class可以。
  • 繼承: struct不可以繼承,class可以繼承。
  • swift與oc混合開發(fā)時,oc調用swift需要繼承NSObject,這就導致了class可以繼承,所以可以調用class,但struct不能繼承,所以不能調用struct

typealias:給代碼中已經存在的類,取別名。

typealias JSONDictionary = [String: AnyObject]

func parseJSON(_ deserializedData:JSONDictionary){}

defer:用于在程序離開當前作用域之前,執(zhí)行一段代碼。 // dafer 是倒敘 先加入后執(zhí)行

  • 關閉文件

    func foo() {
      let fileDescriptor = open(url.path, O_EVTONLY)
      defer {
        close(fileDescriptor)
      }
      // use fileDescriptor...
    }
    
  • 加/解鎖:下面是 swift 里類似 Objective-C 的 synchronized block 的一種寫法,可以使用任何一個 NSObject 作 lock

    func foo() {
      objc_sync_enter(lock)
      defer { 
        print("003")  
        objc_sync_exit(lock) 
      }
      defer { 
        print("002")   
      }
      print("001")    
      // do something...
    }
    
defer 的執(zhí)行時機:

defer 的執(zhí)行時機緊接在離開作用域之后,但是是在其他語句之前。這個特性為 defer 帶來了一些很“微妙”的使用方式。比如從 0 開始的自增:

class Foo {
    var num = 0
    func foo() -> Int {
        defer { num += 1 }
        return num
    }
    
    // 沒有 `defer` 的話我們可能要這么寫
    // func foo() -> Int {
    //    num += 1
    //    return num - 1
    // }
}

let f = Foo()
f.foo() // 0
f.foo() // 1
f.num   // 2

fallthrough:顯式地允許從當前 case 跳轉到下一個相鄰 case 繼續(xù)執(zhí)行代碼。

let box = 1

switch box  
{  
    case 0:  
    print("Box equals 0")  
    fallthrough  
    case 1:  
    print("Box equals 0 or 1")  
    default:  
    print("Box doesn't equal 0 or 1")  
    // Box equals 0 和 Box equals 0 or 1  都執(zhí)行了
}

guard:當有一個以上的條件不滿足要求時,將離開當前作用域。同時還提供解包可選類型的功能。

private func printRecordFromLastName(userLastName: String?)
{  
    guard let name = userLastName, name != "Null" else  
    {  
        //userLastName = "Null",需要提前退出
        return  
    }
    //繼續(xù)執(zhí)行代碼
    print(dataStore.findByLastName(name))  
}

1.guard關鍵字必須使用在函數中。
2.guard關鍵字必須和else同時出現。
3.guard關鍵字只有條件為false的時候才能走else語句 相反執(zhí)行后邊語句。

repeat:在使用循環(huán)的判斷條件之前,先執(zhí)行一次循環(huán)中的代碼。類似于 do while 循環(huán)

repeat
{
print("Always executes at least once before the condition is considered")
}
while 1 > 2

where:要求關聯類型必須遵守特定協議,或者類型參數和關聯類型必須保持一致。也可以用于在 case 中提供額外條件,用于滿足控制表達式。

  • 增加判斷條件
for i in 0…3 where i % 2 == 0  
{  
    print(i) //打印 0 和 2  
}
  • 協議使用where, 只有基類實現了當前協議才能添加擴展。 換個說法, 多個類實現了同一個協議,該語法根據類名分別為這些類添加擴展, 注意是分別(以類名區(qū)分)!!!
protocol SomeProtocol {
    func someMethod()
}
class A: SomeProtocol {
    let a = 1
       func someMethod() {
       print("call someMethod")
    }
}
class B {
    let a = 2
}
//基類A繼承了SomeProtocol協議才能添加擴展
extension SomeProtocol where Self: A {
    func showParamA() {
        print(self.a)
    }
}
//反例,不符合where條件
extension SomeProtocol where Self: B {
    func showParamA() {
        print(self.a)
    }
}
let objA = A()
let objB = B()  //類B沒實現SomeProtocol, 所有沒有協議方法
objA.showParamA()  //輸出1

as:類型轉換運算符,用于嘗試將值轉成其它類型。

  • as : 數值類型轉換

    let age = 28 as Int
    let money = 20 as CGFloat
    let cost = (50 / 2) as Double
    
    switch person1 { 
    case let person1 as Student: 
        print("是Student類型,打印學生成績單...") 
    case let person1 as Teacher: 
        print("是Teacher類型,打印老師工資單...") 
    default: break
    }
    
  • as!:向下轉型(Downcasting)時使用。由于是強制類型轉換,如果轉換失敗會報 runtime 運行錯誤。

    let a = 13 as! String
    print(a)
    //會crash
    
    let a = 13 as? String
    print(a)
    //輸出為nil
    

is:類型檢查運算符,用于確定實例是否為某個子類類型。

class Person {}  
class Programmer : Person {}  
class Nurse : Person {}

let people = [Programmer(), Nurse()]

for aPerson in people  
{  
    if aPerson is Programmer  
    {  
        print("This person is a dev")  
    }  
    else if aPerson is Nurse  
    {  
        print("This person is a nurse")  
    }  
}

nil:在 Swift 中表示任意類型的無狀態(tài)值。

Swift的nil和OC中的nil不一樣.在OC中,nil是一個指向不存在對象的指針.而在Swift中,nil不是指針,它是一個不確定的值.用來表示值缺失.任何類型的optional都可以被設置為nil. 而在OC中,基本數據類型和結構體是不能被設置為nil的. 給optional的常量或者變量賦值為nil.來表示他們的值缺失情況.一個optional常量或者變量如果在初始化的時候沒有被賦值,他們自動會設置成nil.

class Person{}  
struct Place{}

//任何 Swift 類型或實例可以為 nil
var statelessPerson:Person? = nil  
var statelessPlace:Place? = nil  
var statelessInt:Int? = nil  
var statelessString:String? = nil

super:在子類中,暴露父類的方法、屬性、下標。

class Person  
{  
    func printName()  
    {  
        print("Printing a name. ")  
    }  
}

class Programmer : Person  
{  
    override func printName()  
    {  
        super.printName()  
        print("Hello World!")  
    }  
}

let aDev = Programmer()  
aDev.printName() //打印 Printing a name. Hello World!

self:任何類型的實例都擁有的隱式屬性,等同于實例本身。此外還可以用于區(qū)分函數參數和成員屬性名稱相同的情況。

class Person  
{  
    func printSelf()  
    {  
        print("This is me: \(self)")  
    }  
}

let aPerson = Person()  
aPerson.printSelf() //打印 "This is me: Person"

Self:在協議中,表示遵守當前協議的實體類型。

protocol Printable  
{  
    func printTypeTwice(otherMe:Self)  
}

struct Foo : Printable  
{  
    func printTypeTwice(otherMe: Foo)  
    {  
        print("I am me plus \(otherMe)")  
    }  
}

let aFoo = Foo()  
let anotherFoo = Foo()

aFoo.printTypeTwice(otherMe: anotherFoo) //打印 I am me plus Foo()

_:用于匹配或省略任意值的通配符。

for _ in 0..<3  
{  
    print("Just loop 3 times, index has no meaning")  
}

另外一種用法:

let _ = Singleton() //忽略不使用的變量

convenience:

在 Swift 中,為保證安全性,init 方法只能調用一次,且在 init 完成后,保證所有非 Optional 的屬性都已經被初始化。

每個類都有指定的初始化方法:designated initializer,這些初始化方法是子類必須調用的,為的就是保證父類的屬性都初始化完成了。

而如果不想實現父類的 designated initializer,可以添加 convenience 關鍵字,自己實現初始化邏輯。
convenience 初始化不能調用父類的初始化方法,只能調用同一個類中的 designated initializer。
由于 convenience 初始化不安全,所以 Swift 不允許 convenience initializer 被子類重寫,限制其作用范圍。

class People {
    var name: String
    init(name: String) {
        self.name = name
    }
}

通過extension給原有的People類增加init方法:

// 使用convenience增加init方法
extension People {
    convenience init(smallName: String) {
        self.init(name: smallName)
    }
}

接下來,Student類繼承父類People

class Student: People {
    var grade: Int
    
    init(name: String, grade: Int) {
        self.grade = grade
        super.init(name: name)
        // 無法調用
        // super.init(smallName: name)
    }
    
    // 可以被重寫 
    override init(name: String) {
        grade = 1
        super.init(name: name)
    }
    
    // 無法重寫,編譯不通過
    override init(smallName: String) {
        grade = 1
        super.init(smallName: smallName)
    }
}

子類對象調用父類的convenience的init方法:只要在子類中實現重寫了父類convenience方法所需要的init方法的話,我們在子類中就可以使用父類的convenience初始化方法了

class People {
    
    var name: String
    
    init(name: String) {
        self.name = name
    }
}
// 使用convenience增加init方法
extension People {
    convenience init(smallName: String) {
        self.init(name: smallName)
    }
}


// 子類
class Teacher: People {
    
    var course: String
    
    init(name: String, course: String) {
        self.course = course
        super.init(name: name)
    }
    
    override init(name: String) {
        self.course = "math"
        super.init(name: name)
    }
}

// 調用convenience的init方法
let xiaoming = Teacher(smallName: "xiaoming")
  • 總結:子類的designated初始化方法必須調用父類的designated方法,以保證父類也完成初始化。

required

對于某些我們希望子類中一定實現的designated初始化方法,我們可以通過添加required關鍵字進行限制,強制子類對這個方法重寫。
required修飾符的使用規(guī)則:

  • required修飾符只能用于修飾類初始化方法。
  • 當子類含有異于父類的初始化方法時(初始化方法參數類型和數量異于父類),子類必須要實現父類的required初始化方法,并且也要使用required修飾符而不是override。
  • 當子類沒有初始化方法時,可以不用實現父類的required初始化方法。
    class MyClass {
        var str:String
        required init(str:String) {
            self.str = str
        }
    }
    class MySubClass:MyClass
    {
        init(i:Int) {
            super.init(str:String(i))
        }
        
    }
    // 編譯錯誤
    MySubClass(i: 123)

會報錯,因為你沒有實現父類中必須實現的方法。正確的寫法:

    class MyClass {
        var str:String
        required init(str:String) {
            self.str = str
        }
    }
    class MySubClass:MyClass
    {
        init(i:Int) {
            super.init(str:String(i))
        }
        required init(str: String) {
            fatalError("init(str:) has not been implemented")
        }
    }
    // 編譯錯誤
    MySubClass(i: 123)

從上面的代碼中,不難看出子類需要添加異于父類的初始化方法,必須要重寫有required的修飾符的初始化方法,并且也要使用required修飾符而不是override,請千萬注意!

如果子類中并沒有不同于父類的初始化方法,Swift會默認使用父類的初始化方法:

class MyClass{
    var str: String?
    required init(str: String?) {
        self.str = str
    }
}
class MySubClass: MyClass{
}
var MySubClass(str: "hello swift")

在這種情況下,編譯器不會報錯,因為如果子類沒有任何初始化方法時,Swift會默認使用父類的初始化方法。

以#開頭的關鍵字

#available:基于平臺參數,通過 if,while,guard 語句的條件,在運行時檢查 API 的可用性。

if #available(iOS 10, *)  
{  
    print("iOS 10 APIs are available")  
}

#colorLiteral:在 playground 中使用的字面表達式,用于創(chuàng)建顏色選取器,選取后賦值給變量。

let aColor = #colorLiteral //創(chuàng)建顏色選取器

#column:一種特殊的字面量表達式,用于獲取字面量表示式的起始列數。

class Person  
{  
    func printInfo()  
    {  
        print("Some person info - on column \(#column)")
    }  
}

let aPerson = Person()  
aPerson.printInfo() //Some person info - on column 47

#function:特殊字面量表達式,返回函數名稱。在方法中,返回方法名。在屬性的 getter 或者 setter 中,返回屬性名。在特殊的成員中,比如 init 或 subscript 中,返回關鍵字名稱。在文件的最頂層時,返回當前所在模塊名稱。

class Person
{
    func printInfo()
    {
        print("Some person info - inside function \(#function)")
    }
}

let aPerson = Person()
aPerson.printInfo() //Some person info - inside function printInfo()

#line:特殊字面量表達式,用于獲取當前代碼的行數。

class Person  
{  
    func printInfo()  
    {  
        print("Some person info - on line number \(#line)")
    }  
}

let aPerson = Person()  
aPerson.printInfo() //Some person info - on line number 5

#selector:用于創(chuàng)建 Objective-C selector 的表達式,可以靜態(tài)檢查方法是否存在,并暴露給 Objective-C。

//靜態(tài)檢查,確保 doAnObjCMethod 方法存在  
control.sendAction(#selector(doAnObjCMethod), to: target, forEvent: event)

dynamic && @objc

@objc

OC 是基于運行時,遵循了 KVC 和動態(tài)派發(fā),而 Swift 為了追求性能,在編譯時就已經確定,而不需要在運行時的,在 Swift 類型文件中,為了解決這個問題,需要暴露給 OC 使用的任何地方(類,屬性,方法等)的生命前面加上 @objc 修飾符
如果用 Swift 寫的 class 是繼承 NSObject 的話, Swift 會默認自動為所有非 private 的類和成員加上@objc

在Swift中,我們在給button添加點擊事件時,對應的點擊事件的觸發(fā)方法就需要用@objc來修飾

dynamic

Swift 中的函數可以是靜態(tài)調用,靜態(tài)調用會更快。當函數是靜態(tài)調用的時候,就不能從字符串查找到對應的方法地址了。這樣 Swift 跟 Objective-C 交互時,Objective-C 動態(tài)查找方法地址,就有可能找不到 Swift 中定義的方法。

這樣就需要在 Swift 中添加一個提示關鍵字,告訴編譯器這個方法是可能被動態(tài)調用的,需要將其添加到查找表中。這個就是關鍵字 dynamic 的作用。

didSet

屬性觀察者,當值存儲到屬性后馬上調用。

var data = [1,2,3]  
{  
    didSet  
    {  
        tableView.reloadData()  
    }  
}

final

防止方法、屬性、下標被重寫。

final class Person {}  
class Programmer : Person {} //編譯錯誤
 

get

返回成員的值。還可以用在計算型屬性上,間接獲取其它屬性的值。

class Person  
{  
    var name:String  
    {  
        get { return self.name }  
        set { self.name = newValue}  
    }
 
    var indirectSetName:String  
    {  
        get  
        {  
            if let aFullTitle = self.fullTitle  
            {  
                return aFullTitle  
            }  
            return ""  
        }
 
        set (newTitle)  
        {  
            //如果沒有定義 newTitle,可以使用 newValue
            self.fullTitle = "(self.name) :(newTitle)"  
        }
    }  
}
 

infix

指明一個用于兩個值之間的運算符。如果一個全新的全局運算符被定義為 infix,還需要指定優(yōu)先級。

let twoIntsAdded = 2 + 3
 

indirect

指明在枚舉類型中,存在成員使用相同枚舉類型的實例作為關聯值的情況。

indirect enum Entertainment  
{  
    case eventType(String)  
    case oneEvent(Entertainment)  
    case twoEvents(Entertainment, Entertainment)  
}
 
let dinner = Entertainment.eventType("Dinner")  
let movie = Entertainment.eventType("Movie")
 
let dateNight = Entertainment.twoEvents(dinner, movie)
 

lazy

指明屬性的初始值,直到第一次被使用時,才進行初始化。

class Person  
{  
    lazy var personalityTraits = {  
        //昂貴的數據庫開銷  
        return ["Nice", "Funny"]  
    }()  
}
let aPerson = Person()  
aPerson.personalityTraits //當 personalityTraits 首次被訪問時,數據庫才開始工作

left

指明運算符的結合性是從左到右。在沒有使用大括號時,可以用于正確判斷同一優(yōu)先級運算符的執(zhí)行順序。

//"-" 運算符的結合性是從左到右
10-2-4 //根據結合性,可以看做 (10-2) - 4
 

mutating

允許在方法中修改結構體或者枚舉實例的屬性值。

struct Person  
{  
    var job = ""
 
    mutating func assignJob(newJob:String)  
    {  
        self = Person(job: newJob)  
    }  
}
 
var aPerson = Person()  
aPerson.job //""
 
aPerson.assignJob(newJob: "iOS Engineer at Buffer")  
aPerson.job //iOS Engineer at Buffer
 

none

是一個沒有結合性的運算符。不允許這樣的運算符相鄰出現。

//"<" 是非結合性的運算符
1 < 2 < 3 //編譯失敗
 

nonmutating

指明成員的 setter 方法不會修改實例的值,但可能會有其它后果。

enum Paygrade  
{  
    case Junior, Middle, Senior, Master
 
    var experiencePay:String?  
    {  
        get  
        {  
            database.payForGrade(String(describing:self))  
        }
 
        nonmutating set  
        {  
            if let newPay = newValue  
            {  
                database.editPayForGrade(String(describing:self), newSalary:newPay)  
            }  
        }  
    }  
}
 
let currentPay = Paygrade.Middle
 
//將 Middle pay 更新為 45k, 但不會修改 experiencePay 值
currentPay.experiencePay = "$45,000"

optional

用于指明協議中的可選方法。遵守該協議的實體類可以不實現這個方法。

@objc protocol Foo  
{  
    func requiredFunction()  
    @objc optional func optionalFunction()  
}
 
class Person : Foo  
{  
    func requiredFunction()  
    {  
        print("Conformance is now valid")  
    }  
}

override

指明子類會提供自定義實現,覆蓋父類的實例方法、類型方法、實例屬性、類型屬性、下標。如果沒有實現,則會直接繼承自父類。

class Person  
{  
    func printInfo()  
    {  
        print("I'm just a person!")  
    }  
}
 
class Programmer : Person  
{  
    override func printInfo()  
    {  
        print("I'm a person who is a dev!")  
    }  
}
 
let aPerson = Person()  
let aDev = Programmer()
 
aPerson.printInfo() //打印 I'm just a person!  
aDev.printInfo() //打印 I'm a person who is a dev!

postfix

位于值后面的運算符。

var optionalStr:String? = "Optional"  
print(optionalStr!)

precedence

指明某個運算符的優(yōu)先級高于別的運算符,從而被優(yōu)先使用。

infix operator ~ { associativity right precedence 140 }  
4 ~ 8

prefix

位于值前面的運算符。

var anInt = 2  
anInt = -anInt //anInt 等于 -2
 

required

確保編譯器會檢查該類的所有子類,全部實現了指定的構造器方法。

class Person  
{  
    var name:String?
 
    required init(_ name:String)  
    {  
        self.name = name  
    }  
}
 
class Programmer : Person  
{  
    //如果不實現這個方法,編譯不會通過
    required init(_ name: String)  
    {  
        super.init(name)  
    }  
}

right

指明運算符的結合性是從右到左的。在沒有使用大括號時,可以用于正確判斷同一優(yōu)先級運算符的順序。

//"??" 運算符結合性是從右到左
var box:Int?  
var sol:Int? = 2
 
let foo:Int = box ?? sol ?? 0 //Foo 等于 2
 

set

通過獲取的新值來設置成員的值。同樣可以用于計算型屬性來間接設置其它屬性。如果計算型屬性的 setter 沒有定義新值的名稱,可以使用默認的 newValue。

class Person  
{  
    var name:String  
    {  
        get { return self.name }  
        set { self.name = newValue}  
    }
 
    var indirectSetName:String  
    {  
        get  
        {  
            if let aFullTitle = self.fullTitle  
            {  
                return aFullTitle  
            }  
            return ""  
        }
 
        set (newTitle)  
        {  
            //如果沒有定義 newTitle,可以使用 newValue
            self.fullTitle = "(self.name) :(newTitle)"  
        }  
    }  
}
 

Type

表示任意類型的類型,包括類類型、結構類型、枚舉類型、協議類型。

class Person {}  
class Programmer : Person {}
 
let aDev:Programmer.Type = Programmer.self

unowned

讓循環(huán)引用中的實例 A 不要強引用實例 B。前提條件是實例 B 的生命周期要長于 A 實例。

class Person  
{  
    var occupation:Job?  
}
 
//當 Person 實例不存在時,job 也不會存在。job 的生命周期取決于持有它的 Person。
class Job  
{  
    unowned let employee:Person
 
    init(with employee:Person)  
    {  
        self.employee = employee  
    }  
}

weak

允許循環(huán)引用中的實例 A 弱引用實例 B ,而不是強引用。實例 B 的生命周期更短,并會被先釋放。

class Person  
{  
    var residence:House?  
}
 
class House  
{  
    weak var occupant:Person?  
}
 
var me:Person? = Person()  
var myHome:House? = House()
 
me!.residence = myHome  
myHome!.occupant = me
 
me = nil  
myHome!.occupant // myHome 等于 nil
 

willSet

屬性觀察者,在值存儲到屬性之前調用。

class Person  
{  
    var name:String?  
    {  
        willSet(newValue) {print("I've got a new name, it's (newValue)!")}  
    }  
}
 
let aPerson = Person()  
aPerson.name = "Jordan" //在賦值之前,打印 "I've got a new name, it's Jordan!"

原文地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372