码迷,mamicode.com
首页 > 其他好文 > 详细

block

时间:2016-01-15 22:52:55      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:

 


block的用法


0.作用:

  • 保存一段代码,并不是马上执行,需要手动调用

1.声明:返回值(^block变量名)(block参数类型),参数变量名可以省略

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

2.定义方式

定义1:

等号右边:^(参数类型 参数变量名){ };
无返回值:(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.开发场景(传值)

传值的方式:

+ 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.内存管理(面试)

总结:

  • block:如果block没有访问外部的局部变量或者局部变量被static修饰,默认存放在全局区;如果block访问了外部的局部变量,就会存放在栈里面

 

1.MRC:(没有strong,weak,只有assign,retain,copy)

面试题: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中,默认一个对象就是基本类型.

2.ARC:

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.如果访问的是全局变量,也是指针传递

10.参数使用

1.什么时候使用block充当参数?思想

封装一个功能,这个功能做什么事情由外界决定,但是什么时候调用由内部决定,这时候就需要把block充当参数去使用.

2.怎么去把block充当参数?实战

3.链式编程思想:把方法调用通过点语法链接,可读性非常好

4.封装一个计算器,提供一个加法语法.

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

block

标签:

原文地址:http://www.cnblogs.com/zhoudaquan/p/5134423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!