2015-02-07 27 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塊進入一個屬性,並從那裏重用它。這樣,當你的塊被設置爲零時,你的塊就會在堆上消失並消失。