剖析RAC中的@weakify、@strongify

来源:https://www.cnblogs.com/xuzb/archive/2018/04/18/8872006.html
-Advertisement-
Play Games

需要:pod 'YYKit' 在block語句塊中,如果需引用self,而self對象中又持有block對象,就會造成迴圈引用迴圈引用(retain cycle),導致記憶體泄露,比如以下代碼 一般我們是這麼解決的,使用一個__weal修飾的weakSelf變數指向self對象,在block中使用we ...


需要:pod 'YYKit'

 

在block語句塊中,如果需引用self,而self對象中又持有block對象,就會造成迴圈引用迴圈引用(retain cycle),導致記憶體泄露,比如以下代碼

self.block = ^{

        [self description];
    };

一般我們是這麼解決的,使用一個__weal修飾的weakSelf變數指向self對象,在block中使用weakSelf:

 __weak typeof(self) weakSelf = self;
    self.block = ^{
[weakSelf description]; };

但是醬紫寫,還是可能出問題,因為weakSelf是弱引用,而self一旦釋放了,weakSelf可能為nil,還是舉個慄子吧:
先定義一個TestObj對象,他的屬性有一個block對象

@interface TestObj : NSObject@property (nonatomic, copy)void(^block)();@end@implementation TestObj- (void)dealloc {
    NSLog(@"%s",__func__);}- (instancetype)init {
    self = [super init];
    if (self) {

        __weak typeof(self) weakSelf = self;
        self.block = ^{
            dispatch_async(dispatch_get_global_queue(0, 0), ^{
                [NSThread sleepForTimeInterval:1];
                NSLog(@"%@",weakSelf);
            });
        };
    }
    return self;
}

@end

執行testFunc方法,結果是列印的是(null),因為block里列印的方法是非同步執行的,在 NSLog(@"%@",weakSelf);這句代碼執行之前testFunc函數就結束,所以obj對象已經被release了。
怎麼解決呢?所以再對weakSelf做一次 __strong就可以了:

__weak typeof(self) weakSelf = self;
        self.block = ^{

            __strong typeof(weakSelf) strongSelf = weakSelf;
            dispatch_async(dispatch_get_global_queue(0, 0), ^{

                [NSThread sleepForTimeInterval:1];
                NSLog(@"%@",strongSelf);
            });
        };
}

使用了__strongstrongSelf變數作用域結束之前,對weakSelf有一個引用,防止對象(self)提前被釋放。而作用域一過,strongSelf不存在了,對象(self)也會被釋放。

前面的寫法雖然嚴謹了,也解決了問題了,但是作為喜歡偷懶的程式猿,會不會覺得很啰嗦?每次都要寫那兩條長長的__weak__strong,而且在block里用到的self的全部要改成strongSelf,假設把一段很多self的代碼拷貝到block里,一個個改成strongSelf是不是很蛋疼?

只要在block外用了@weakify(self);然後再block里寫@strongify(self);就可以了,@strongify(self);語句後的的self可以原封不動,好像很神奇,下麵一起看看@weakify、@strongify 這兩個神奇的巨集最終替換了什麼東西。
導入RAC的頭文件,把上面的測試代碼替換成RAC中用的@weakify(self);和@strongify(self), 分屏顯示Xcode,讓右側的顯示內容改為 preprocess“,就可以看到巨集最終替換的結果。 

 

再比如:

     @weakify(self);
        _topView.block = ^(NSInteger tag) {
            
            @strongify(self);
            
            CGPoint point = CGPointMake(tag * SCREEN_WIDTH, self.scrollView.contentOffset.y);
            [self.scrollView setContentOffset:point animated:YES];
        };

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HttpTool.h HttpTool.m ...
  • JSON相比XML最顯著的優點是不需要使用重量級的解析庫,因為其本身就是面向數據的,而且非常容易轉換成哈希字典。除此之外,JSON文檔相比同樣的XML文檔更小。在網路寬頻有限的情況下,你很容易在Iphone中證明這一點。而且這一點對於iPhone來講尤為重要。一般用JSON文檔傳送相同的數據會比用X ...
  • 通常從伺服器端獲取的圖片是URL地址,如果簡單地通過URL地址獲取圖片? 有一個開源項目:SmartImageView,做到了這個功能,同時還有其他功能,下載不便,過於龐大 這裡自己實現它的這個簡單功能 代碼: 兩個重載方法: 1:明確URL地址正確、不會失誤,直接調用 2:防止圖片URL出錯,設置 ...
  • 第一種: 用CADisplayLink可以實現不停重繪。 - (CADisplayLink *)link { if (!_link) { // 創建定時器,一秒鐘調用rotation方法60次 _link = [CADisplayLink displayLinkWithTarget:self sel ...
  • 效果圖如下: 二級列表附有點擊事件。 1、佈局文件: 此處加了一個自定義的導航RelativeLayout,記得註activity的時候添加 android:theme="@style/Theme.AppCompat.Light.NoActionBar" 去掉自帶的導航。 2、一級列表佈局: 3、二 ...
  • 參考高通文檔: 80 NL239 4_F_PMIC_SW_Driver_Overview_MSM8916.pdf DTS文檔: android\kernel\Documentation\devicetree\bindings\batterydata\batterydata.txt 項目數據節點需要的 ...
  • 在網上看到幾篇不錯的博客,分享和學習一下! Android使用WebView載入網頁 https://blog.csdn.net/tuke_tuke/article/details/51684254 教你怎麼配置Android的AndroidManifest.xml讓你不用重覆新建項目 https: ...
  • 開發文檔 官方開發文檔 開發IDE 官方工具下載 UI組件 WeUI:是一套同微信原生視覺體驗一致的基礎樣式庫,由微信官方設計團隊為微信內網頁和微信小程式量身設計; ZanUI-WeApp:是有贊移動 Web UI 規範 ZanUI 的小程式現實版本,結合了微信的視覺規範 MinUI:是基於微信小程 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...