2015-02-07 75 views
1

我有一个块正在检查用户从firebase中的状态属性。如果状态属性是“自由”我想从块返回,否则我想搜索其他用户,并检查他们的身份和这样做,直到一个“自由”的用户已经发现:一个块内的块被调用后出现不良访问(iOS)

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)”低于行:

-(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); 
}]; 
} 

一切都很好,如果块没有被被召回并且被检查的第一个用户已经是“免费”的。我被困在为什么我得到这个错误/崩溃,并想知道我能如何解决它!

谢谢!

+0

在checkIfFree中复制comp块: – malex 2015-02-07 23:24:02

+0

我该怎么做? – ryder 2015-02-07 23:27:20

+0

myCompletion copyBlock = [compblock copy]; – malex 2015-02-07 23:29:59

回答

2

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

你可以做的一件事就是将你的块声明为__block变量。

__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]; 
    } 
} 
+0

真棒,感谢您的帮助! – ryder 2015-02-08 00:03:24

+0

你有一个保留周期。 'myResponseBlock'对自己有很强的参考。 – newacct 2015-02-09 09:30:26

+0

谢谢@newacct我已经更新了我的答案。 – ozgur 2015-02-09 09:44:57

2

我认为你仍然可能有错误,因为你所有的块都在堆栈上创建。所以如果发生任何异步,myResponseBlock将会消失。

我推荐的是你的副本(使用具有副本属性的属性)你的myResponse块进入一个属性,并从那里重用它。这样,当你的块被设置为零时,你的块就会在堆上消失并消失。

相关问题