//ARC机制会跟踪每一个实例正在被多少属性,常量和变量所引用,只要这个实例的引用数不为0,那么这个实例就不会被销毁。那么它的deinit也不会被调用 //实例之间的循环引用是怎么发生的。如果消除循环引用导致内存泄露 class Person { let name : String init (name : String) { self.name = name println("\(name) is being initialized") } deinit { println("\(name) is being deinitialized") } } var reference1:Person? var reference2:Person? var reference3:Person? reference1 = Person(name: "John Appleseed") reference2 = reference1 reference3 = reference1 reference1 = nil reference2 = nil reference3 = nil } func swiftARCMethodTwo() { //Strong Reference Cycles Between Class Instances class Person { let name : String init (name : String){ self.name = name } var apartment: Apartment? deinit { // apartment = nil; println("\(name) is being deinitialized") } } class Apartment{ let number : Int init (number : Int){ self.number = number } weak var tenant : Person? deinit { // tenant = nil; println("Apartment #\(number) is being deinitialized") } } //上2个类分别都有另一个类的optional类型的变量。结果就是互相持有对方 //在ARC中,当把John和number73都赋值为nil时,看似断了2个引用,但在实例中,还有apartment和tenant2个引用没断,于是,把释放写入deinit中 //deinit并不会被调用。因为ARC中只有引用计数到0时,deinit才会被调用 //为了解决上面的循环引用,引入了关键字weak var john : Person? var number73 : Apartment? john = Person(name: "John Appleseed") number73 = Apartment(number: 73) john!.apartment = number73 number73!.tenant = john // john number73 // \strong \strong // name:John Appleseed --->strong number:73 // apartmen<Apartment 实例> <---weak tenant:<Person 实例> //引入了weak引用不会阻止ARC回收实例,也就是说,一个实例,如果没有被强引用,再多的引用持有它的话,它依然可以被释放。 //无主引用,Unowned References //weak是给optional类型用的(!?),而unowned是给非可选型用的 class Customer{ let name :String var card : CreditCard? init (name : String){ self.name = name } deinit { println("\(name) is being deinitialized") } } class CreditCard{ let number : UInt64 unowned let customer : Customer // weak var customer : Customer? init (number : UInt64 , customer : Customer){ self.number = number self.customer = customer } deinit { println("Card #\(number) is being deinitialized") } } var johnOne : Customer? johnOne = Customer(name: "John Appleseed") johnOne!.card = CreditCard(number: 1234_5678_9012_3456, customer: johnOne!) //闭包导致的循环强引用,Strong Reference Cycles for Closures /* class HTMLElement{ let name: String let text: String? //闭包 lazy var asHTML: () -> String = { // [unowned self] in if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { println("\(name) is being deinitialized") } } */
//析构过程是构造过程的逆向过程,当一个类的实例被释放的时候,在内存中消失前,析构器会被调用 //swift通过ARC管理内存。 //由于swift是ARC管理内存,所以析构过程已经不是那么重要了 class MyClass{ var myNum = 0 init (){ myNum = 1 } deinit { myNum = 0 println("myNum \(myNum)") } } var myClass = MyClass() println("myClass.myNum = \(myClass.myNum)") // myClass = nil //Deinitializers in Action struct Bank { //在银行的金币数 static var coinsInBank = 10_000 //出售金币 static func vendCoins(var numberOfCoinsToVend:Int)->Int{ println("numberOfCoinsToVend = \(numberOfCoinsToVend)") println("coinsInBank = \(coinsInBank)") numberOfCoinsToVend = min(numberOfCoinsToVend, coinsInBank) println("numberOfCoinsToVend = \(numberOfCoinsToVend)") coinsInBank -= numberOfCoinsToVend return numberOfCoinsToVend } //收到金币 static func receiveCoins(coins:Int){ coinsInBank += coins } } class Player{ //硬币钱包 var coinsInPurse : Int //初始化 init (coins: Int){ coinsInPurse = Bank.vendCoins(coins) println("Player.init.coinsInPurse = \(coinsInPurse)") } //赢得的钱币 func winCoins(coins:Int){ coinsInPurse += Bank.vendCoins(coins) } //析构过程 deinit{ Bank.receiveCoins(coinsInPurse) } } //生成一个player,初始化银行出售金币100枚 var playerOne : Player? = Player(coins:100) println("A new player has joined the game with \(playerOne!.coinsInPurse) coins") // prints "A new player has joined the game with 100 coins" println("There are now \(Bank.coinsInBank) coins left in the bank") // 银行剩余9900 coins playerOne!.winCoins(2_000) println("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins") //赢了2000枚,加上前面的100枚 println("The bank now only has \(Bank.coinsInBank) coins left")//银行剩余7900 playerOne = nil println("The bank now only has \(Bank.coinsInBank) coins left")//银行剩余10000枚
//下标语法,Subscript Syntax //读写型 /* subscript(index:Int) -> Int { get { // return an appropriate subscript value here } set(newValue) { // perform a suitable setting action here } } */
//实例方法,Instance Methods //swift会为方法的第一个参数只提供函数内部使用的名字,从第二个参数开始,既可以外部用,也可以内部用 class CsjClass{ var myNum : Int = 0 func increaseNum(base:Int, numberOfTimes:Int){ myNum += base * numberOfTimes } } var csjClass = CsjClass() //第二个参数开始,会自动提供一个外部使用变量名 csjClass.increaseNum(10, numberOfTimes: 8)//******
//func想为外部提供一个变量名的话有2种做法 //func csjFunc(value paramA:Int){......} //value是给外部使用的名字,paramA是内部使用 //func csjFunc(#paramA:Int) {......} //paramA 既是外部用的,也是内部用的 //csjClass类的实例方法中,相当于,从第二个参数开始,swift自动为我们提供了"#"的功能,不需要我们写# class NewCsjClass{ var myNum : Int = 0 //"_ "这样swift就不再会自动提供外部使用名字了 func increaseNum(base:Int, _ numberOfTimes:Int){ myNum += base * numberOfTimes } } var newCsjClass = NewCsjClass() newCsjClass.increaseNum(10, 8)//******
//self属性,The self Property //每个实例,都有一个属性用于表示它自己这个实例,这个属性叫做self class CSJSedClass { var num : Int = 0 //传入参数名叫num,设置属性也叫num的时候,到底是传入的值,还是实例的属性,我们为实例属性前面加了self,表示这个是实例自己的属性 func setNume(num:Int){ self.num = num } }
//变化(修改)方法,修改值类型的实例方法,Modifying Value Types from Within Instance Methods //上述都是class的情况,对于struct,enum这样的值传递类型,却不能使用实例方法来改变属性的值 struct CSJPoint{ var x = 0, y = 0 mutating func moveByXY(deltaX: Int, y deltaY:Int){ x += deltaX y += deltaY } } var csjPoint = CSJPoint() csjPoint.moveByXY(3, y: 4) println("x:\(csjPoint.x),y:\(csjPoint.y)") //在struct,enum里使用mutating关键字,达到class里一样的效果 //如果x,y是let就不能使用,不能改变常量
//在mutating方法中,给self赋值 struct CSJTwoPoint{ var x = 0 ,y = 0 mutating func changeSelf(deltaX:Int, y deltaY:Int){ self = CSJTwoPoint(x:deltaX,y:deltaY) } } var csjTwoPoint = CSJTwoPoint() csjTwoPoint.changeSelf(3,y:4) println("x:\(csjTwoPoint.x),y:\(csjTwoPoint.y)") //达到了改变csjTwoPoint中x和y的目的,给self赋值的方法,却是生成了一个新的CSJTwoPoint实例(内部做了内存释放工作) enum CSJStateMachine{ case None,Init,Run,Deinit //实例方法 mutating func nextState(){ switchself{ case None:self = Init case Init:self = Run case Run:self = Deinit case Deinit:self = None } } } var csjStateMachine = CSJStateMachine.None csjStateMachine.nextState() //self变成Init println(csjStateMachine == CSJStateMachine.Init)//ture csjStateMachine.nextState() println(csjStateMachine == CSJStateMachine.Run)//ture //状态机的状态切换代码可以直接写在enum的定义中
//类型方法,Type Methods //上面地方都是实例方法,它们都是针对某一个实例进行操作的,而类方法,是对这个类型的。(static和class) class TestClass{ class var computedProperty : Int { return0 } class func someMethod(){ //这才是一个类方法 } } //因为类里面的类型属性只能用于计算,不能保存数据,所以类的类方法,暂时不适合写一个可以跑起来的例子,应该结合struct或者enum,才可以写 struct LevelTracker{//等级跟踪器 static var highestUnlockedLevel = 1//类型属性,所有的实例共用这个值 //类方法 static func unlockLevel(level: Int){ if level > highestUnlockedLevel{ highestUnlockedLevel = level } } //类方法 static func levelIsUnlocked(level : Int) -> Bool{ return level <= highestUnlockedLevel } var currentLevel = 1 mutating func advanceToLevel(level:Int) ->Bool{ if LevelTracker.levelIsUnlocked(level){ currentLevel = level returntrue }else{ returnfalse } } }
class Player { var tracker = LevelTracker() let playName : String func completedLevel(level:Int){ LevelTracker.unlockLevel(level+1)//调用结构体类方法 tracker.advanceToLevel(level+1) //调用了tracker的实例advanceToLevel } init(name:String){ playName = name } } var player = Player(name:"World") player.completedLevel(1)//调用后 tarcker的highestUnlockedLevel变成2 println("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
var player2 = Player(name:"Kitty") if player2.tracker.advanceToLevel(6){ println("player is not on level 6") }else{ println("level 6 has not yet been unlocked") }