2019 iOS 面試 -中級(jí)篇之 Block

1. block的實(shí)質(zhì)是什么佛吓?一共有幾種block?都是什么情況下生成的李茫?

block的實(shí)質(zhì)是什么十电?

  • block本質(zhì)上也是一個(gè)OC對象知押,它內(nèi)部也有個(gè)isa指針
  • block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對象
  • block是封裝函數(shù)及其上下文的OC對象

查看block源碼:

  • 打開終端,在main.m所在目錄下鍵入clang -rewrite-objc main.m即可在當(dāng)前目錄下生成一個(gè)main.cpp文件;
  • 當(dāng)引用了OC中的Foundation或者UIKit框架時(shí)鹃骂,通過 clang -rewrite-objc 指定文件名 命令將指定文件轉(zhuǎn)換成C++代碼會(huì)報(bào)錯(cuò);
  • 可通過 clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk 指定文件名

block定義:

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};
 
struct Block_layout {
    void *isa;
    int flags;
    int reserved; 
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
    /* Imported variables. */

一共有幾種block台盯?

  • _NSConcreteGlobalBlock 全局靜態(tài)
  • _NSConcreteStackBlock 保存在棧中,出函數(shù)作用域就銷毀
  • _NSConcreteMallocBlock 保存在堆中畏线,retainCount == 0銷毀而ARC和MRC中静盅,還略有不同;

都是什么情況下生成的?

  • 1寝殴、在全局區(qū)域聲明定義一個(gè)block

  • 2蒿叠、block表達(dá)式中沒有使用捕獲的自動(dòng)變量時(shí)

  • 以上情況生成的block都是NSConcreteGlobalBlock類型,只生成一個(gè)結(jié)構(gòu)體實(shí)例蚣常;除此情況下市咽,生成的都是NSConcreteStackBlock類型的block,且都是存儲(chǔ)在棧上史隆。

  • 參考1:block 系列文章之一

  • 參考2:又見block系列(值得再看一遍)

  • 參考3:《Objective-C高級(jí)編程 iOS與OS X多線程和內(nèi)存管理》電子書參考第二章

2. 為什么在默認(rèn)情況下無法修改被block捕獲的變量魂务? __block都做了什么?

Block只捕獲Block中會(huì)用到的變量泌射。由于只捕獲了自動(dòng)變量(自動(dòng)變量是以值傳遞方式傳遞到Block的構(gòu)造函數(shù)里面)的值,并非內(nèi)存地址鬓照,所以Block內(nèi)部不能改變自動(dòng)變量的值熔酷。Block捕獲的外部變量可以改變值的是靜態(tài)變量,靜態(tài)全局變量豺裆,全局變量拒秘。

參考:深入研究Block捕獲外部變量和__block實(shí)現(xiàn)原理

如何在block中修改外部自動(dòng)變量的值号显,主要有以下2種方法:

  • a、修改C語言中的靜態(tài)變量躺酒、靜態(tài)全局變量和全局變量
  • b押蚤、使用__block修飾需要修改的自動(dòng)變量

3. 模擬一下循環(huán)引用的一個(gè)情況?block實(shí)現(xiàn)界面反向傳值如何實(shí)現(xiàn)羹应?

循環(huán)引用:

#import <Foundation/Foundation.h>
typedef void(^Study)();  
@interface Student : NSObject
@property (copy , nonatomic) NSString *name;
@property (copy , nonatomic) Study study;
@end


#import "ViewController.h"
#import "Student.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
  
    Student *student = [[Student alloc]init];
    student.name = @"Hello World";
 
    student.study = ^{
        NSLog(@"my name is = %@",student.name);
    };

block界面反向傳值實(shí)例:
1揽碘、在第二個(gè)視圖控制器的.h文件中定義聲明Block屬性:

// NextViewController.h
// 定義block
@property (nonatomic,copy) void (^NextViewControllerBlock)
(NSString *tfText);
// NextViewController.m
@interface NextViewController ()
@property (weak, nonatomic) IBOutlet UITextField *inputTF;
@end
 
- (IBAction)BtnAction:(id)sender {
    //判斷block是否為空
    if (self.NextViewControllerBlock) {
        self.NextViewControllerBlock(self.inputTF.text);   
    }
    [self.navigationController popViewControllerAnimated:YES];
}

2、在第一個(gè)視圖中獲得第二個(gè)視圖控制器园匹,并且用第二個(gè)視圖控制器來調(diào)用定義的屬性:

// AViewController.m
@interface AViewController ()
@property (weak, nonatomic) IBOutlet UILabel *nextVCInfoLabel;
@end
 
- (IBAction)btnClicked:(id)sender {
    NextViewController *nextVC = [[NextViewController alloc]init];
    nextVC.NextViewControllerBlock = ^(NSString *tfText){
        self.nextVCInfoLabel.text = tfText;
    };
    [self.navigationController pushViewController:nextVC animated:YES];
}

4. NSTImer的循環(huán)引用問題

使用NSTimer可能會(huì)碰到循環(huán)引用的問題雳刺。特別是當(dāng)類具有NSTimer類型的成員變量,并且需要反復(fù)執(zhí)行計(jì)時(shí)任務(wù)時(shí)裸违。例如

_timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                          target:self
                                        selector:@selector(startCounting)   userInfo:nil
                                         repeats:YES];

類有一個(gè)成員變量_timer,給_timer設(shè)置的target為這個(gè)類本身。這樣類保留_timer镣奋,_timer又保留了這個(gè)類胁勺,就會(huì)出現(xiàn)循環(huán)引用的問題,最后導(dǎo)致類無法正確釋放怔昨。

解決這個(gè)問題的方式也很簡單料饥,當(dāng)類的使用者能夠確定不需要使用這個(gè)計(jì)時(shí)器時(shí),就調(diào)用

[_timer invalidate];
_timer = nil;

這樣就打破了保留環(huán)朱监,類也可以正確釋放岸啡。但是,這種依賴于開發(fā)者手動(dòng)調(diào)用方法赫编,才能讓內(nèi)存正確釋放的方式不是一個(gè)非常好的處理方式巡蘸。所以需要另外一種解決方案。
如下所示:

@interface NSTimer (JQUsingBlock)
+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)ti
                                     block:(void(^)())block
                                   repeats:(BOOL)repeats;
@end
 
@implementation NSTimer (JQUsingBlock)
 
+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)ti
                                     block:(void(^)())block
                                   repeats:(BOOL)repeats{
    return [self scheduledTimerWithTimeInterval:ti
                                     target:self                                                                        selector:@selector(jq_blockInvoke:)
                                   userInfo:[block copy]
                                    repeats:repeats];
}
 
+ (void)jq_blockInvoke:(NSTimer *)timer{
    void(^block)() = timer.userInfo;
    if (block) {
        block();
    }
}
 
@end

定義一個(gè)NSTimer的類別擂送,在類別中定義一個(gè)類方法悦荒。類方法有一個(gè)類型為塊的參數(shù)(定義的塊位于棧上,為了防止塊被釋放嘹吨,需要調(diào)用copy方法搬味,將塊移到堆上)。
使用這個(gè)類別的方式如下:

__weak ViewController *weakSelf = self;
_timer = [NSTimer jq_scheduledTimerWithTimeInterval:5.0
                        block:^{
                                __strong ViewController *strongSelf = weakSelf;
                                [strongSelf startCounting];
                                }
                      repeats:YES];

使用這種方案就可以防止NSTimer對類的保留蟀拷,從而打破了循環(huán)引用的產(chǎn)生碰纬。__strong ViewController *strongSelf = weakSelf主要是為了防止執(zhí)行塊的代碼時(shí),類被釋放了问芬。在類的dealloc方法中悦析,記得調(diào)用[_timer invalidate]。

相關(guān)閱讀:

1此衅、iOS 面試題 --- 基礎(chǔ)部分
2强戴、iOS 面試題 --- 中級(jí)篇 Runtime
3亭螟、iOS 面試題 --- 中級(jí)篇 Runloop
4、iOS 面試題 --- 高級(jí)篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骑歹,一起剝皮案震驚了整個(gè)濱河市预烙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌道媚,老刑警劉巖扁掸,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衰琐,居然都是意外死亡也糊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門羡宙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狸剃,“玉大人,你說我怎么就攤上這事狗热〕伲” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵匿刮,是天一觀的道長僧凰。 經(jīng)常有香客問我,道長熟丸,這世上最難降的妖魔是什么训措? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮光羞,結(jié)果婚禮上绩鸣,老公的妹妹穿的比我還像新娘。我一直安慰自己纱兑,他們只是感情好呀闻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潜慎,像睡著了一般捡多。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铐炫,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天垒手,我揣著相機(jī)與錄音,去河邊找鬼驳遵。 笑死淫奔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的堤结。 我是一名探鬼主播唆迁,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼竞穷!你這毒婦竟也來了唐责?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤瘾带,失蹤者是張志新(化名)和其女友劉穎鼠哥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體看政,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朴恳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了允蚣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片于颖。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嚷兔,靈堂內(nèi)的尸體忽然破棺而出森渐,到底是詐尸還是另有隱情,我是刑警寧澤冒晰,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布同衣,位于F島的核電站,受9級(jí)特大地震影響壶运,放射性物質(zhì)發(fā)生泄漏耐齐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一蒋情、第九天 我趴在偏房一處隱蔽的房頂上張望埠况。 院中可真熱鬧,春花似錦恕出、人聲如沸询枚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽金蜀。三九已至,卻和暖如春的畴,著一層夾襖步出監(jiān)牢的瞬間渊抄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工丧裁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留护桦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓煎娇,卻偏偏與公主長得像二庵,于是被迫代替她去往敵國和親贪染。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

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

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,093評論 1 32
  • 面向?qū)ο蟮娜筇匦裕悍庋b催享、繼承杭隙、多態(tài) OC內(nèi)存管理 _strong 引用計(jì)數(shù)器來控制對象的生命周期。 _weak...
    運(yùn)氣不夠技術(shù)湊閱讀 1,092評論 0 10
  • 《招聘一個(gè)靠譜的 iOS》—參考答案(下) 說明:面試題來源是微博@我就叫Sunny怎么了的這篇博文:《招聘一個(gè)靠...
    韓發(fā)發(fā)吖閱讀 1,557評論 0 8
  • 有人說我傻乎乎的因妙!還妄圖成為我想成為的那種人痰憎,讓我羨慕他一輩子!哼(¬︿??¬☆) Runaway蠻好聽的~ 煙火...
    舞荷閱讀 363評論 4 1
  • 關(guān)鍵詞:溝通題主:女問:冷大蜗细,你好!我23歲据德,是一名大三的學(xué)生鳄乏。我的男朋友24歲,已經(jīng)工作兩年棘利。他在童年時(shí)候橱野,他經(jīng)...
    冷愛閱讀 279評論 0 0