块回调——当原始对象被释放时
block callbacks -- when original object is deallocated
我正在调用我的 DatabaseManager 来保存在 viewController 中创建的对象,如下所示:
[DatabaseManager addUniqueObject:fooChild key:[fooParent fooChildKey] toObject:self.foo callback:^(BOOL succeeded, NSError *error) {
if (error) {
[[UIApplication sharedApplication] endBackgroundTask:self.sendBackgroundTaskId];
return;
}
[self.tableView reloadData];
[self scrollToBottomAnimated:YES];
}
[[UIApplication sharedApplication] endBackgroundTask:self.sendBackgroundTaskId];
}];
addUniqueObject
是我的 DatabaseManager 中的一个 class 方法(如您所见,我使用 Parse 作为后端):
+ (void)addUniqueObject:(PFObject*)uniqueObject key:(NSString*)key toObject:(PFObject*)object callback:(void(^)(BOOL succeeded, NSError *error))callback {
if (uniqueObject) {
[PFCloud callFunctionInBackground:@"addUniqueObjectToObject"
withParameters:@{@"classKey":[object parseClassName],
@"objectId":[object objectId],
@"keyToAdd":key,
@"objectToAddClassKey":[uniqueObject parseClassName],
@"objectToAddId":[uniqueObject objectId],
}
block:^(NSMutableDictionary *results , NSError *error) {
if (!error) {
callback(YES, error);
}
else {
callback(NO, error);
}
}];
}
}
第一个问题 - 因此,如果我创建了这个对象,然后导航离开并因此在保存执行之前弹出这个 VC,那么 self.tableView
或任何其他 属性 此时我在完成块中引用的是 nil
,对吗?
第二个问题 - 我将完成块传递给 DatabaseManager - 如果原始 VC 被销毁,这个完成对象是否仍然存在?在执行 callback()
之前是否必须检查此块是否存在?
这对我来说似乎没有任何问题,所以直到现在我才质疑它。但我想明白。
不,您的 VC 不会被释放,因为 self
是在块内捕获的。如果你想让它被释放,你应该这样写:
__weak typeof(self) weakSelf = self; // we don't increase retain count here
[DatabaseManager addUniqueObject:fooChild key:[fooParent fooChildKey] toObject:self.foo callback:^(BOOL succeeded, NSError *error) {
__strong typeof(self) self = weakSelf;
// if weakSelf is still not deallocated, it will be retained until block finishes
考虑使用 @strongify/@weakify 代替此代码段。
是的。 callback
由您传递给 callFunctionInBackground:withParameters:block:
的块保留,因此在执行块之前不会释放它。如果你确定没有人会用 callback:nil
调用你的函数,那么你不需要检查它是否仍然存在于完成块中。
我正在调用我的 DatabaseManager 来保存在 viewController 中创建的对象,如下所示:
[DatabaseManager addUniqueObject:fooChild key:[fooParent fooChildKey] toObject:self.foo callback:^(BOOL succeeded, NSError *error) {
if (error) {
[[UIApplication sharedApplication] endBackgroundTask:self.sendBackgroundTaskId];
return;
}
[self.tableView reloadData];
[self scrollToBottomAnimated:YES];
}
[[UIApplication sharedApplication] endBackgroundTask:self.sendBackgroundTaskId];
}];
addUniqueObject
是我的 DatabaseManager 中的一个 class 方法(如您所见,我使用 Parse 作为后端):
+ (void)addUniqueObject:(PFObject*)uniqueObject key:(NSString*)key toObject:(PFObject*)object callback:(void(^)(BOOL succeeded, NSError *error))callback {
if (uniqueObject) {
[PFCloud callFunctionInBackground:@"addUniqueObjectToObject"
withParameters:@{@"classKey":[object parseClassName],
@"objectId":[object objectId],
@"keyToAdd":key,
@"objectToAddClassKey":[uniqueObject parseClassName],
@"objectToAddId":[uniqueObject objectId],
}
block:^(NSMutableDictionary *results , NSError *error) {
if (!error) {
callback(YES, error);
}
else {
callback(NO, error);
}
}];
}
}
第一个问题 - 因此,如果我创建了这个对象,然后导航离开并因此在保存执行之前弹出这个 VC,那么
self.tableView
或任何其他 属性 此时我在完成块中引用的是nil
,对吗?第二个问题 - 我将完成块传递给 DatabaseManager - 如果原始 VC 被销毁,这个完成对象是否仍然存在?在执行
callback()
之前是否必须检查此块是否存在?
这对我来说似乎没有任何问题,所以直到现在我才质疑它。但我想明白。
不,您的 VC 不会被释放,因为
self
是在块内捕获的。如果你想让它被释放,你应该这样写:__weak typeof(self) weakSelf = self; // we don't increase retain count here [DatabaseManager addUniqueObject:fooChild key:[fooParent fooChildKey] toObject:self.foo callback:^(BOOL succeeded, NSError *error) { __strong typeof(self) self = weakSelf; // if weakSelf is still not deallocated, it will be retained until block finishes
考虑使用 @strongify/@weakify 代替此代码段。
是的。
callback
由您传递给callFunctionInBackground:withParameters:block:
的块保留,因此在执行块之前不会释放它。如果你确定没有人会用callback:nil
调用你的函数,那么你不需要检查它是否仍然存在于完成块中。