如果没有在块内检测到nil?

时间:2014-12-26 17:21:28

标签: ios cocoa block avplayer avplayeritem

我有一个这个观察者的AVPLayer

  __weak typeof(self.player) myPlayer = self.player;

  myself.timer = [myself.player addPeriodicTimeObserverForInterval:interval
                                                         queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
                                                    usingBlock: ^(CMTime time) {

          if (myself.runAfterEveryFrame) {
            Float64 currentTime = CMTimeGetSeconds([myPlayer currentTime]);
            myself.runAfterEveryFrame(currentTime);  // crashes here
          }

  }];

玩家在self.player

此应用程序按顺序加载电影。当电影结束时,该应用会创建一个全新的AVPlayer,加载该资源并将其存储在self.player上。类似的东西:

AVPlayer *newPlayer = ... init new player
// load assets, create new periodic observers, etc.
// new player is ready
self.player = newPlayer;

这样可以正常工作但是在播放了3或4部电影之后,它就崩溃了

 myself.runAfterEveryFrame(currentTime);  // crashes here

myself = nil

这是个问题。有这个,如果

          if (myself.runAfterEveryFrame) {
            Float64 currentTime = CMTimeGetSeconds([myPlayer currentTime]);
            myself.runAfterEveryFrame(currentTime);  // crashes here
          }

runAfterEveryFrame是在每帧之后运行的代码块。如果myselfnil,这两行是如何执行的?怎么会这样?

如果我自己为零,那么myself.runAfterEveryFramenilif内的内容不应该运行,但它正在if内运行并崩溃。

2 个答案:

答案 0 :(得分:2)

假设myself是弱引用,例如myPlayer(您未在问题中说明),可以随时取消分配,包括在if块内。要解决此问题,请在块内创建一个强引用:

__strong typeof(myself) strongSelf = myself;
__strong typeof(myPlayer) strongPlayer = myPlayer;

if (strongSelf.runAfterEveryFrame) {
    Float64 currentTime = CMTimeGetSeconds([strongPlayer currentTime]);
    strongSelf.runAfterEveryFrame(currentTime);
}

此外,您应该检查CMTimeGetSeconds是否返回NaN或无穷大是安全的。

答案 1 :(得分:-1)

在异步块内第二次使用弱变量是不安全的,所以总是将弱转换为块内的强变量。所以自我被捕获弱,但保留在块

    __weak myType *weakType = self;

    //dispatch block

   //INSIDE block
    __strong myType *strongType = weakType;