iOS block和代理的區別


  block和代理是iOS開發中實現回調的兩種方式,大多數情況下是用哪個都可以,主要看個人喜好。本文主要是對兩者做一下對比。

1.block簡介

  在 iOS中, block一共分三種。
  (1)全局靜態 block,不會訪問任何外部變量,執行完就銷毀。

 ^{
        NSLog(@"Hello World!");
    }();

(2)保存在棧中的 block,當函數返回時會被銷毀,和第一種的區別就是調用了外部變量。

 
    [UIView animateWithDuration:3 animations:^{
       
        self.view.backgroundColor = [UIColor redColor];
    }];

  (3)保存在堆中的 block,當引用計數為 0 時會被銷毀。例如按鈕的點擊事件,一直存在,即使執行過,也不銷毀,因為按鈕還可能被點擊,持有按鈕的View被銷毀,它才會被銷毀。

#import <UIKit/UIKit.h>

typedef void(^ButtonClickBlcok)();

@interface TestView : UIView

@property (nonatomic, copy) ButtonClickBlcok buttonClickBlcok;

@end

#import "TestView.h"

@implementation TestView

- (IBAction)buttonClick:(id)sender {
    
    if (self.buttonClickBlcok) {
        self.buttonClickBlcok();
    }
}
@end

2.block優點

  block的代碼可讀性更好。因為應用block和實現block的地方在一起。代理的聲明和實現就分開來了,在兩個類中。代理使用起來也更麻煩,因為要聲明協議、聲明代理、遵守協議、實現協議里的方法。block不需要聲明,也不需要遵守,只需要聲明和實現就可以了。
  block是一種輕量級的回調,可以直接訪問上下文,由於block的代碼是內聯的,運行效率更高。block就是一個對象,實現了匿名函數的功能。所以我們可以把block當做一個成員變量、屬性、參數使用,使用起來非常靈活。像用AFNetworking請求數據和GCD實現多線程,都使用了block回調。

3.block缺點

  blcok的運行成本高。block出棧需要將使用的數據從棧內存拷貝到堆內存,當然對象的話就是引用計數加1,使用完或者block置nil后才銷毀。delegate只是保存了一個對象指針(一定要用week修飾delegate,不然也會循環引用),直接回調,沒有額外消耗。就像C的函數指針,只多做了一個查表動作。
  block容易造成循環引用,而且不易察覺。因為為了blcok不被系統回收,所以我們都用copy關鍵字修飾,實行強引用。block對捕獲的變量也都是強引用,所以就會造成循環引用。

#import "ViewController.h"

typedef void(^TestBlock)(void);

@interface ViewController ()
{
    void (^_testCycleBlock)(void);
}
@end

@implementation ViewController

- (void)viewDidLoad {
  
    [super viewDidLoad];
    
    __weak ViewController *weakSelf = self;
    _testCycleBlock = ^{

        /**
          //引發循環引用
          NSLog(@"%@", self);
         */
        //防止循環引用
        NSLog(@"%@", weakSelf);
    };
}
@end

4.如何使用

  優先使用block。
  如果回調函數很多,多余三個使用代理。
  如果回調的很頻繁,次數很多,像UITableview,每次初始化、滑動、點擊都會回調,使用代理。
  block和代理都各有優缺點,所以我們一定要理解區分使用場景,應用適合的回調方式。優化APP的性能,提高流暢性,從點滴做起。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM