调用块中的块后访问错误(iOS)

调用块中的块后访问错误(iOS),ios,firebase,objective-c-blocks,exc-bad-access,Ios,Firebase,Objective C Blocks,Exc Bad Access,我有一个从firebase检查用户状态属性的块。如果status属性为“free”,我希望从块返回,否则我希望搜索其他用户并检查其状态,直到找到“free”用户: void( ^ myResponseBlock)(BOOL finished) = ^ void(BOOL finished) { if (finished) { if ([self.freedom isEqualToString: @"free"]) { NSLog(@"free!"); r

我有一个从firebase检查用户状态属性的块。如果status属性为“free”,我希望从块返回,否则我希望搜索其他用户并检查其状态,直到找到“free”用户:

void( ^ myResponseBlock)(BOOL finished) = ^ void(BOOL finished) {

if (finished) {
    if ([self.freedom isEqualToString: @"free"]) {
        NSLog(@"free!");
        return;
    } else if ([self.freedom isEqualToString: @"matched"]) {
        NSLog(@"get another user");
        //get another user
        do {
            //picking another random user from array
            rando = arc4random_uniform(arraycount);
        }

        while (rando == randomIndex && rando == [self.randString intValue]);
        self.randString = [NSString stringWithFormat: @"%u", rando];
        [users removeAllObjects];
        [users addObject:usersArray[rando]];
        self.freeUser = users.firstObject;

        NSLog(@"set up another check");

        //error is called after this block is called here, again
        [self checkIfFree: myResponseBlock];

    } else {
        NSLog(@"error!");
    }
} else {
    NSLog(@"not finished the checking yet");
}
};
[self checkIfFree: myResponseBlock];
如图所示,当在下面的“compblock(YES)”行上第二次调用块时,我得到一个错误“BAD ACCESS”:

-(void)checkIfFree:(myCompletion) compblock{

self.freeUserFB = [[Firebase alloc] initWithUrl:[NSString stringWithFormat: @"https://skipchat.firebaseio.com/users/%@", self.freeUser.objectId]];

[self.freeUserFB observeEventType:FEventTypeValue  withBlock:^(FDataSnapshot *snapshot)
 {
     self.otherStatus = snapshot.value[@"status"];

     NSLog(@"snapshot info %@", snapshot.value);

     if ([self.otherStatus isEqualToString:@"free"]) {
         self.userIsFree = YES;
         self.freedom = @"free";
         NSLog(@"user is free in the check method %@", self.freedom);
     }
     else{
         self.userIsFree = NO;
         self.freedom = @"matched";
         NSLog(@"user is matched in the check method %@", self.freedom);

     }
     compblock(YES);
 }];
}
如果不需要调用块,并且检查的第一个用户已经是“空闲”的,那么一切都很好。我一直在想为什么会出现这个错误/崩溃,并想知道如何解决它


谢谢

A
block
捕获传入的所有变量,包括其自身,但是变量
myResponseBlock
尚未在块内初始化。因此,您正在使用
nil
值调用
checkIfFree
方法,从而导致应用程序崩溃

要克服这个问题,可以做的一件事是将块声明为
\uu块
变量

__block __weak void(^weakResponseBlock)(BOOL);

void(^myResponseBlock)(BOOL);

weakResponseBlock = myResponseBlock = ^void(BOOL finished) {
    ...
    if (weakResponseBlock) {
       [self checkIfFree:weakResponseBlock];
    }
}
此外,请注意,块保留传递给它们的所有变量。在这种情况下,您将在块内保留self,所以只要块执行,它就永远不会被释放。因此,除非另有要求,否则始终向块传递弱引用

__weak UIViewController *weakSelf = self;

weakResponseBlock = myResponseBlock = ^void(BOOL finished) {
    ...
    if (weakResponseBlock) {
       [weakSelf checkIfFree:weakResponseBlock];
    } 
}

捕获传入的所有变量,包括自身,但是变量
myResponseBlock
尚未在块内初始化。因此,您正在使用
nil
值调用
checkIfFree
方法,从而导致应用程序崩溃

要克服这个问题,可以做的一件事是将块声明为
\uu块
变量

__block __weak void(^weakResponseBlock)(BOOL);

void(^myResponseBlock)(BOOL);

weakResponseBlock = myResponseBlock = ^void(BOOL finished) {
    ...
    if (weakResponseBlock) {
       [self checkIfFree:weakResponseBlock];
    }
}
此外,请注意,块保留传递给它们的所有变量。在这种情况下,您将在块内保留self,所以只要块执行,它就永远不会被释放。因此,除非另有要求,否则始终向块传递弱引用

__weak UIViewController *weakSelf = self;

weakResponseBlock = myResponseBlock = ^void(BOOL finished) {
    ...
    if (weakResponseBlock) {
       [weakSelf checkIfFree:weakResponseBlock];
    } 
}

我仍然认为您可能有一个错误,因为您的所有块都是在堆栈上创建的。因此,如果发生任何异步情况,myResponseBlock将消失


我建议您将myResponse块复制(使用具有copy属性的a属性)到属性中,并从中重用它。这样,当self设置为nil时,您的块将位于堆上并消失

我仍然认为您可能有一个错误,因为您的所有块都是在堆栈上创建的。因此,如果发生任何异步情况,myResponseBlock将消失


我建议您将myResponse块复制(使用具有copy属性的a属性)到属性中,并从中重用它。这样,当self设置为nil时,您的块将位于堆上并消失

在checkifree中复制comp块:我该怎么做?myCompletion copyBlock=[compblock copy];在checkifree中复制comp块:我该怎么做?myCompletion copyBlock=[compblock copy];你有一个保留周期
myResponseBlock
对自身有很强的引用。您有一个保留周期
myResponseBlock
对自身有很强的引用。