理解Block

堆棧的區(qū)別:經(jīng)典解釋

原作者不詳,未詳細查詢胜卤,從其它地方轉(zhuǎn)載并修改部分?jǐn)⑹觯卮苏f明

  1. 預(yù)備知識:程序的內(nèi)存分配

    一個由C/C++編譯的程序占用的內(nèi)存分為以下幾個部分
    1. 棧(stack):由編譯器自動分配釋放 葛躏,存放函數(shù)的參數(shù)值澈段,局部變量的值等舰攒。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
    2. 堆(heap): 一般由程序員分配釋放芒率, 若程序員不釋放,程序結(jié)束時可能由OS回收 偶芍。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事充择,分配方式類似于鏈表匪蟀。
    3. 全局區(qū)(靜態(tài)區(qū)static):全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域材彪, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域琴儿,程序結(jié)束后由系統(tǒng)釋放。
    4. 文字常量區(qū):常量字符串放在這里造成, 程序結(jié)束后由系統(tǒng)釋放
    5. 程序代碼區(qū):存放函數(shù)體的二進制代碼。
  2. 例子程序
//main.cpp
int a = 0; //全局初始化區(qū)
char *p1; //全局未初始化區(qū)
main()
{
    int b; //棧
    char s[] = "abc"; //棧
    char *p2; //棧
    char *p3 = "123456"; //123456\0在常量區(qū)雄嚣,p3在棧上。
    static int c =0缓升;//全局(靜態(tài))初始化區(qū)
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);
    //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。
    strcpy(p1, "123456"); //123456\0放在常量區(qū)港谊,編譯器可能會將它與p3所指向的"123456"優(yōu)化成一個地方。
}

Block基本語法

//As a local variable:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a property:

//As a property:
@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
As a method parameter:

//As a method parameter:
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
As an argument to a method call:

//As an argument to a method call:
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
As a typedef:

//As a typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};

修飾Block成員變量

Block 成員需要使用 copy 進行修飾歧寺,需要考慮Block是否線程安全,必要情況下使用atomic參數(shù)成福,當(dāng)使用atomic參數(shù)也不能百分百確保線程安全,因此在使用時最好將block屬性賦值給本地變量在使用奴艾,以防止其它線程將self.block置空。實際上蕴潦,我們使用修飾符 copy 是因為將存在棧區(qū)上的block轉(zhuǎn)移到堆區(qū)上,這個習(xí)慣是在MRC下的潭苞,現(xiàn)在在ARC下使用 copy 和 strong 是相同的。

2015/10/15更新:為什么ARC下使用copy和strong是相同的

要解釋這個問題必須要知道block的實現(xiàn)原理此疹,具體的實現(xiàn)原理參閱『參考3』僧诚。我在這里直接給出解釋蝗碎,實際上Block是有不同類型的,這些類型的區(qū)別在于Block是存儲在哪一個內(nèi)存區(qū)間蹦骑。

在MRC下有三種類型(見名知意):

  1. _NSConcreteGlobalBlock 全局的靜態(tài) block慈省,不會訪問任何外部變量眠菇。
  2. _NSConcreteStackBlock 保存在棧中的 block袱衷,當(dāng)函數(shù)返回時會被銷毀。
  3. _NSConcreteMallocBlock 保存在堆中的 block笑窜,當(dāng)引用計數(shù)為 0 時會被銷毀。

但在ARC下只有兩種怖侦,也就是第一種和第三種谜叹,也就是說本來需要在MRC下使用copy所做的操作實際上ARC幫我們做了,因此使用copy和strong也就無所謂了荷腊。

循環(huán)引用(ARC)

使用:

__weak __typeof(self) weakSelf = self;

解決循環(huán)引用self的問題艳悔。

** AFNetworking 作者的使用技巧:**

MyObject *obj = [[MyObject alloc]init];
obj.text = @"string";
__weak MyObject *weakObj = obj;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong MyObject *strongObj = weakObj;
    sleep(3);
});
sleep(1);
obj = nil;
sleep(4);

把變量在 block 外先用 __weak 聲明女仰,在 block 內(nèi)把前面 __weak 聲明的變量在賦值給 __strong 修飾的變量。這種寫法的好處就是可以讓變量在 block 內(nèi)部安全使用疾忍,即使外部對象釋放了,也會在 block 的生命周期內(nèi)保留該變量一罩。這種寫法非常巧妙杨幼,既避免了循環(huán)引用的問題聂渊,又可以在 block 內(nèi)部持有該變量。

參考:

正確使用Block避免Cycle Retain和Crash

How Do I Declare A Block in Objective-C?

談Objective-C Block的實現(xiàn)

block沒那么難(一):block的實現(xiàn)

若有錯誤請不吝指教

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汉嗽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饼暑,更是在濱河造成了極大的恐慌,老刑警劉巖弓叛,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邪码,居然都是意外死亡,警方通過查閱死者的電腦和手機闭专,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門旧烧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掘剪,你說我怎么就攤上這事∧蜗海” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵肉微,是天一觀的道長。 經(jīng)常有香客問我碉纳,道長,這世上最難降的妖魔是什么劳曹? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮铁孵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜕劝。我一直安慰自己账忘,他們只是感情好熙宇,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烫止,像睡著了一般。 火紅的嫁衣襯著肌膚如雪馆蠕。 梳的紋絲不亂的頭發(fā)上期升,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天互躬,我揣著相機與錄音,去河邊找鬼吼渡。 笑死容为,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坎背。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼得滤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了懂更?” 一聲冷哼從身側(cè)響起眨业,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤沮协,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后皂股,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體命黔,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡呜呐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年悍募,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坠宴。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖喜鼓,靈堂內(nèi)的尸體忽然破棺而出副砍,到底是詐尸還是另有隱情庄岖,我是刑警寧澤豁翎,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布隅忿,位于F島的核電站心剥,受9級特大地震影響背桐,放射性物質(zhì)發(fā)生泄漏优烧。R本人自食惡果不足惜链峭,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纷责,春花似錦、人聲如沸再膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽不瓶。三九已至灾杰,卻和暖如春蚊丐,著一層夾襖步出監(jiān)牢的瞬間艳吠,已是汗流浹背麦备。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工昭娩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凛篙,地道東北人栏渺。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓呛梆,卻偏偏與公主長得像磕诊,于是被迫代替她去往敵國和親填物。 傳聞我的和親對象是個殘疾皇子霎终,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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

  • 1. 關(guān)于 Block 的幾道題 結(jié)果分別為:A、B莱褒、A击困、B保礼、B 解釋: 第一題中沛励,Block 訪問外部變量 a炮障,...
    GLGeek閱讀 587評論 0 1
  • 本文主要根據(jù)《Objective-C高級編程》這本書中的第二章來進行的一個總結(jié)目派,其中包含了查看其它文章后的總結(jié)和自...
    AnICoo1閱讀 1,022評論 0 2
  • 前言 Blocks是C語言的擴充功能胁赢,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,757評論 0 23
  • 《Objective-C高級編程》這本書就講了三個東西:自動引用計數(shù)、block、GCD谅摄,偏向于從原理上對這些內(nèi)容...
    WeiHing閱讀 9,793評論 10 69
  • ――深深感恩生活 這次不慎腳傷,既沒讓我跌倒送漠,也沒讓我傷的很重,但卻切切實實讓我疼到痛不欲生闽寡,...
    簫音聲聲閱讀 309評論 0 1