iOS——記一次block的循環(huán)引用

最近在做的小項目出現(xiàn)了一個問題。當(dāng)presentViewController時內(nèi)存上升(在debug navigator下觀察),dissmissViewController時竟然沒有下降。我第一反應(yīng)就是哪里出現(xiàn)循環(huán)引用了。于是我手工遍歷一遍代碼,還好代碼量不是太多,很快就找到問題的根源。

下文的block其實就是swift中的closure閉包,兩者非常想想。

問題描述:

有時候為了減少重復(fù)代碼,我們會將重復(fù)的代碼抽取出去放在一個函數(shù)里面,然后根據(jù)不同參數(shù)來調(diào)用該函數(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的原理就是一個結(jié)構(gòu)體,像函數(shù)傳參這種一般都是傳sureBlock的結(jié)構(gòu)體指針。在使用屬性的時候,swift允許我們不加self,所以customAlerView是被self引用到的。而只要這個sureBlock里面有對self的強引用,將sureBlock賦值給customAlerView.sureBlock的話就會造成循環(huán)易用。所以說,抽代碼要小心吶。

再看看editAccountBook這個函數(shù)被調(diào)用的地方,一開始我是這么寫的

    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)

當(dāng)時覺得這個block是臨時生成的,里面雖然引用到self,應(yīng)該也沒什么關(guān)系。殊不知這個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的省略寫法,當(dāng)函數(shù)最后一個參數(shù)是block時,可以將整個block移到函數(shù)的末尾??梢钥吹竭@里使用了[weak self],這一句會將selfwrap成一個optional,所以在使用的時候得unwrap。其中的if let strongSelf = self就是unwrap??吹竭@里,用Objc開發(fā)的同學(xué)應(yīng)該很熟悉了,在ARC下block的寫法和swift里的思想都是一模一樣的,格式有點不同罷了。

自己寫的總結(jié),方便以后查看。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 《Objective-C高級編程》這本書就講了三個東西:自動引用計數(shù)、block、GCD,偏向于從原理上對這些內(nèi)容...
    WeiHing閱讀 10,100評論 10 69
  • 此人畫渣 第一次畫萌物 第一次使用馬克筆 學(xué)習(xí)之余的畫 一做完作業(yè)立刻提起畫筆,以此釋放我的壓力 第一次畫框 對于...
    萌萌噠喵喵醬閱讀 406評論 3 1
  • 很多人工作了好些年,一直得不到升遷,看著資歷比自己低的已經(jīng)位居高位了,心中難免有怨氣,天天在抱怨:老子拼死拼活干得...
    趣昂閱讀 416評論 0 1
  • 2016年國慶,90后的我裸辭了,帶著兩身衣服回到家。做短暫的啃老族,中旬奔赴另一個城市從事其他的行業(yè)崗位。 現(xiàn)在...
    木筱菱閱讀 611評論 0 0

友情鏈接更多精彩內(nèi)容