讀源碼系列—-MBProgressHUD(載入等待框)

來源:互聯網
上載者:User

閱讀本文前,請先去下載原始碼(傳送門)

MBProgressHUD是一個iOS的類,當等待後台進程執行時,可以顯示出一個包含指標或者標籤的半透明的HUD。HUD是UIKit包中不允許開發人員使用的UIProgressHUD的替代品。

使用前提

MBProgressHUD可以以ARC或者non-ARC方式運行在iOS的任何版本,它使用到下列Cocoa Touch架構

  • Foundation.framework
  • UIKit.framework
  • CoreGraphics.framework

我們從MBProgressHUD.h看起,首先MBProgressHUD繼承子UIView,它具有View的特性,其標頭檔中,定義的枚舉類型MBProgressHUDMode和MBProgressHUDAnimation,分別對應不同的載入等待框樣式和消失動畫類型。通過接下來的宏定義,來標誌ARC和non-ARC模式及對BLOCK的支援。通過類方法+
(MBProgressHUD *)showHUDAddedTo:(UIView *)view animated:(BOOL)animated;
或者通過對象方法alloc及initWithView可以獲得MBProgressHUD對象,可以通過MBProgressHUD的delegate屬性,將遵循MBProgressHUDDelegate協議的對象,設為委託,在MBProgressHUD將要隱藏時回調。

在程式遇到非同步或者耗時較長的任務需要執行時,可以使用- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;方法,“鎖住“主介面,並顯示載入等待框。重點變在該函數內部,我們看一下:

- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {methodForExecution = method;targetForExecution =MB_RETAIN(target);objectForExecution =MB_RETAIN(object);// Launch execution in new threadself.taskInProgress =YES;[NSThreaddetachNewThreadSelector:@selector(launchExecution)toTarget:selfwithObject:nil];// Show HUD view[selfshow:animated];}

首先,我們將要執行的任務及目標對象傳入後,MB_RETAIN實際只是宏,在之前說的那段標頭檔中,在non-ARC下,它將先將target和object的記憶體計數加1,熟悉記憶體管理的應該知道,接到參數後先retain,才能防止對象被提前釋放。接著使用NSThread開一個線程,這是重點,現在有了新的一條線程,他將去執行我們的傳進來的任務,可不讓任務在主線程中調用,這樣才不會阻塞主線程。新線程發訊息給launchExecution。

- (void)launchExecution {@autoreleasepool {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Warc-performSelector-leaks"// Start executing the requested task[targetForExecutionperformSelector:methodForExecutionwithObject:objectForExecution];#pragma clang diagnostic pop// Task completed, update view in main thread (note: view operations should// be done only in the main thread)[selfperformSelectorOnMainThread:@selector(cleanUp)withObject:nilwaitUntilDone:NO];}}

targetForExecution完成具體任務的執行,這時候該線程在一直執行我們的任務,performSelectorOnMainThread的意思是在主線程執行cleanUp,所以當我們任務在其他線程執行完,回到主線程時,執行cleanUp。

cleanUp執行一些release和賦值nil操作後,將執行- (void)hide:(BOOL)animated這個將去執行觸發動畫效果的方法,接著將調用-
(void)done,在done中有一段這樣的代碼

if ([delegaterespondsToSelector:@selector(hudWasHidden:)]) {[delegateperformSelector:@selector(hudWasHidden:)withObject:self];}

向我們代理的對象發送hudWasHidden:訊息,如果之前設定這確,便可以響應。

 在標頭檔中有

@property (atomic, copy) NSString *labelText;@property (atomic, copy) NSString *detailsLabelText;

我們對這兩個NSString類型的屬性的賦值,會直接更新介面中的Label,這裡使用到的是KVO編程,通過#pragma mark - KVO標記可以查看該部分代碼,所有索引值資訊

- (NSArray *)observableKeypaths {return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"detailsLabelText", @"detailsLabelFont", @"progress", nil];}

註冊索引值

- (void)registerForKVO {for (NSString *keyPath in [self observableKeypaths]) {[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];}}

當索引值改變時,更新UI

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {if (![NSThread isMainThread]) {[self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO];} else {[self updateUIForKeypath:keyPath];}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.