使用Specta單元測試檢測View和ViewController是否泄漏

前面使用Specta單元測試檢測對象是否泄漏介紹了如何檢測一個普通的NSObject對象是否泄漏谴忧。UIView和UIViewController也是NSObject的子類袋励,當(dāng)然也能使用使用Specta單元測試檢測對象是否泄漏,但是我們知道UIView和UIViewController的應(yīng)用場景比起普通的NSObject對應(yīng)要更加復(fù)雜一些末购。

下面會介紹使用Specta單元測試檢測View和ViewController是否泄漏。

TestContainer 代碼

和之前的文章一樣虎谢,也需要一個TestContainer來weak持有要檢測的對象盟榴。


@interface TestContainer : NSObject

@property (nonatomic, weak) id object;

@end


@implementation TestContainer
// Empty
@end

UIView的檢測

對于UIView的檢測,我們可以創(chuàng)建一個UIWindow婴噩,并且把UIView添加到這個UIWindow里面擎场,然后讓這個UIWindow進行展示,最后再將這個UIWindow設(shè)置成nil几莽,這樣就能模擬這個UIView一個完整的生命周期迅办。

這樣就能檢測UIView是否存在泄漏。

UIView - Spec測試代碼

下面寫檢測代碼章蚣,我們定義一個局部變量weakView站欺, 然后在一個@autoreleasepool里面創(chuàng)建對象, 并且這個weakView在block內(nèi)部置為nil

describe(@"TestObject", ^{
    context(@"when created", ^{
        it(@"should dealloc", ^{
            TestContainer *tc = [TestContainer new];
            __weak TestView *weakView = nil;
            @autoreleasepool {
                TestView *view = [[TestView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
                expect(view).beKindOf([UIView class]);
                UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
                [window makeKeyAndVisible];
                [window addSubview:view];
                weakView = view;
                expect(weakView).notTo.beNil();
                tc.object = weakView;
                view = nil;
                window = nil;
            }
            expect(tc.object).after(5).to.beNil();
        });
    });
});

這里我們斷言:斷定tc的object指針在5秒鐘后究驴,是nil镊绪。

UIView - 模板代碼

sharedExamplesFor(@"view_dealloc_behavior", ^(NSDictionary *data) {
    context(@"removed", ^{
        it(@"should dealloc", ^{
            id (^block)(void) = [[data allValues] firstObject];
            if (!block) {
                return;
            }
            TestContainer *tc = [TestContainer new];
            __weak UIView *weakView = nil;
            @autoreleasepool {
                UIView *view = block();
                expect(view).beKindOf([UIView class]);
                UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
                [window makeKeyAndVisible];
                [window addSubview:view];
                weakView = view;
                expect(weakView).notTo.beNil();
                tc.object = weakView;
                view = nil;
                window = nil;
            }
            expect(tc.object).after(5).to.beNil();
        });
    });
});


使用上面的模板代碼匀伏,

describe(@"TestView", ^{
    itShouldBehaveLike(@"view_dealloc_behavior", @{ @"value" : ^{
        return [[TestView alloc] init];
    } });
});
檢測結(jié)果

在Xcode中洒忧,按Command + U開始測試,上面代碼中够颠, 我們運行的結(jié)果是 Test Success

UIViewController的檢測

對于UIViewController的檢測熙侍,我們同樣可以創(chuàng)建一個UIWindow,并且把UIViewController設(shè)置為這個UIWindow的rootViewController履磨,同樣然后讓這個UIWindow進行展示蛉抓,最后再將這個UIWindow設(shè)置成nil,同樣也就能模擬這個UIViewController一個完整的生命周期剃诅。

這樣就能檢測UIViewController是否存在泄漏巷送。

UIViewController - Spec測試代碼

下面寫檢測代碼,我們定義一個局部變量weakView矛辕, 然后在一個@autoreleasepool里面創(chuàng)建對象笑跛, 并且這個weakView在block內(nèi)部置為nil

describe(@"TestObject", ^{
    context(@"when created", ^{
        it(@"should dealloc", ^{
            TestContainer *tc = [TestContainer new];
            __weak TestViewController *weakController = nil;
            @autoreleasepool {
                TestViewController *controller = [[TestViewController alloc] init];
                expect(controller).beKindOf([UIViewController class]);
                UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
                [window makeKeyAndVisible];
                [window setRootViewController:controller];
                weakController = controller;
                expect(weakController).notTo.beNil();
                tc.object = weakController;
                controller = nil;
                window = nil;
            }
            expect(tc.object).after(5).to.beNil();
        });
    });
});

這里我們斷言:斷定tc的object指針在5秒鐘后,是nil聊品。

UIViewController - 模板代碼

sharedExamplesFor(@"viewController_dealloc_behavior", ^(NSDictionary *data) {
    context(@"removed", ^{
        it(@"should dealloc", ^{
            id (^block)(void) = [[data allValues] firstObject];
            if (!block) {
                return;
            }
            TestContainer *tc = [TestContainer new];
            __weak UIViewController *weakController = nil;
            @autoreleasepool {
                UIViewController *controller = block();
                expect(controller).beKindOf([UIViewController class]);
                UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
                [window makeKeyAndVisible];
                [window setRootViewController:controller];
                weakController = controller;
                expect(weakController).notTo.beNil();
                tc.object = weakController;
                controller = nil;
                window = nil;
            }
            expect(tc.object).after(5).to.beNil();
        });
    });
});


使用上面的模板代碼飞蹂,

describe(@"TestViewController", ^{
    itShouldBehaveLike(@"viewController_dealloc_behavior", @{ @"value" : ^{
        return [[TestViewController alloc] init];
    } });
});
檢測結(jié)果

在Xcode中,按Command + U開始測試翻屈,上面代碼中陈哑, 我們運行的結(jié)果是 Test Success

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惊窖,更是在濱河造成了極大的恐慌刽宪,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件界酒,死亡現(xiàn)場離奇詭異纠屋,居然都是意外死亡,警方通過查閱死者的電腦和手機盾计,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門售担,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人署辉,你說我怎么就攤上這事族铆。” “怎么了哭尝?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵哥攘,是天一觀的道長。 經(jīng)常有香客問我材鹦,道長逝淹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任桶唐,我火速辦了婚禮栅葡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尤泽。我一直安慰自己欣簇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布坯约。 她就那樣靜靜地躺著熊咽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闹丐。 梳的紋絲不亂的頭發(fā)上横殴,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音卿拴,去河邊找鬼衫仑。 笑死,一個胖子當(dāng)著我的面吹牛巍棱,可吹牛的內(nèi)容都是我干的惑畴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼航徙,長吁一口氣:“原來是場噩夢啊……” “哼如贷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤杠袱,失蹤者是張志新(化名)和其女友劉穎尚猿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楣富,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡凿掂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纹蝴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庄萎。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖塘安,靈堂內(nèi)的尸體忽然破棺而出糠涛,到底是詐尸還是另有隱情,我是刑警寧澤兼犯,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布忍捡,位于F島的核電站,受9級特大地震影響切黔,放射性物質(zhì)發(fā)生泄漏砸脊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一纬霞、第九天 我趴在偏房一處隱蔽的房頂上張望凌埂。 院中可真熱鬧,春花似錦险领、人聲如沸侨舆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熔恢,卻和暖如春脐湾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背叙淌。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工秤掌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹰霍。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓闻鉴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茂洒。 傳聞我的和親對象是個殘疾皇子孟岛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,096評論 1 32
  • 重點參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,430評論 0 15
  • 1.OC里用到集合類是什么? 基本類型為:NSArray,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,371評論 0 3
  • 7渠羞、不使用IB是斤贰,下面這樣做有什么問題? 6次询、請說說Layer和View的關(guān)系荧恍,以及你是如何使用它們的。 1.首先...
    AlanGe閱讀 673評論 0 1
  • 彼岸花開開彼岸屯吊,奈何橋頭無奈何(:-*)
    d418f903ca49閱讀 114評論 0 1