iOS开发之Block(4)

本文探讨了Objective-C中Block如何直接修改类实例方法中的实例变量,避免了使用__block说明符的需求,并讨论了Block与self引用可能导致的保留环问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

块总能修改实例变量

之前的文章中写了块可以截获当前环境中的局部变量,如果想要修改就要使用 __block 说明符。

但是针对类实例方法中的块,可以直接修改实例变量。

Worker.h

#import <Foundation/Foundation.h>

@interface Worker : NSObject
{
    NSString * _wId;
}

-(id)initWihtId:(NSString *)wId;
-(void)changeId;
-(void)printfWorkerId;

@end

Worker.m

#import "Worker.h"

@implementation Worker
-(id)initWihtId:(NSString *)wId
{
    self = [super init];
    if (self) {
        _wId = wId;
    }
    return self;
}

//将工号统一归零
-(void)changeId
{
    void(^aBlock)() = ^{
        _wId = @"0";
    };
    aBlock();
}

-(void)printfWorkerId
{
    NSLog(@"the current Id is %@",_wId);
}

@end


main.m

#import <Foundation/Foundation.h>

#import "Worker.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        

        Worker *worker = [[Worker alloc]initWihtId:@"2015032801"];
        
        [worker printfWorkerId];
        
        [worker changeId];
        
        [worker printfWorkerId];
        
        
    }
    return 0;
}

打印结果:

2015-03-28 08:10:58.820 Block_Demo[638:22232] the current Id is 2015032801
2015-03-28 08:10:58.821 Block_Demo[638:22232] the current Id is 0
Program ended with exit code: 0

注意事项:

这时候实例变量中的块同时捕捉到了self引用,此时相当于block持用self,若此时对象也持有block,则会造成保留环。

块截获的局部变量保存的是他们的指针

block截获的实例变量结构体中保存的都是他们的指针。

栈块、全局块、堆块

定义块的时候,他是分配在栈上的,也就是说,块只是在定义它的那个范围内有效。

实际使用中可能会写下这样的代码:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        
        printf("please input a number:\n");
        int i;
        scanf("%d",&i);
        void(^aBlock)();
        
        if (i==0) {
            aBlock = ^{
                NSLog(@"you type 0");
            };
        }else{
            aBlock = ^{
                NSLog(@"what fuck you type");
            };
        }
        
        aBlock();
        
        
    }
    return 0;
}

输出:

please input a number:
77
2015-03-28 08:28:26.175 Block_Demo[680:26203] what fuck you type
Program ended with exit code: 0

这时候块可能由于执行范围结束,被销毁,从而输出错误结果。那么来实现一个安全的;

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        
        printf("please input a number:\n");
        int i;
        scanf("%d",&i);
        void(^aBlock)();
        
        if (i==0) {
            aBlock = [^{
                NSLog(@"you type 0");
            }copy];
        }else{
            aBlock = [^{
                NSLog(@"what fuck you type");
            }copy];
        }
        
        aBlock();
        
        //此时块被复制到堆中,只要不被手动释放,则可以随时引用,只有在第一次copy的时候执行复制到堆中的操作,此后的均为引用计数+1,ARC环境下内存自动管理引用计数。MRC下需要手动release。
    }
    return 0;
}

我们实现了栈块和堆块。

现实场景中我们还会经常一种全局块,也就是全局变量。

#import <Foundation/Foundation.h>

void(^block)() = ^{NSLog(@"这里实现一些编译期间确定的内容,相当于一个单例对象");};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        
        block();
        
        //对全局块的copy操作时一个空操作。可以使用全局变量并进行修改。
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值