iOS循環(huán)引用深入理解

循環(huán)引用也就是引用之后造成的一個循環(huán)用圖理解吧


image.png

下面是可能造成循環(huán)引用的幾種情況

1.協(xié)議代理

都知道協(xié)議的代理對象都用weak修飾,哪為何不用strong,或者copy呢掌测?答案是會造成循環(huán)引用。下面就用代碼解釋吧

#import <Foundation/Foundation.h>
//協(xié)議
@protocol TestToolDelegate <NSObject>
- (void)protacolTest:(NSString *)string;
@end

@interface TestTool : NSObject
//使用strong會造成循環(huán)引用
@property (nonatomic,strong)id <TestToolDelegate> delegate;
@end

上面是聲明的協(xié)議,下面是一個類對象瘫镇,類對象里強引用了delegate對象
下面來看下TestTool的使用

@interface ViewController ()<TestToolDelegate>
@property (nonatomic,strong)TestTool *tool;
@end
@implementation ViewController1

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tool = [[TestTool alloc]init];
//    1協(xié)議強引用
    self.tool.delegate = self;
}
- (void)protacolTest:(NSString *)string{
    NSLog(@"%@",string);
}

@property (nonatomic,strong)id <TestToolDelegate> delegate;
如果使用strong修飾則會造成循環(huán)引用
所以我們使用weak修飾
@property (nonatomic,weak)id <TestToolDelegate> delegate;


image.png
2.Block

和協(xié)議代理的解釋也類似,Block是如何造成循環(huán)引用的呢
請看如下代碼

#import <Foundation/Foundation.h>

typedef void(^MyBlock)(NSString *string);

@interface TestTool : NSObject
@property (nonatomic,copy) MyBlock block;

- (void)testBlock:(void(^)(NSString *string))block;
@end
#import "TestTool.h"

@implementation TestTool
- (void)testBlock:(void (^)(NSString *))block{
//      如果不將block賦給self.block的話是不會造成循環(huán)引用的芹壕,可在有的情況下block不在此方法中傳值汇四,所以就需要賦值了。
        self.block = block;
//      做完一些事后block返回數(shù)據(jù)
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            dispatch_sync(dispatch_get_main_queue(), ^{
                block(@"測試block");
            });
        });
}
@end
@interface ViewController ()<TestToolDelegate>
@property (nonatomic,strong)TestTool *tool;
@end
@implementation ViewController1

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tool = [[TestTool alloc]init];
    [self.tool testBlock:^(NSString *string) {
        NSLog(@"%@",string);
//     如果此時直接使用self的話踢涌,就會造成循環(huán)引用
        self.view.backgroundColor = [UIColor whiteColor];
    }];
}

正確的使用方法是用weak修飾self通孽;

@interface ViewController ()<TestToolDelegate>
@property (nonatomic,strong)TestTool *tool;
@end
@implementation ViewController1

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tool = [[TestTool alloc]init];
    __weak typeof(self) weakSelf = self;
    [self.tool testBlock:^(NSString *string) {
        NSLog(@"%@",string);
//     如果此時直接使用self的話,就會造成循環(huán)引用
        weakSelf.view.backgroundColor = [UIColor whiteColor];
    }];
}

還是用圖理解一下吧


image.png
3.兩個類之間的循環(huán)引用

一個類是ViewController睁壁,一個類是TestTool. ViewController中先強引用了TestTool對象背苦,然后TestTool中也強引用了一個對象ViewController.這樣就造成了循環(huán)引用。

#import <Foundation/Foundation.h>
@interface TestTool : NSObject
@property (nonatomic,strong) id ID;
@end
@interface ViewController ()
@property (nonatomic,strong)TestTool *tool;
@end
@implementation ViewController1
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tool = [[TestTool alloc]init];
    self.tool.ID = self;
}

圖解


image.png
4.定時器NSTimer
@interface ViewController ()
@property (nonatomic,strong) NSTimer *timer;
@end
@implementation ViewController1
- (void)viewDidLoad {
    [super viewDidLoad];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:weakSelf selector:@selector(timerClick) userInfo:nil repeats:YES];
}
- (void)timerClick{
    NSLog(@"我在重復");
}
//是否調(diào)用dealloc方法潘明,沒有則造成了循環(huán)引用
- (void)dealloc {
    NSLog(@"ViewController被銷毀了");
    [self.timer invalidate];
}

開啟定時器以后, timerClick方法會一直執(zhí)行,即使dismiss此控制器以后,也是一直在打印,而且dealloc方法不會執(zhí)行.很明顯這是循環(huán)引用造成了內(nèi)存泄露,控制器不會被釋放.


image.png

解決辦法:由于循環(huán)引用的起因是target,則可以包裝一個target,讓target是另一個對象,而不是ViewController即可行剂,其實NSTimer有一個類方法是Block創(chuàng)建的,親測不會造成循環(huán)引用

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        weakSelf.view.backgroundColor = [UIColor yellowColor];
    }];
}
image.png

代碼示例

備注:

如果有不足或者錯誤的地方還望各位讀者批評指正钳降,可以評論留言厚宰,筆者收到后第一時間回復。

QQ/微信:976971956/ljh976971956遂填。

簡書號:超級卡布達

感謝各位觀眾老爺?shù)拈喿x铲觉,如果覺得筆者寫的還湊合,可以關(guān)注或收藏一下吓坚,不定期分享一些好玩的實用的demo給大家撵幽。

文/超級卡布達(簡書作者)

著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)礁击,并標注“簡書作者”盐杂。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哆窿,隨后出現(xiàn)的幾起案子链烈,更是在濱河造成了極大的恐慌,老刑警劉巖更耻,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件测垛,死亡現(xiàn)場離奇詭異,居然都是意外死亡秧均,警方通過查閱死者的電腦和手機食侮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門号涯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锯七,你說我怎么就攤上這事链快。” “怎么了眉尸?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵域蜗,是天一觀的道長。 經(jīng)常有香客問我噪猾,道長霉祸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任袱蜡,我火速辦了婚禮丝蹭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坪蚁。我一直安慰自己奔穿,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布敏晤。 她就那樣靜靜地躺著贱田,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘴脾。 梳的紋絲不亂的頭發(fā)上男摧,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音译打,去河邊找鬼彩倚。 笑死,一個胖子當著我的面吹牛扶平,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔬蕊,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼结澄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了岸夯?” 一聲冷哼從身側(cè)響起麻献,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猜扮,沒想到半個月后勉吻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡旅赢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年齿桃,在試婚紗的時候發(fā)現(xiàn)自己被綠了惑惶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡短纵,死狀恐怖带污,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情香到,我是刑警寧澤鱼冀,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站悠就,受9級特大地震影響千绪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梗脾,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一荸型、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧藐唠,春花似錦帆疟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妈嘹,卻和暖如春柳琢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背润脸。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工柬脸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毙驯。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓倒堕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爆价。 傳聞我的和親對象是個殘疾皇子垦巴,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,100評論 1 32
  • 面向?qū)ο蟮娜筇卣?并作簡單的介紹。 面向?qū)ο蟮娜齻€基本特征是:封裝铭段、繼承骤宣、多態(tài)。 1.封裝是面向?qū)ο蟮奶卣髦?...
    xiny123閱讀 1,432評論 0 6
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用序愚,...
    LZM輪回閱讀 3,309評論 0 6
  • 2019年3月27日 周四 晚上憔披,妹夫打電話問我睡了嗎?,我說沒有芬膝。他說找我商量點事望门,問我方便嗎?我說沒問...
    寒梅hm閱讀 891評論 1 18
  • 如何管理超大虛擬地址空間蔗候? 方法一:多級頁表 關(guān)鍵:避免一直將所有頁表都保存在內(nèi)存怒允,尤其不應該將不需要的頁表還保存...
    橡樹人閱讀 892評論 0 1