猿问

总是在ARC中将自身的弱引用传递给块吗?

我对Objective-C中的块用法有些困惑。我当前使用的是ARC,我的应用程序中有很多块,当前总是引用self而不是其弱引用。这可能是这些块保留self并阻止其分配的原因吗?问题是,我应该始终在块中使用的weak引用self吗?


-(void)handleNewerData:(NSArray *)arr

{

    ProcessOperation *operation =

    [[ProcessOperation alloc] initWithDataToProcess:arr

                                         completion:^(NSMutableArray *rows) {

        dispatch_async(dispatch_get_main_queue(), ^{

            [self updateFeed:arr rows:rows];

        });

    }];

    [dataProcessQueue addOperation:operation];

}

ProcessOperation.h


@interface ProcessOperation : NSOperation

{

    NSMutableArray *dataArr;

    NSMutableArray *rowHeightsArr;

    void (^callback)(NSMutableArray *rows);

}

流程操作


-(id)initWithDataToProcess:(NSArray *)data completion:(void (^)(NSMutableArray *rows))cb{


    if(self =[super init]){

        dataArr = [NSMutableArray arrayWithArray:data];

        rowHeightsArr = [NSMutableArray new];

        callback = cb;

    }

    return self;

}


- (void)main {

    @autoreleasepool {

        ...

        callback(rowHeightsArr);

    }

}


吃鸡游戏
浏览 440回答 3
3回答

catspeake

这不仅有助于把重点放在strong或weak讨论的一部分。而是专注于循环部分。保留周期是当对象A保留对象B 而对象B保留对象A 时发生的循环。在这种情况下,如果释放了任何一个对象,则:因为对象B拥有对它的引用,所以不会释放对象A。但是,只要对象A引用了对象B,就永远不会释放它。但是对象A永远不会被释放,因为对象B拥有对它的引用。广告无限因此,即使在一切正常的情况下,这两个对象也应该在程序的生命周期内徘徊,即使它们在一切正常的情况下也应该被释放。因此,我们担心的是保留周期,而创建这些周期的块本身没有任何问题。这不是问题,例如:[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){   [self doSomethingWithObject:obj];}];该块保留self,但self不保留该块。如果释放一个或另一个,则不会创建任何循环,并且一切都将按应有的方式释放。您遇到麻烦的地方是这样的://In the interface:@property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);//In the implementation:[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {  [self doSomethingWithObj:obj];     }];现在,您的对象(self)具有strong对该块的显式引用。并且该块具有对的隐式强引用self。这是一个周期,现在两个对象都不会被正确释放。因为在这样的情况下,self 根据定义,已经有strong对该块的引用,所以通常最容易解决的方法self是为该块使用一个显式的弱引用:__weak MyObject *weakSelf = self;[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {  [weakSelf doSomethingWithObj:obj];     }];但这不应该是您在处理调用块时遵循的默认模式self!这仅应用于打破在self和block之间的保留循环。如果要在所有地方都采用这种模式,则冒着将块传递给在self释放后执行的操作的风险。//SUSPICIOUS EXAMPLE:__weak MyObject *weakSelf = self;[[SomeOtherObject alloc] initWithCompletion:^{  //By the time this gets called, "weakSelf" might be nil because it's not retained!  [weakSelf doSomething];}];

温温酱

您不必总是使用弱引用。如果您的块没有保留,而是被执行然后丢弃,则可以强烈地捕获自身,因为它不会创建保留周期。在某些情况下,您甚至希望该块保留自身,直到该块完成为止,这样它才不会过早地解除分配。但是,如果您强烈捕获该块,并在捕获自身内部,则会创建一个保留周期。

慕容708150

但这不应该是您在处理称为self的块时遵循的默认模式!这仅应用于打破在self和block之间的保留循环。如果要在所有地方都采用这种模式,则冒着将块传递给在释放self之后执行的操作的风险。//SUSPICIOUS EXAMPLE:__weak MyObject *weakSelf = self;[[SomeOtherObject alloc] initWithCompletion:^{  //By the time this gets called, "weakSelf" might be nil because it's not  retained!  [weakSelf doSomething];}];为了克服这个问题,可以weakSelf在块内部定义一个强引用:__weak MyObject *weakSelf = self;[[SomeOtherObject alloc] initWithCompletion:^{  MyObject *strongSelf = weakSelf;  [strongSelf doSomething];}];
随时随地看视频慕课网APP

相关分类

iOS
我要回答