最近在做的小項目出現(xiàn)了一個問題瞧捌。當presentViewController時內存上升(在debug navigator下觀察)闽寡,dissmissViewController時竟然沒有下降筋夏。我第一反應就是哪里出現(xiàn)循環(huán)引用了。于是我手工遍歷一遍代碼团驱,還好代碼量不是太多构订,很快就找到問題的根源蕾羊。
下文的block其實就是swift中的closure閉包,兩者非常想想帽驯。
問題描述:
有時候為了減少重復代碼龟再,我們會將重復的代碼抽取出去放在一個函數(shù)里面,然后根據(jù)不同參數(shù)來調用該函數(shù)尼变。
func editAccountBook(item:AccountBookBtn?, indexPath:NSIndexPath, sureBlock:(String, String)->Void){
customAlertView.title = item?.btnTitle ?? ""
customAlertView.initChooseImage = item?.backgrountImageName ?? "book_cover_0"
customAlertView.cancelBlock = {[weak self] in
if let strongSelf = self{
strongSelf.customAlertView.removeFromSuperview()
}
}
customAlertView.sureBlock = sureBlock
UIApplication.sharedApplication().keyWindow?.addSubview(self.customAlertView)
}
比如上面這個函數(shù)利凑,目光集中在倒數(shù)第二行的sureBlock,這個sureBlock是外部傳進來的嫌术。我們知道Block的原理就是一個結構體哀澈,像函數(shù)傳參這種一般都是傳sureBlock的結構體指針。在使用屬性的時候度气,swift允許我們不加self割按,所以customAlerView是被self引用到的。而只要這個sureBlock里面有對self的強引用磷籍,將sureBlock賦值給customAlerView.sureBlock的話就會造成循環(huán)易用适荣。所以說现柠,抽代碼要小心吶。
再看看editAccountBook這個函數(shù)被調用的地方弛矛,一開始我是這么寫的
let block:(String,String)->Void = {(title, imageName) in
//建一個數(shù)據(jù)庫
let currentTime = Int(NSDate().timeIntervalSince1970)
let dbName = customAccountName + "\(currentTime)" + ".db"
let item = AccountBookBtn(title: title, count: "0筆", image: imageName, flag: false, dbName: dbName)
//插入賬本
self.mainVCModel.addBookItemByAppend(item)
self.mainView.accountBookBtnView.insertItemsAtIndexPaths([indexPath])
//退出alertview
self.customAlertView.removeFromSuperview()
}
editAccountBook(nil, indexPath: indexPath, sureBlock: block)
當時覺得這個block是臨時生成的够吩,里面雖然引用到self,應該也沒什么關系丈氓。殊不知這個block在傳給editAccountBook這個函數(shù)的時候就間接地被self引用到了周循,所以就造成了循環(huán)引用。所以用block真是要特別小心万俗。特別是一些自己寫的函數(shù)湾笛。
解決辦法
解決辦法很簡單,在block的開頭加一些list就好该编。如下
editAccountBook(nil, indexPath: indexPath){[weak self](title, imageName) in
if let strongSelf = self{
//建一個數(shù)據(jù)庫
let currentTime = Int(NSDate().timeIntervalSince1970)
let dbName = customAccountName + "\(currentTime)" + ".db"
let item = AccountBookBtn(title: title, count: "0筆", image: imageName, flag: false, dbName: dbName)
//插入賬本
strongSelf.mainVCModel.addBookItemByAppend(item)
strongSelf.mainView.accountBookBtnView.insertItemsAtIndexPaths([indexPath])
//退出alertview
strongSelf.customAlertView.removeFromSuperview()
}
}
這里用了swift的省略寫法迄本,當函數(shù)最后一個參數(shù)是block時,可以將整個block移到函數(shù)的末尾课竣〖问辏可以看到這里使用了[weak self],這一句會將selfwrap成一個optional于樟,所以在使用的時候得unwrap公条。其中的if let strongSelf = self就是unwrap∮厍看到這里靶橱,用Objc開發(fā)的同學應該很熟悉了,在ARC下block的寫法和swift里的思想都是一模一樣的路捧,格式有點不同罷了关霸。
自己寫的總結,方便以后查看杰扫。