block

 


block的用法


0.做用:

  • 保存一段代碼,並非立刻執行,須要手動調用

1.聲明:返回值(^block變量名)(block參數類型),參數變量名能夠省略

  • 無返回值:void(^block)()

2.定義方式

定義1:web

等號右邊:^(參數類型 參數變量名){ };
無返回值:(void)(^block)() = ^(){ };

定義2:面試

等號右邊:^返回值(參數類型 參數變量名){ };返回值能夠省略,可是也有不省略
無返回值:(void)(^block)() = ^void(){ };
有返回值:int(^block3)(int a) = ^int(int a){
        return 2;
    };

定義3:編程

等號右邊:當沒有返回值,沒有參數,能夠省略
無返回值:(void)(^block)() = ^{ };

3.調用:保存一段代碼,並非立刻執行,須要手動調用

//block的聲明
@property (nonatomic, strong) void(^block)();

//block的定義
void (^block)() = ^{
    NSLog(@"daquan");
};

//block的手動調用
block();
---------------------------------
// name:block類型別名
typedef void(^BlockType)();

//聲明
@property (nonatomic, assign) BlockType block1;

//定義
    _block1 = ^{
        NSLog(@"daquan");
    };

//調用
     _block1();

4.類型

無返回值無參數:void(^block)() = ^{};
無返回值有參數:void(^block)(NSString *str) = ^(NSString *str){ };
有返回值有參數:int(^block)(int a) = ^int(int a) {};
有返回值無參數:int(^block)() = ^int(){};

5.快捷鍵

inlineblock:快速生成block代碼異步

returnType(^blockName)(parameterTypes) = ^(parameters) {
 statements
 };

6.開發使用場景,把代碼保存到模型,彩票思想

  • block用strong聲明策略

7.開發場景(傳值)

傳值的方式:ide

1.順傳:定義屬性
2.逆傳:代理,block.block能夠用來替代代理,實現相同的功能.
  • 使用代理的步驟:定義代理屬性;定義協議;定義方法(包括傳的值);傳值的具體場景;設置代理對象.
實例:點擊主控制器後,就modal另外一個控制器,並將modal出來控制器裏面的值傳遞給主控制器.
主控制器:
#import "ViewController.h"
#import "ModalViewController.h"

@interface ViewController ()<ModalViewControllerDelegate>
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 建立modal控制器
    ModalViewController *modalVc = [[ModalViewController alloc] init];
    modalVc.delegate = self;
    [self presentViewController:modalVc animated:YES completion:nil];
}

#pragma mark -ModalViewControllerDelegate
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value
{
    NSLog(@"%@",value);
}
@end

modal出來的控制器:
#import <UIKit/UIKit.h>
//聲明類
@class ModalViewController;
//定義協議
@protocol ModalViewControllerDelegate <NSObject>
//建立方法(可實現,可不實現)
@optional
//將字符串傳遞出去
- (void)modalViewController:(ModalViewController *)modalVc sendValue:(NSString *)value;
@end

@interface ModalViewController : UIViewController
//代理屬性
@property (nonatomic, weak) id<ModalViewControllerDelegate> delegate;
@end

//點擊事件
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //須要判斷是否實現了代理方法
   if ([_delegate respondsToSelector:@selector(modalViewController:sendValue:)]) {
        [_delegate modalViewController:self sendValue:@"123"];
    }
    
    // 回到上一個控制器(modal出來的控制器就能夠用dismiss回到上一個控制器)
    [self dismissViewControllerAnimated:YES completion:nil];
}
  • 使用block的步驟:聲明帶參數的block屬性;在須要的傳值的控制器中定義block;在傳值的控制器中調用block
主控制器:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 建立modal控制器
    ModalViewController *modalVc = [[ModalViewController alloc] init];
    
    modalVc.valueBlock = ^(NSString *value){
      
        NSLog(@"%@",value);
        
    };
    
    [self presentViewController:modalVc animated:YES completion:nil];
}

modal出來的控制器:
@property (nonatomic, strong) void(^valueBlock)(NSString *value);


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 傳值
    if (_valueBlock) {
        _valueBlock(@"123");
    }
    // 回到上一個控制器
    [self dismissViewControllerAnimated:YES completion:nil];
}

8.內存管理

總結:atom

  • block:若是block沒有訪問外部的局部變量或者局部變量被static修飾,默認存放在全局區;若是block訪問了外部的局部變量,就會存放在棧裏面

 

8.1.MRC:(沒有strong,weak,只有assign,retain,copy)url

面試題:block是否是對象? --> 是(官方文檔:working with blocks)
1.手動管理內存,須要本身去釋放內存.
2.開發習慣:訪問屬性或者設置屬性,必須使用點語法(會調用get方法),不要使用下劃線.
3.區分MRC代碼:看可否調用release、retain;ARC不能調用[super dealloc];
4.修改配置信息:ARC automatic...= NO;(在工程文件中搜索ARC便可找到)
5.如何管理block?
    內存5個區:堆,棧,方法區,常量區,全局區
    堆:手動管理內存
    棧:自動管理,代碼塊一過,就會自動釋放
5.1MRC中,若是block沒有訪問外部的局部變量或者局部變量被static修飾,block默認存放在"全局區"
5.2MRC中,不能使用retain聲明block,依然放在棧裏面,會自動銷燬
5.3MRC中,使用copy聲明block,纔會放在堆裏面.
5.4MRC中,默認一個對象就是基本類型.

8.2.ARC:spa

ARC管理原則:默認一個局部變量對象,都是強指針,存放在堆裏面;若是沒有一個對象沒有強指針引用,就會銷燬.
1.若是block訪問外部的局部變量,block默認存放在"堆"裏面
2.使用strong聲明block,不要使用weak.
3.block會對外部全部強指針對象給強引用.不會對外部的弱指針給強引用.

9.循環引用

  • 爲了解決循環引用問題:咱們都會聲明weakSelf爲弱指針
// 聲明weakSelf弱指針
    __weak typeof(self) weakSelf = self;
    _block = ^{
        NSLog(@"%@",weakSelf);
    };

//dealloc方法
- (void)dealloc
{
    NSLog(@"%s",__func__);
}
  • block使用strong的場景:
_block = ^{  
        // 延遲操做或者異步任務,才須要搞個strongSelf
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{      
            NSLog(@"%@",strongSelf); 
        });      
    };
    
    _block();

10.變量傳值

  • 1.若是block訪問外部局部變量沒有被任何關鍵字修飾,都是值傳遞
  • 2.block訪問外部變量被__block,static修飾,指針傳遞
  • 3.若是訪問的是全局變量,也是指針傳遞

11.參數使用

11.1.何時使用block充當參數?思想3d

封裝一個功能,這個功能作什麼事情由外界決定,可是何時調用由內部決定,這時候就須要把block充當參數去使用.

11.2.怎麼去把block充當參數?實戰代理

11.3.鏈式編程思想:把方法調用經過點語法連接,可讀性很是好

11.4.封裝一個計算器,提供一個加法語法.

11.5.block做爲參數的實現

CalculatorManage:

#import <Foundation/Foundation.h>
@interface CalculatorManage : NSObject
@property (nonatomic, assign) int reslut;

- (int)calculator:(int(^)(int result))block;
@end

@implementation CalculatorManage

- (int)calculator:(int (^)(int result))block
{
   _reslut = block(_reslut);
    
    return _reslut;
}


主控制器:

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CalculatorManage *mgr = [[CalculatorManage alloc] init];
    
    [mgr calculator:^(int result) {
        result += 5;
        result *= 2;
        
        return result;
    }];
    
    NSLog(@"%d",mgr.reslut); 
}

輸出結果:10
相關文章
相關標籤/搜索