ios - 调用 block 内的 block 后的 BAD ACCESS (iOS)

标签 ios firebase objective-c-blocks exc-bad-access

我有一个 block ,我正在从 firebase 检查用户的状态属性。如果状态属性是“免费”,我想从 block 中返回,否则我想搜索另一个用户并检查他们的状态,直到找到一个“免费”用户:

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)”行第二次调用该 block 时,我收到“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);
 }];
}

如果不必召回该 block 并且检查的第一个用户已经“空闲”,那么一切都很好。我不知道为什么会出现此错误/崩溃,并且想知道如何解决它!

谢谢!

最佳答案

一个 block捕获所有传入的变量,包括它自己,但是变量 myResponseBlock尚未在 block 内初始化。因此,您调用checkIfFree带有 nil 的方法值进而导致应用程序崩溃。

您可以做的一件事就是将您的 block 声明为 __block多变的。

__block __weak void(^weakResponseBlock)(BOOL);

void(^myResponseBlock)(BOOL);

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

此外,请注意 block 保留传递给它们的所有变量。在这种情况下,您将 self 保留在 block 内,因此只要 block 执行,它就永远不会被释放。因此,除非另有要求,否则始终传递对 block 的弱引用。
__weak UIViewController *weakSelf = self;

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

关于ios - 调用 block 内的 block 后的 BAD ACCESS (iOS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28388668/

相关文章:

ios - 当我调用 URLSession 任务 task.cancel() 时会发生什么?

ios - 根据条件在第二个 TableView 中添加和删除行

javascript - 用于 firebase 的 Cloud Functions 返回响应 500

objective-c - 如何在回调 block 中异步创建 FetchRequest

ios - block 方法完成后执行方法

ios - 测试静态库中的更改?

ios - 带有动画的 UITableview 重新加载数据

java - 应用程序在到达 RecyclerView Android 末尾时停止

ios - 电子邮件注册方法的 .onCreate 触发器中未定义用户显示名称

objective-c - 我真的可以像这样检查 block 中的实例变量吗?