关于ios:零__弱自我 – 为什么会发生?

nil __weak self - Why it's happend?

我想在街区里使用软弱的自我,但在街区里,这个懦夫变成了零。

刚刚创建,在块之前(尝试使用不同的变体)-看起来都可以

enter image description here

但后来在块-每个变种零

enter image description here

怎么了?有人能解释吗?

编辑

1
2
SPHVideoPlayer *videoPlayer = [[SPHVideoPlayer alloc] initVideoPlayerWithURL:urlToFile];
[videoPlayer prepareToPlay];

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma mark - LifeCycle

- (instancetype)initVideoPlayerWithURL:(NSURL *)urlAsset
{
    if (self = [super init]) {
        [self initialSetupWithURL:urlAsset];
    }
    return self;
}

- (void)initialSetupWithURL:(NSURL *)url
{
    NSDictionary *assetOptions = @{ AVURLAssetPreferPreciseDurationAndTimingKey : @YES };
    self.urlAsset = [AVURLAsset URLAssetWithURL:url options:assetOptions];
}

以及使用块的方法

1
2
3
4
5
6
7
8
9
10
11
- (void)prepareToPlay
{
    __weak typeof(self) weakSelf = self;
    __weak SPHVideoPlayer *weakSealf2 = self;
    NSArray *keys = @[@"tracks"];
    [self.urlAsset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf startLoading];
        });
    }];
}


正如Rckoenes所说,这个SPHVideoPlayer已经超出范围,正在被释放。假设您不想释放它,您只需选择一个保持它的作用域(例如,使其成为显示视频的视图控制器的属性)。

您描述了使用weakSelf来防止"保留周期"(现在通常称为"强参考周期")。是的,使用weakSelf模式来防止强参考周期。从技术上讲,还不完全清楚你一定有一个很强的参考周期。它取决于loadValuesAsynchronousForKey...实现的细节(例如,是否将此块加载到某些类属性中,从而创建从类到self的块类属性引用的强引用循环,从而保持对self的强引用)。

但这都有点学术性:尽管如此,weakSelf模式还是谨慎的,因为它准确地反映了适当的对象图(块没有业务"拥有"和/或维护对视频播放器的强引用)。不过,巧合的是,当您使用weakSelf时,它也消除了强参考周期的潜在风险。

真正的问题是,您可能不仅希望在加载资产时将视频播放器保持在作用域内,而且希望在播放视频时也保持在作用域内,因此您可能希望更改视频播放器的作用域,而不管(可能是为了与呈现视频播放器的视图控制器相匹配)。


这就是弱变量的概念:弱变量不包含引用计数,因此如果弱变量是保留在对象上的唯一对象,则对象将被释放,弱变量将为零。这是弱变量应该如何工作和应该如何使用的100%。

如果你使用了一个强引用,那么你的代码块将是唯一仍然保留着self的代码,你对self所做的所有工作都将是毫无意义的,因为没有其他人会注意到它。由于使用的是弱变量,因此可以通过检查变量是否为零来避免这种情况。

在多线程环境中,最后一个强引用可能随时消失,而您的弱引用可能随时变为零。通过将弱变量复制到强变量中来避免这种情况,因为这是块中的第一件事情,所以您知道在进入块之前,弱变量可能已经消失,但在块执行期间,它不会消失。


对块具有弱引用的原因是不使用块保留类。当实例不再存在时,弱引用得到零,因此您需要相应地处理弱引用(在代码中这样做)。如果这不是您想要实现的,您需要确保您的实例没有解除分配,但这与您的块无关…