我有一个名为ServiceBrowser
的班级。在这个类中,我有一个基于块的方法来搜索NSNetServices。
我这样称呼方法:
[_serviceBrowser discoverServicesOfType:@"_theService._tcp."
inDomain:@"local."
didDiscoverServices:^(NSArray *services) {
NSLog(@"Services discovered %@", services);
[UIView fadeView:_button toAlpha:1.0 duration:0.5 completion:nil];
} didRemoveServices:^(NSArray *services) {
NSLog(@"Services removed %@", services);
} failure:^(NSString *message) {
NSLog(@"Failure %@", message);
}];
如果我删除对fadeView:toAlpha:duration:completion:
的呼叫,它会找到服务并将其记录下来。只有当我在这个块中使用self时,Xcode才会崩溃而没有任何错误记录到控制台。
fadeView:toAlpha:duration:completion:
是UIView上的一个类别方法,它接受视图并将其淡入或淡出,这作为一个独立的方法可以正常工作。问题是当我在块中使用_button
时它会崩溃。
我已对此进行过调查,我认为这是一个保留周期。从查看其他问题和博客文章,我应该在块内使用弱自我。
我尝试过使用__block id weakSelf = self;
和typeof(self) __weak w_self = self;
,但都无法使用。
答案 0 :(得分:0)
您可以尝试修改您的类,以便将self
作为方法参数传递,并且该类将引用传递回块:
[_serviceBrowser discoverServicesOfType:@"_theService._tcp." inDomain:@"local." didDiscoverServices:^(NSArray *services, id sender) {
// ^^^^^^^^^ "sender" is "self"
} didRemoveServices:^(NSArray *services) {
} failure:^(NSString *message) {
} fromSender:self];
// ^^^^^^^^^^^^^^^ pass self here
类中的实现将是:
- (void)discoverServicesOfType:(NSString *)type inDomain:(NSString *)domain didDiscoverServices:^(NSArray *, id)discoveredBlock fromSender:(id)sender {
NSMutableArray *services = [NSMutableArray array];
// do some fancy stuff here
discoveredBlock(services, sender);
}
Anc Ainu也可能是对的。请检查对象是否仍然存在。
答案 1 :(得分:0)
您可以尝试使用以下代码来捕获块中self
的弱引用(Foo
是self
的类。)
该块现在也需要注意,UIKit方法将在主线程上执行:
__weak Foo* weakSelf = self;
[_serviceBrowser discoverServicesOfType:@"_theService._tcp."
inDomain:@"local."
didDiscoverServices:^(NSArray *services) {
NSLog(@"Services discovered %@", services);
Foo* strongSelf = weakSelf;
if (strongSelf) {
dispatch_async(dispatch_get_main_queue(), ^{
[UIView fadeView:strongSelf.button
toAlpha:1.0
duration:0.5 completion:nil];
});
}
} didRemoveServices:^(NSArray *services) {
NSLog(@"Services removed %@", services);
} failure:^(NSString *message) {
NSLog(@"Failure %@", message);
}];
当块执行时,self
应取消分配,强引用strongSelf
将为nil
。
为什么从UI元素捕获弱指针优先于捕获强指针?虽然这可能不是导致崩溃的原因,但这是一项重大改进。
强烈下面的块捕获 现在,块的效果是,UI元素self
以证明这一点。请注意,当您直接引用ivar时,例如_button
而不是通过属性self.button
,self
将在块中隐式捕获,也就是说,它将一直保留到块完成之后。< / p>
self
将一直保持活动状态,直到块执行之后,无论何时发生这种情况,无论视图是否可见:用户可能拥有在此期间切换到许多其他视图和控制器。但是,self
在块完成之后才会被释放。这不必要地保留了内存中的资源(可能是大图像),这些资源到目前为止还没有释放。[_serviceBrowser discoverServicesOfType:@"_theService._tcp."
inDomain:@"local."
didDiscoverServices:^(NSArray *services) {
NSLog(@"Services discovered %@", services);
dispatch_async(dispatch_get_main_queue(), ^{
[UIView fadeView:self.button
toAlpha:1.0
duration:0.5 completion:nil];
});
} didRemoveServices:^(NSArray *services) {
NSLog(@"Services removed %@", services);
} failure:^(NSString *message) {
NSLog(@"Failure %@", message);
}];