关于block的一点思考--底层可否用全局保存上层传下来的block

来源:互联网 发布:做一个软件多少钱 编辑:程序博客网 时间:2024/04/29 16:25


关于block的一点思考


上层传下来的block,用全局保存,那么上层可以嵌套这个block吗?

block在执行中又对全局block重新赋值,会出现什么问题吗,为什么?



以下demo,BlockTest模拟底层提供api,

 fun1: Block: 模拟api接收block入参并保存block副本,

底层处理完事情后,执行保存在全局的block


测试方法中,block执行过程中又调用了BlockTest的fun1: block:方法

这时底层全局block还没执行完,又被自身在执行过程中赋值上新的block

赋值之后还没执行完的block是否能正常继续执行呢?


.h文件

#import <Foundation/Foundation.h>



typedefint(^TestBlock)(int p1);



@interface BlockTest :NSObject


-(int)fun1:(int)p1 Block:(TestBlock)block;


@end



.m文件

#import "BlockTest.h"



staticTestBlock testBlock;

static int gp1;


@implementation BlockTest


-(int)fun1:(int)p1 Block:(TestBlock)block

{

    NSLog(@"begin fun1 P1=%d thread=%@",p1,[NSThreadcurrentThread]);

   gp1 = p1;

   testBlock = [block copy];

//底层尝试用3种方式来执行block

//    [self performSelectorInBackground:@selector(ExcuteBlock) withObject:nil];

    [selfperformSelector:@selector(ExcuteBlock)withObject:nilafterDelay:0.1];

//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),/* dispatch_get_main_queue(),*/ ^{

//        [self ExcuteBlock];

//    });

    

    NSLog(@"end fun1 P1=%d ",p1);

   return 0;

}


-(void)ExcuteBlock

{

    NSLog(@"befor testBlock p1=%d thread=%@",gp1,[NSThreadcurrentThread]);

    testBlock(gp1);//如果有嵌套,那么这句在执行过程中会把自身给替换掉,这时替换语句后面的代码,以及下面的代码是否能正常继续运行

    NSLog(@"after testBlock p1=%d thread=%@",gp1,[NSThreadcurrentThread]);

    

}


-(void)dealloc{

    NSLog(@"dealloc %@",self);

}


@end



测试方法


-(void)testNestedGlobalBlock

{

   BlockTest * blockTest = [[BlockTestalloc] init];

    [blockTestfun1:1 Block:^int(int p1) {

        NSLog(@"begin block 1");

        NSLog(@"即将替换掉当前执行的block");

        [blockTestfun1:2 Block:^int(int p1) {

            NSLog(@"begin block 2");

            

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

               NSLog(@"dispatch_after");

            });

            

           NSLog(@"end block 2");

           return 2;

        }];

        NSLog(@"被替换后,block继续运行");

        NSLog(@"end block 1");

       return 1;

    }];

    

    NSLog(@"testNestedGlobalBlock over");

}


测试结果

底层模拟了3种方式来执行方法,从而执行block,下面是执行过程中的输出结果

从这3种输出结果来看,正在执行中得block,虽然其对应的全局变量被替换掉了,但却还能正常往下执行


 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),/* dispatch_get_main_queue(),*/ ^{

        [selfExcuteBlock];

    });

2015-01-07 15:15:38.820 test[1278:36599] begin fun1 P1=1 thread=<NSThread: 0x7ffa0b42ee20>{number = 1, name = main}

2015-01-07 15:15:38.821 test[1278:36599] end fun1 P1=1 

2015-01-07 15:15:38.821 test[1278:36599] testNestedGlobalBlock over

2015-01-07 15:15:39.852 test[1278:36676] befor testBlock p1=1 thread=<NSThread: 0x7ffa0b768190>{number = 2, name = (null)}

2015-01-07 15:15:39.852 test[1278:36676] begin block 1

2015-01-07 15:15:39.853 test[1278:36676]即将替换掉当前执行的block

2015-01-07 15:15:39.853 test[1278:36676] begin fun1 P1=2 thread=<NSThread: 0x7ffa0b768190>{number = 2, name = (null)}

2015-01-07 15:15:39.854 test[1278:36676] end fun1 P1=2 

2015-01-07 15:15:39.854 test[1278:36676]被替换后,block继续运行

2015-01-07 15:15:39.855 test[1278:36676] end block 1

2015-01-07 15:15:39.855 test[1278:36676] after testBlock p1=2 thread=<NSThread: 0x7ffa0b768190>{number = 2, name = (null)}

2015-01-07 15:15:40.866 test[1278:36676] befor testBlock p1=2 thread=<NSThread: 0x7ffa0b768190>{number = 2, name = (null)}

2015-01-07 15:15:40.866 test[1278:36676] begin block 2

2015-01-07 15:15:40.867 test[1278:36676] end block 2

2015-01-07 15:15:40.868 test[1278:36676] after testBlock p1=2 thread=<NSThread: 0x7ffa0b768190>{number = 2, name = (null)}

2015-01-07 15:15:40.868 test[1278:36676] dealloc <BlockTest: 0x7ffa0b527180>

2015-01-07 15:15:40.977 test[1278:36599] dispatch_after




    [selfperformSelectorInBackground:@selector(ExcuteBlock)withObject:nil];

2015-01-07 15:15:14.735 test[1263:36135] begin fun1 P1=1 thread=<NSThread: 0x7ffb10d21c80>{number = 1, name = main}

2015-01-07 15:15:14.737 test[1263:36135] end fun1 P1=1 

2015-01-07 15:15:14.737 test[1263:36135] testNestedGlobalBlock over

2015-01-07 15:15:14.738 test[1263:36218] befor testBlock p1=1 thread=<NSThread: 0x7ffb10c16940>{number = 2, name = (null)}

2015-01-07 15:15:14.738 test[1263:36218] begin block 1

2015-01-07 15:15:14.738 test[1263:36218]即将替换掉当前执行的block

2015-01-07 15:15:14.739 test[1263:36218] begin fun1 P1=2 thread=<NSThread: 0x7ffb10c16940>{number = 2, name = (null)}

2015-01-07 15:15:14.739 test[1263:36219] befor testBlock p1=2 thread=<NSThread: 0x7ffb10e8a170>{number = 3, name = (null)}

2015-01-07 15:15:14.740 test[1263:36219] begin block 2

2015-01-07 15:15:14.740 test[1263:36219] end block 2

2015-01-07 15:15:14.740 test[1263:36219] after testBlock p1=2 thread=<NSThread: 0x7ffb10e8a170>{number = 3, name = (null)}

2015-01-07 15:15:14.741 test[1263:36218] end fun1 P1=2 

2015-01-07 15:15:14.741 test[1263:36218]被替换后,block继续运行

2015-01-07 15:15:14.742 test[1263:36218] end block 1

2015-01-07 15:15:14.838 test[1263:36218] after testBlock p1=2 thread=<NSThread: 0x7ffb10c16940>{number = 2, name = (null)}

2015-01-07 15:15:14.838 test[1263:36218] dealloc <BlockTest: 0x7ffb10c16c10>

2015-01-07 15:15:14.841 test[1263:36135] dispatch_after



    [selfperformSelector:@selector(ExcuteBlock)withObject:nilafterDelay:0.1];

2015-01-07 15:14:12.868 test[1243:35475] begin fun1 P1=1 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:12.869 test[1243:35475] end fun1 P1=1 

2015-01-07 15:14:12.870 test[1243:35475] testNestedGlobalBlock over

2015-01-07 15:14:12.971 test[1243:35475] befor testBlock p1=1 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:12.972 test[1243:35475] begin block 1

2015-01-07 15:14:12.972 test[1243:35475]即将替换掉当前执行的block

2015-01-07 15:14:12.972 test[1243:35475] begin fun1 P1=2 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:12.972 test[1243:35475] end fun1 P1=2 

2015-01-07 15:14:12.972 test[1243:35475]被替换后,block继续运行

2015-01-07 15:14:12.972 test[1243:35475] end block 1

2015-01-07 15:14:12.972 test[1243:35475] after testBlock p1=2 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:13.075 test[1243:35475] befor testBlock p1=2 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:13.075 test[1243:35475] begin block 2

2015-01-07 15:14:13.075 test[1243:35475] end block 2

2015-01-07 15:14:13.076 test[1243:35475] after testBlock p1=2 thread=<NSThread: 0x7ff481c287f0>{number = 1, name = main}

2015-01-07 15:14:13.076 test[1243:35475] dealloc <BlockTest: 0x7ff481d49540>

2015-01-07 15:14:13.180 test[1243:35475] dispatch_after





不过与其在那边担心用全局block会不会有问题,还不如做成局部的,那就不会有问题了吧,

下面这个demo,把block做成类的一个属性



.h文件

#import <Foundation/Foundation.h>


typedefint(^TestBlock)(int p1);



@interface BlockTest2 :NSObject


@property(nonatomic,copy)TestBlock testBlock;


-(int)fun1:(int)p1 Block:(TestBlock)block;


@end


.m文件

#import "BlockTest2.h"


static int gp1;


@implementation BlockTest2


-(int)fun1:(int)p1 Block:(TestBlock)block

{

    NSLog(@"begin fun1 P1=%d thread=%@",p1,[NSThreadcurrentThread]);

   gp1 = p1;

   self.testBlock = block;

//底层尝试用3种方式来执行block

//    [self performSelectorInBackground:@selector(ExcuteBlock) withObject:nil];

//        [self performSelector:@selector(ExcuteBlock) withObject:nil afterDelay:0.1];

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)),dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),/* dispatch_get_main_queue(),*/ ^{

            [selfExcuteBlock];

        });

    

    NSLog(@"end fun1 P1=%d ",p1);

   return 0;

}


-(void)ExcuteBlock

{

    NSLog(@"befor testBlock p1=%d thread=%@",gp1,[NSThreadcurrentThread]);

    self.testBlock(gp1);

    NSLog(@"after testBlock p1=%d thread=%@",gp1,[NSThreadcurrentThread]);

    

}


-(void)dealloc{

    NSLog(@"dealloc %@",self);

}


@end


测试方法


-(void)testNestedMemberBlock

{

   BlockTest2 * blockTest = [[BlockTest2alloc] init];

    [blockTestfun1:1 Block:^int(int p1) {

        NSLog(@"begin block 1");

       BlockTest2 * blockTest1  = [[BlockTest2alloc] init];

        [blockTest1fun1:2 Block:^int(int p1) {

            NSLog(@"begin block 2");

            

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

               NSLog(@"dispatch_after");

            });

            

           NSLog(@"end block 2");

           return 2;

        }];

        

        NSLog(@"end block 1");

       return 1;

    }];

    

    NSLog(@"testNestedMemberBlock over");

}


测试结果


        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)),dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),/* dispatch_get_main_queue(),*/ ^{

            [selfExcuteBlock];

        });

2015-01-07 15:10:50.435 test[1178:33136] begin fun1 P1=1 thread=<NSThread: 0x7feb21e25810>{number = 1, name = main}

2015-01-07 15:10:50.436 test[1178:33136] end fun1 P1=1 

2015-01-07 15:10:50.436 test[1178:33136] testNestedMemberBlock over

2015-01-07 15:10:51.516 test[1178:33228] befor testBlock p1=1 thread=<NSThread: 0x7feb21d65e40>{number = 2, name = (null)}

2015-01-07 15:10:51.516 test[1178:33228] begin block 1

2015-01-07 15:10:51.517 test[1178:33228] begin fun1 P1=2 thread=<NSThread: 0x7feb21d65e40>{number = 2, name = (null)}

2015-01-07 15:10:51.518 test[1178:33228] end fun1 P1=2 

2015-01-07 15:10:51.518 test[1178:33228] end block 1

2015-01-07 15:10:51.518 test[1178:33228] after testBlock p1=2 thread=<NSThread: 0x7feb21d65e40>{number = 2, name = (null)}

2015-01-07 15:10:51.519 test[1178:33228] dealloc <BlockTest2: 0x7feb21d6cae0>

2015-01-07 15:10:52.577 test[1178:33228] befor testBlock p1=2 thread=<NSThread: 0x7feb21d65e40>{number = 2, name = (null)}

2015-01-07 15:10:52.577 test[1178:33228] begin block 2

2015-01-07 15:10:52.578 test[1178:33228] end block 2

2015-01-07 15:10:52.578 test[1178:33228] after testBlock p1=2 thread=<NSThread: 0x7feb21d65e40>{number = 2, name = (null)}

2015-01-07 15:10:52.579 test[1178:33228] dealloc <BlockTest2: 0x7feb21c2a000>

2015-01-07 15:10:52.688 test[1178:33136] dispatch_after




    [selfperformSelectorInBackground:@selector(ExcuteBlock)withObject:nil];

2015-01-07 15:12:03.972 test[1201:34017] begin fun1 P1=1 thread=<NSThread: 0x7fb19870b040>{number = 1, name = main}

2015-01-07 15:12:03.973 test[1201:34017] end fun1 P1=1 

2015-01-07 15:12:03.974 test[1201:34017] testNestedMemberBlock over

2015-01-07 15:12:03.974 test[1201:34093] befor testBlock p1=1 thread=<NSThread: 0x7fb198638ed0>{number = 2, name = (null)}

2015-01-07 15:12:03.974 test[1201:34093] begin block 1

2015-01-07 15:12:03.975 test[1201:34093] begin fun1 P1=2 thread=<NSThread: 0x7fb198638ed0>{number = 2, name = (null)}

2015-01-07 15:12:03.978 test[1201:34094] befor testBlock p1=2 thread=<NSThread: 0x7fb198418880>{number = 3, name = (null)}

2015-01-07 15:12:03.979 test[1201:34094] begin block 2

2015-01-07 15:12:03.979 test[1201:34094] end block 2

2015-01-07 15:12:03.979 test[1201:34094] after testBlock p1=2 thread=<NSThread: 0x7fb198418880>{number = 3, name = (null)}

2015-01-07 15:12:03.980 test[1201:34093] end fun1 P1=2 

2015-01-07 15:12:03.980 test[1201:34093] end block 1

2015-01-07 15:12:03.981 test[1201:34093] dealloc <BlockTest2: 0x7fb198416ef0>

2015-01-07 15:12:03.981 test[1201:34093] after testBlock p1=2 thread=<NSThread: 0x7fb198638ed0>{number = 2, name = (null)}

2015-01-07 15:12:04.030 test[1201:34093] dealloc <BlockTest2: 0x7fb198641a50>

2015-01-07 15:12:04.084 test[1201:34017] dispatch_after



        [selfperformSelector:@selector(ExcuteBlock)withObject:nilafterDelay:0.1];

2015-01-07 15:13:07.607 test[1225:34701] begin fun1 P1=1 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.608 test[1225:34701] end fun1 P1=1 

2015-01-07 15:13:07.609 test[1225:34701] testNestedMemberBlock over

2015-01-07 15:13:07.708 test[1225:34701] befor testBlock p1=1 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.709 test[1225:34701] begin block 1

2015-01-07 15:13:07.709 test[1225:34701] begin fun1 P1=2 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.709 test[1225:34701] end fun1 P1=2 

2015-01-07 15:13:07.709 test[1225:34701] end block 1

2015-01-07 15:13:07.709 test[1225:34701] after testBlock p1=2 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.709 test[1225:34701] dealloc <BlockTest2: 0x7f975952b180>

2015-01-07 15:13:07.811 test[1225:34701] befor testBlock p1=2 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.811 test[1225:34701] begin block 2

2015-01-07 15:13:07.812 test[1225:34701] end block 2

2015-01-07 15:13:07.812 test[1225:34701] after testBlock p1=2 thread=<NSThread: 0x7f975971d4b0>{number = 1, name = main}

2015-01-07 15:13:07.813 test[1225:34701] dealloc <BlockTest2: 0x7f9759606310>

2015-01-07 15:13:07.917 test[1225:34701] dispatch_after




看起来执行也是没问题,且不用当心block被替换掉得问题,因为每次都是给一个新的对象赋值block属性



本来还当心BlockTest作为局部变量,会不会在block实际执行前就销毁了,不过看看日志,发现不会的,原因吗,我也不懂,真的发现自己是那么的无知

还有一点是,block在赋值时,用不用copy,区别在哪?





想多了解block,以下几篇文章可参考下


iOS BlockARC/ARC下的实用总结

http://www.tekuba.net/program/349/


【小测试】你真的知道blocksObjective-C中是怎么工作的吗?(获奖公布)

http://www.cocoachina.com/bbs/read.php?tid=152222


iOSBlock介绍(一)基础

http://mobile.51cto.com/hot-403897.htm


iOSBlock介绍(二)内存管理与其他特性

http://mobile.51cto.com/hot-403914.htm


iOSblock介绍(三)揭开神秘面纱()

http://mobile.51cto.com/hot-403931.htm


iOSblock介绍(四)揭开神秘面纱()

http://mobile.51cto.com/hot-403935.htm



0 0