![](/img/trans.png)
[英]When should I use weakself in a block, and why there is no retain cycle in Masonry?
[英]iOS - Should I be calling “weakSelf” in this block?
好的,所以我可能还没有完全掌握什么时候我应该在块中使用weakSelf
。 我知道这是为了防止保留周期而不是,但我听说这个规则有一些例外。
在下面的代码中,我检查API调用是否由于登录会话到期而失败,然后我尝试重新验证用户并通过调用[self sendTask:request successCallback:success errorCallback:errorCallback];
重试因此问题而失败的API请求[self sendTask:request successCallback:success errorCallback:errorCallback];
在重新认证方法的成功块中:
/*!
* @brief sends a request as an NSHTTPURLResponse. This method is private.
* @param request The request to send.
* @param success A block to be called if the request is successful.
* @param error A block to be called if the request fails.
*/
-(void)sendTask:(NSURLRequest*)request successCallback:(void (^)(NSDictionary*))success errorCallback:(void (^)(NSString*))errorCallback
{
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[self parseResponse:response data:data successCallback:success errorCallback:^(NSString *error) {
//if login session expired and getting "not authenticated" error (status 401)
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 401) {
NSLog(@"NOT AUTHENTICATED THO");
AuthenticationHelper* auth = [AuthenticationHelper sharedInstance];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
//attempt to re-authenticate the user
[AuthenticationHelper loginUser:[defaults stringForKey:@"username"] password:[defaults stringForKey:@"password"] successCallback:^(User* u)
{
auth.loggedInUser = u;
NSLog(@"RE-AUTHENTICATION BUG FIX SUCCEEDED");
//attempt to re-try the request that failed due to
[self sendTask:request successCallback:success errorCallback:errorCallback];
} errorCallback:^(NSString *error) {
NSLog(@"RE-AUTHENTICATION BUG FIX FAILED");
}];
}
else {
errorCallback(error);
}
}];
}];
[task resume];
}
这种不良做法是否会导致保留周期? 如果是这样,为什么? 我应该使用[weakSelf sendTask:request successCallback:success errorCallback:errorCallback];
假设我做MyAPIInterface *__weak weakSelf = self;
预先?
在这个例子中,没有保留周期,因为self
没有持有对块的引用。 当块完成时,它将释放其对self
保持,如果这是最后一个引用,则实例将被解除分配,就像您期望的那样。
保留周期肯定是强引用的一个风险,虽然我认为它不适用于这种情况。 在这些回调中对self
的强引用可能会延长self
对象的生命周期,直到它们完成,但看起来块一旦被调用就会被释放,或者当请求失败时,它们将释放它们的强引用,并且self
对象可以被释放。
但是,您仍然可以看到这些强引用导致的意外行为。 这些强引用可以使这个对象保持活着,直到这些请求完成。 这可能会导致您希望在请求完成时将某个对象保留在内存中,并在将来远程更改应用程序状态。
作为一个可能的例子; 假设您启动其中一个请求,然后用户退出并登录到其他帐户。 请求可能会失败,然后使用第二个用户帐户的凭据重试。 这可能不是用户想要的结果。
也许这在这个应用程序中实际上是不可能的,但如果您使用这样的强引用,则需要考虑它,并在每次更改应用程序与此对象交互的方式时重新考虑它。 这导致一个类很难重用甚至是危险的。 如果改为谨慎使用的strong
和weak
,你可以写一个类,它不会变得耦合到应用的静止状态。
在这种情况下正确使用弱引用可能比您预期的要复杂一些。 创建一个弱保留的self
版本肯定是正确的第一步:
__weak __typeof__(self) weakSelf = self
这给了我们一个weakSelf
,如果self
在执行完成块之前被释放,那么它将是nil,但是根据你的并发模型, 在执行完成块期间可能会释放self
。 因此,我们通常要创建一个有力的参考作为我们的块中第一个操作,这样,如果self
当块开始执行它会一直保持到块结束,该强引用被丢弃,依然存在:
__strong __typeof__(self) strongSelf = weakSelf
许多objective-c库和项目将这些语句提取为weakify
和strongify
宏,这可能会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.