Block学习笔记

2020-04-19  本文已影响0人  冷武橘

Block的初始化

block是一种特殊的数据类型,和Int,double,float....一样,可定义变量、作为参数、作为返回值。block可以用来保存一段代码,在恰当的时间再取出来调用,一般在动画、多线程、集合遍历、网络请求回掉中都经常见的到。

    1;               //整形
    2.1;             //浮点型
    @"2";            //字符串
    ^{
      NSLog(@"block是一种特殊的数据类型");
    };                //blockl类型;

block是一种特殊的数据类型,书写形式也就是在大括号前加上一个^,而大括号里可以保存代码段。

   int a;               //整形变量声明
   float b;             //浮点型变量声明
   NSString *str ;            //变量声明
  void(^myblock)();    //block类型变量声明

    a=12;
    b= 11.2;
    str=@"123";
    myblock=^(){
      NSLog(@"block类型的变量myblock赋值");
    };
int c=12;
void(^hltblock)=^{
NSLog(@"block变量声明的同时并赋值");
};

在定义和初始化block时,我们要时刻记住block也是一种特殊的数据类型,其初始化方式和其他数据类型一样。
1.有参数的block

   void(^hblock)(int,NSString*)=^(int a,NSString*b){
        NSLog(@"%d %@",a,b);
    };
    hblock(2,@"qqq");

2.无参数的block

  void(^hblock)()=^(){
        NSLog(@"无参数的block");
    };
  void(^bblock)()=^{
        NSLog(@"无参数的block,小括号可以省略");
    };

3.有返回值的block

 int(^block3)() = ^int{
        return 3;
    };
 int(^block5)() = ^{
      NSLog(@"block返回可以省略,不管有没有返回值,都可以省略
");
        return 3;
    };
    NSLog(@"%d",block5());  

   // block快捷方式 inline
  <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
 <#statements#>
  };

Block内部访问外部变量

    c=666;
    int a =10;
    __block int b=11;
    void(^lwjblock)()=^(){
        NSLog(@"%d",a);//默认情况下,block内部可以访问外面的变量
        //a = 13;//默认情况下,block内部不能修改外面的局部变量
        b=14;//给局部变量加上__block关键字,就可以修改局部变量了
        NSLog(@"%d",b);
        c=123;//全局变量可以修改
        NSLog(@"%d",c);
    };
    lwjblock();

Block内部访问外部变量

//如果是局部变量,Block是值传递
int a = 3;
void(^block)() = ^{
  NSLog(@"%d",a);
};
a = 5;
block();//block打印出的是3,是值传递
//block中使用的外面变量的值是拷贝过来的即值拷贝,所以在调用之前修改外界变量的值,不会影响到block中拷贝的值.
// 如果是静态变量,全局变量,__block修饰的变量,block都是指针传递
__block int a = 3;
void(^block)() = ^{
 NSLog(@"%d",a);
};
a = 5;
block();//这里调用block打印出的是5,是指针传递,可以直接影响变量的值

Block实战应用01-(保存代码)

应用场景描述:点击不同的cell跳转到不同的界面

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Settingitem : NSObject
/** 图片 */
@property (nonatomic, strong) UIImage *icon;

/** 标题 */
@property (nonatomic, copy) NSString *title;

/** 点击这一行要做的事情 */
@property (nonatomic, copy) void(^operation)(NSIndexPath *indexPath);

+ (instancetype)itemWithIcon:(UIImage *)icon title:(NSString *)title;
#import "Settingitem.h"

@implementation Settingitem

+ (instancetype)itemWithIcon:(UIImage *)icon title:(NSString *)title{
    Settingitem *item = [[self alloc] init];
    
    item.icon = icon;
    
    item.title = title;
    
    return item;
}
@end


#import <UIKit/UIKit.h>

@interface SettingController : UIViewController

@end
#import "SettingController.h"
#import "Settingitem.h"
@interface SettingController ()<UITableViewDelegate,UITableViewDataSource>

/** 数组总数 */
@property (nonatomic, strong) NSMutableArray *groups;
@end

@implementation SettingController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor=[UIColor whiteColor];
    self.title=@"设置";
    UITableView *tableview=[[UITableView alloc]initWithFrame:self.view.bounds style: UITableViewStylePlain];
    tableview.delegate=self;
    tableview.dataSource=self;
    [self.view addSubview:tableview];
    _groups = [NSMutableArray array];
    Settingitem *item1 = [Settingitem itemWithIcon:[UIImage imageNamed:@"RedeemCode"] title:@"使用税换码"];
    item1.operation = ^(NSIndexPath *indexpath){
        NSLog(@"使用税换码");
    };
    Settingitem *item2 = [Settingitem itemWithIcon:[UIImage imageNamed:@"MorePush"] title:@"推送和提醒"];
   //保存代码,保存要做的事
    item2.operation = ^(NSIndexPath *indexpath){
        NSLog(@"推送和提醒");
    };
    Settingitem *item3 = [Settingitem itemWithIcon:[UIImage imageNamed:@"handShake"] title:@"使用摇一摇机选"];
    item3.operation = ^(NSIndexPath *indexpath){
        NSLog(@"使用摇一摇机选");
    };
    [self.groups addObject:item1];
    [self.groups addObject:item2];
    [self.groups addObject:item3];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    Settingitem *item =  self.groups[indexPath.row];
    if (item.operation) {
        item.operation(indexPath);
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.groups.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *ID = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
    }
    Settingitem *item =  self.groups[indexPath.row];
    cell.imageView.image = item.icon;
    cell.textLabel.text = item.title;
    return cell;
}
@end

Block实战应用02-(逆向传值)

#import "ViewController.h"
#import "ModalViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    ModalViewController *modalVc = [[ModalViewController alloc] init];
    modalVc.view.backgroundColor = [UIColor brownColor];

    modalVc.block = ^(NSString *value) {
      
        NSLog(@"%@",value);
    };
    
    // 跳转
    [self presentViewController:modalVc animated:YES completion:nil];
}
@end
#import <UIKit/UIKit.h>
@interface ModalViewController : UIViewController
//定义个block属性,以此为媒介进行传值
@property (nonatomic, strong) void(^block)(NSString *value);
@end
#import "ModalViewController.h"
@interface ModalViewController ()
@end
@implementation ModalViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 传值给ViewController
    if (_block) {
        _block(@"123");
    }
}
@end

Block实战应用03-(作为参数使用)

需求:封装一个计算器,提供一个计算方法,怎么计算由外界决定,什么时候计算由内部决定.

#import <Foundation/Foundation.h>
@interface CacultorManager : NSObject
@property (nonatomic, assign) NSInteger result;
// 计算
- (void)cacultor:(NSInteger(^)(NSInteger result))cacultorBlock;
@end
#import "CacultorManager.h"
@implementation CacultorManager
- (void)cacultor:(NSInteger (^)(NSInteger))cacultorBlock
{
    if (cacultorBlock) {
      _result =  cacultorBlock(_result);
    }
}
@end
#import "ViewController.h"
#import "CacultorManager.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 把block当做参数,并不是马上就调用Block,什么时候调用,由方法内部决定
    // 什么时候需要把block当做参数去使用:做的事情由外界决定,但是什么时候做由内部决定.
    // 创建计算器管理者
    CacultorManager *mgr = [[CacultorManager alloc] init];
    [mgr cacultor:^(NSInteger result){
        result += 5;
        result += 6;
        result *= 2;
        return result;
    }];
}
@end

封装一个网络请求工具类

#import <Foundation/Foundation.h>
#import "AFNetworking.h"
@interface HttpTool : NSObject
/**
 *  发送一个GET请求
 *
 *  @param url     请求路径
 *  @param params  请求参数
 *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
 *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
 */
+ (void)get:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;

/**
 *  发送一个POST请求
 *
 *  @param url     请求路径
 *  @param params  请求参数
 *  @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
 *  @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
 */
+ (NSURLSessionDataTask *)post:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;
@end

#import "HttpTool.h"
@implementation HttpTool
+(void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    //1.获得请求管理者
    AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
    
    //2.发送Get请求
    [mgr GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failure) {
            failure(error);
        }
    }];
}

+(NSURLSessionDataTask *)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    //1.获得请求管理者
    AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
   NSURLSessionDataTask *dataTask = [mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
       if (success) {
           success(responseObject);
       }
   } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
       
       if (failure) {
           failure(error);
       }
   }];
    return dataTask;
}
@end

解决block循环引用

#import "Secviewcontroller.h"
#import "Person.h"
@interface Secviewcontroller (){
    Person * _person;
}
@property(nonatomic,copy)void(^block)();
@property(nonatomic,strong)NSString *name;

@end

@implementation Secviewcontroller
/*
 循环引用:我引用你,你也引用,就会造成循环引用,双方都不会被销毁,导致内存泄露问题
 
block造成循环利用:Block会对里面所有强指针变量都强引用一次 
 
 解决循环引用: 创建一个弱指针,如果外部对象是弱引用那么内部会自动生成一个弱引用,引用着外部对象。关键字:__weak
 
 */
- (void)viewDidLoad {
    [super viewDidLoad];
       self.view.backgroundColor=[UIColor whiteColor];
    [self test2];
}
//解决循环引用
- (void)test1{
    /*理解self:在当前指的是一个 Secviewcontroller对象,
     即 :Secviewcontroller *weakself=self;
     默认指针变量都是强指针,即
     __strong Secviewcontroller *weakself=self;
     为了避免循环引用,我们需要把__strong指针变成弱指针,于是我们需要这样就接受拿到self, 即
     __weak Secviewcontroller *weakself=self;
     */
    
    __weak Secviewcontroller *weakself=self;

   self.block=^(){
        NSLog(@"%@",weakself.name);
    };

}
- (void)test2{
 __strong Person *p = [[Person alloc] init];
  
    __weak  Person *weakperson=p;

   p.personblock=^(){
     NSLog(@"%@",weakperson.name);
  };
}

//typeof(x) 函数动态根据x判断x的真实类型
- (void)commara{
    int a = 10;
    typeof(1) b =30;
    NSLog(@"a %d b %d",a, b);
    
    __weak typeof(self)weakself = self;
    //typeof(self)相当于Secviewcontroller *
    
    Person *p = [[Person alloc] init];
    __weak typeof(p)weakperson = p;
    NSLog(@"%@",[weakperson class]);
    //typeof(self)相当于Person *
}
- (void)test3{
   Person *p = [[Person alloc] init];
    __weak  typeof(p)weakperson = p;
    
    p.personblock=^(){
        NSLog(@"%@",weakperson.name);
    };
    __weak typeof(self)weakself = self;
    self.block= ^(){
        NSLog(@"%@",weakself);
    };
    
}
//控制器只有被销毁时,才会被调用。(即循环引用的情况下,不会被调用)
-(void)dealloc{
    NSLog(@"被释放销毁了");
}
@end
上一篇下一篇

猜你喜欢

热点阅读