• IOS中block的一些用法


    __weak typeof(self) weakSelf = self的应用

    typeof(xxx)是用来确定括号中内容的类型,如

    int a = 10;

    可以这样写

    typeof(100) a = 10;

    这两种写法是等价的。那么回到上边,__weak typeof(self) weakSelf 可以用其它代码代替。假如self为PersonViewController,那么

    __weak PersonViewController *weakSelf = self;

    这两种也是等价的,只不过用typeof不用管那么多。

    意思是声明了一个self类型的weakSelf,加上__weak表示它是弱引用的。整行代码就是给self定义了一个弱引用性质的替身。
    一般用在block上,因为block会copy它内部的变量,可能会造成循环引用,使用__weak性质的self代替self,可以切断block对self的应用,避免循环使用。如

     1 if (nil == error) {
     2     __weak typeof(self) weakSelf = self;
     3     dispatch_async(dispatch_get_global_queue(0, 0), ^{
     4         /*异步解析*/
     5         NSArray  *array = EncodeArrayFromDic(jsonItems,@"data");
     6                 
     7         NSMutableArray *arrayDtos = [NSMutableArray array];
     8         for (NSDictionary *item in array) {
     9             DocMsgModel *dto = [DocMsgModel parser:item];
    10             if (nil != dto) {
    11                 [arrayDtos addObject:dto];
    12             }
    13         }
    14                 
    15         dispatch_async(dispatch_get_main_queue(), ^{
    16             [weakSelf.delegate manageMainView];
    17         });
    18     });
    19 }

     

    block可以把函数当做属性来声明,虽然也可以直接在.h中写方法,这两种写法作用是一样的,只是写法不同。如下
    在TableCell.h中

    1 @property (nonatomic,strong) UIView *cellDownBg;
    2 @property (nonatomic,copy) void(^deleteBtnClickBlock)(NSString *contentID);
    3 //该block写法和下边的作用一样
    4 //-(void)deleteBtnClick:(NSString *)contentId;

    然后使用block时还需设置self(指的是controller)为weak型
    在controller的.m中,

    1 -(void)someFunction{
    2     __weak typeof(self) weakSelf = self;
    3     TableCell *cell = [[TableCell alloc] init];
    4     cell.deleteBtnClickBlock = ^(NSString *contentID){
    5         [weakSelf deleteContentWithContentId:contentID];
    6     }
    7 }

     

    下面说下block比较详细的用法

    第一部分:block形式
    block有三种形式,关于参数和返回值的。
    ①无参数,无返回值

    -(void)viewDidLoad {
        [super viewDidLoad];
    
        void(^printSth)() = ^(){
            printf("没有数字
    ");
        }
        printSth();
    }

    打印结果为:

    ②有参数,无返回值

    -(void)viewDidLoad {
        [super viewDidLoad];
    
        printTheNum(55);
    }
    
    void(^printTheNum)(int) = ^(int val){
        printf("the num is %d 
    ",val);
    };

    打印结果为:

    ③有参数,有返回值

    -(void)viewDidLoad {
        [super viewDidLoad];
    
        int localNum = 7;
        int (^printElse)(int) = ^(int num){
            return num * localNum;
        };
    
        int newNum = printElse(3);
        printf("new localNum is %d 
    ",newNum);
    }

    打印结果为:

    由上可以看出,block既可以定义在方法(如viewDidLoad)内部,也可以定义在方法外部。

    第二部分:__block关键字的使用
    在block的{}内,是不可以对外面的变量进行赋值的。如:

    1 - (void)viewDidLoad {
    2     [super viewDidLoad];
    3 
    4     int localNum = 7;
    5     int (^myBlock)(int) = ^(int num){
    6         localNum = num * 3;
    7         return num * localNum;
    8     };
    9 }

    此时会有Variable is not assignable (missing __block type specifier)的错误提示。

    加上__block,就可以修改了。

    第三部分:不同类间的传值
    block作用如同函数,当用作property时,可以在两个类之间传值。如:
    两个controller,分别为A和B,A中有label,B中有textfield。当跳往B后,点击按钮再返回A。label显示textfield的内容。
    ①用delegate实现
    在B的.h中

    @protocol ThirdViewControllerDelegate <NSObject>
    
    @optional
    -(void)transferTheVal:(NSString *) textVal;
    
    @end
    
    @interface ThirdViewController : UIViewController
    
    @property(nonatomic,assign) id<ThirdViewControllerDelegate> delegate;
    
    @end

    在B的.m中

    -(void)clickTheBtn{
        [self.navigationController popViewControllerAnimated:YES];
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(transferTheVal:)]) {
            [self.delegate transferTheVal:self.textFirldAll.text];
        }
    }

    在A的.m中

    @interface ViewController ()<ThirdViewControllerDelegate>
    @property(nonatomic,strong) UILabel *myLab;
    @end
    
    -(void)transferTheVal:(NSString *)textVal{
        self.myLab.text = textVal;
    }

    ②用block实现
    在B的.h中

    @interface NextViewController : UIViewController
    
    @property(nonatomic,strong) UITextField *textFirldAll;
    
    @property(nonatomic,copy) void(^nextControlBlock)(NSString *textVal);
    
    @end

    在B的.m中

    -(void)clickTheBtn{
        [self.navigationController popViewControllerAnimated:YES];
        
        if (self.nextControlBlock) {
            self.nextControlBlock(self.textFirldAll.text);
        }
    }

    在A的.m中

     1 -(void)clickTheBtn{
     2     NextViewController *nextVC = [[NextViewController alloc] init];
     3     [self.navigationController pushViewController:nextVC animated:YES];
     4     __weak typeof(self) weakSelf = self;
     5     //block中应为weak型的self,防止循环引用
     6     nextVC.nextControlBlock = ^(NSString *textVal){
     7         [weakSelf resetTextVal:textVal];
     8     };
     9 }
    10 
    11 -(void)resetTextVal:(NSString *)newVal{
    12     self.myLab.text = newVal;
    13 }

    由此可以看出delegate和block两种用法的异同

     

    ************************** 2015-10-08 补充 **************************

    block也可以在函数中使用,作为参数类型。

    //参数为changed,类型为void(^)(void)
    - (void)doSth:(void(^)(void))changed;
    //参数squre的类型为int(^)(int)型
    -(void)objcMethod:(int(^)(float))squre;

    使用时有

    - (void)doSth:(void(^)(void))changed{
        //其它的其它操作
        //执行block
        changed();
    }
    
    -(void)objcMethod:(int(^)(float))squre{
        squre(3.0);
    }

    void(^)(void)表示无参数无返回值,int(^)(float)表示参数为float,返回值为int

    由这两种写法可以看出,当block作为参数类型时,代码格式---中间的(^)是必须的

    使用block需要注意的问题

    ①在调用block时必须做非空判断,否则会崩溃

    void (^logPrint)() = ^{
        NSLog(@"*********");
    };
    
    if (nil != logPrint) {
        logPrint();
    }

    ②对于比较长的block,尽量用typedef定义新的名称来代替block。typedef的用法如下:

    typedef int MyInt;
    //与int a = 10 等价
    MyInt a = 10;

    意为将int类型用MyInt代替,这样比较直观。对于block类型,写法不太一样。

    //两数相加
    int(^plusNum)(int,int) = ^(int a,int b){
        return a+b;
    };
    
    //两数相减
    int(^minusNum)(int,int) = ^(int a,int b){
        return a-b;
    };

    用typedef重新定义

    typedef int(^twoNum)(int num1,int num2);

    表示返回值为int类型,参数有两个,且都为int类型,block名称为twoNum。
    使用时可以

    -(void)viewDidLoad{
        [super viewDidLoad];
    
        //两数相加
        twoNum plusNu = ^(int a,int b){
            return a + b;
        };
        
        //两数相减
        twoNum minusNu = ^(int a,int b){
            return a - b;
        };
        
        plusNu(4,2);
        minusNu(3,5);
    }

    对于对象类型的block,有参数有返回值的写法

    NSString * (^myName)(NSString *a,NSString *b) = ^(NSString *firstName,NSString *lastName){
        NSString *name = [firstName stringByAppendingString:lastName];
        NSLog(@"my Name is %@",name );
        return name;
    };

    用typedef定义时

    typedef NSString * (^MyName) (NSString *firstName,NSString *lastName);
    -(void)viewDidLoad{
        [super viewDidLoad];
    
        MyName nameL = ^(NSString *firstName,NSString *lastName){
            NSString *name = [firstName stringByAppendingString:lastName];
            NSLog(@"----%@",name);
            return name;
        };
        nameL(@"Xi",@"Li");
    }

    可以看出,作用一样,只是形式上更简洁。尽量使用typedef这种写法。

    *********** 2016-04-12补充  *****************

    block作为代码块,可以用在属性、方法中。示例如下:

    #pragma mark —— block作为属性

    //无参数,无返回值
    @property(nonatomic,copy) void(^test1)();
    //无参数,有返回值
    @property(nonatomic,copy) NSString *(^test2)();
    //有参数,有返回值
    @property(nonatomic,copy) NSString *(^test3)(NSString *firstName,NSString *lastName);

    #pragma mark —— block作为方法的参数

    //无参数,无返回值
    -(void)testOne:(void(^)()) testBlock;
    //无参数,有返回值
    -(void)testTwo:(NSString *(^)()) testBlock;
    //有参数,有返回值
    -(void)testThree:(NSString *(^)(NSString *num1,NSString *num2)) testBlock;
  • 相关阅读:
    P1131 [ZJOI2007]时态同步(树形dp)
    P2831 愤怒的小鸟(状压dp)
    bzoj2456 / P2397 yyy loves Maths VI (mode)
    P1879 [USACO06NOV]玉米田Corn Fields(状压dp)
    P1026 统计单词个数
    P2679 子串
    数据库合并工具 esql
    在游戏中实现语音聊天和语音转化成文字
    在游戏中实现语音聊天和语音转化成文字
    类型强转的那些坑
  • 原文地址:https://www.cnblogs.com/Apologize/p/4775830.html
Copyright © 2020-2023  润新知