1

我想在块中使用弱自我,但是在块中这个weakSelf变成了nil

刚刚创建,在块之前(尝试使用不同的变体) - 看起来一切正常

在此处输入图像描述

但后来在块 - 每个变种为零

在此处输入图像描述

做错了什么?谁能解释一下?

编辑

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

初始化

#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];
}

以及使用块的方法

- (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];
        });
    }];
}
4

3 回答 3

5

正如 rckoenes 所建议的,这SPHVideoPlayer超出了范围并正在发布。假设您不希望它被释放,您只需要选择一个保持它的范围(例如,使其成为显示视频的视图控制器的属性)。

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

但这有点学术性:weakSelf尽管如此,该模式还是谨慎的,因为它准确地反映了适当的对象图(该块没有业务“拥有”和/或保持对视频播放器的强引用)。不过巧合的是,当你使用 时weakSelf,它也消除了强引用循环的潜在风险。

真正的问题是,您可能不仅要在加载资产时将视频播放器保持在范围内,而且还要在播放视频时,所以无论如何您都希望更改视频播放器的范围(大概是为了匹配呈现视频播放器的视图控制器。

于 2014-12-02T16:08:19.517 回答
3

这就是弱变量的想法:弱变量保存引用计数,所以如果弱变量是唯一保留对象的东西,则对象将被释放,弱变量将为零。这是弱变量应该如何工作和应该使用的 100% 方式。

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

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

于 2014-12-02T15:22:50.233 回答
1

对块进行弱引用的原因是不将类与块一起保留。当实例不再存在时,弱引用将为零,因此您需要相应地处理弱引用(您在代码中执行此操作)。如果这不是您想要实现的,您需要确保您的实例没有被释放,但这与您的块无关......

于 2014-12-02T14:46:49.243 回答