IOS 多播委託(GCDMulticastDelegate)

在IOS中爲了實現回調通常有以下幾個方法:緩存

  1. delegate
  2. 通知中心
  3. block
  4. KVO(較特殊的回調,姑且也算一種)

以上四種中在我本身的項目中比較經常使用的就是delegate和block了。多線程

在現實中回調的需求也分兩種架構

  1. 一對一的回調。
  2. 一對多的回調。

對於一對一的回調,在IOS中使用delegate、block都能實現。而一對多的回調基本就是通知中心了。ide

 

假如如今有一個需求,咱們以圖片下載爲例。這裏先忽略哪些SDWebimage等已經封裝好的第三方類庫。對於圖片下載通常的過程以下:atom

  1. 先判斷該圖片url是否已經下載完畢。若是已經下載完畢那麼直接回調顯示圖片。若是沒有下載那麼進入下載過程.
  2. 使用合適的圖片下載器下載圖片。
  3. 圖片下載完畢後回調顯示圖片。而且把該圖片存到緩存中。

這裏的難點是回調。若是一個頁面中有多個地方須要顯示同一張圖片,那麼勢必會發生這樣一種狀況,就是同時有多個請求下載贊成url的圖片,而且下載完成後須要同時在多個地方顯示圖片。要是實現這樣的需求,用現有的方案貌似很難解決。有的同窗會想到通知中心,可是通知中心實際上是一個廣播服務,只要註冊了接受該通知那麼全部的註冊者都能收到通知,但事實上我只須要在我須要下載的那個url的圖片下載完後給出通知,而不須要全部的下載完畢事件都通知。這時候咱們就須要多播委託了。url

什麼是多播委託?我直接拿其餘博客上的一個定義來解釋。簡單地說,多播委託是指容許建立方法的調用列表或者鏈表的能力。當多播委託被調用時,列表中的方法均自動執行spa

在IOS中我就以咱們日常用的最多的delagate爲例,普通的delegate只能是一對一的回調,沒法作到一對多的回調。而多播委託正式對delegate的一種擴展和延伸,多了一個註冊和取消註冊的過程,任何須要回調的對象都必須先註冊。線程

如何在IOS中實現多播委託?老外早就已經寫好了,並且至關的好用。我最初接觸IOS多播委託是我在研究XMPPframework的時候,而多播委託能夠說是XMPPframework架構的核心之一。具體的類名就是GCDMulticastDelegate,從名字就能夠看出,這是一個支持多線程的多播委託。那爲何要支持多線程呢?個人理解是多個回調有可能不是在同一個線程的,好比我註冊回調的時候是在後臺線程,可是你回調的時候卻在UI線程,那就有可能出問題了。所以必須保證你註冊的時候在哪一個線程上註冊的,那麼回調的時候必須仍是在那個線程上回調的。code

下面我講解寫多播委託在IOS中的用法。orm

我先舉個例子,好比有一個UserInfo(有一個userName的屬性)的類,頁面上有三個lable和一個按鈕,當點擊按鈕的時候給userInfo的userName屬性賦值,這時候三個lable同時顯示userInfo的userName屬性的值。

針對以上過程,咱們須要對每一個lable向userInfo實例註冊,也就是向多播委託註冊。當對userInfo的userName賦值的時候調用多播委託的方法,這裏也就是調用setText方法。這樣就能實現上面的需求了。

用代碼表示就是:

//繼承自多播委託基類的userInfo類
@interface UserInfo : MulticastDelegateBaseObject
@property (nonatomic,strong)NSString *userName;
@end

@implementation UserInfo
-(void)setUserName:(NSString *)userName{
    _userName=userName;
    [multicastDelegate setText:userName];//調用多播委託
}
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //初始化一個userinfo的實例
    userInfo=[[UserInfo alloc] init];
    
    //添加一個lable
    UILabel *lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 20, 100, 30)];
    lable.backgroundColor=[UIColor blueColor];
    lable.textColor=[UIColor blackColor];
    [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()];//向多播委託註冊
    [self.view addSubview:lable];
    
    lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 60, 100, 30)];
    lable.backgroundColor=[UIColor blueColor];
    lable.textColor=[UIColor blackColor];
    [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()];
    [self.view addSubview:lable];
    
    lable =[[UILabel alloc] initWithFrame:CGRectMake(0, 100, 100, 30)];
    lable.backgroundColor=[UIColor blueColor];
    lable.textColor=[UIColor blackColor];
    [userInfo addDelegate:lable delegateQueue:dispatch_get_main_queue()];
    [self.view addSubview:lable];
    
    //添加一個按鈕
    UIButton *btn=[[UIButton alloc] initWithFrame:CGRectMake(200, 20, 100, 50)];
    [btn setBackgroundColor:[UIColor blueColor]];
    [btn setTitle:@"button1" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(btnCLicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
}

-(void)btnCLicked:(UIButton *)btn{
    userInfo.userName=@"123456";//給userInfo賦值
}

 

源代碼點擊下載

相關文章
相關標籤/搜索