Ако не открива нула вътре в блока?

Имам 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 е блок от код, който се изпълнява след всеки кадър. ако myself е nil, как се изпълняват тези два реда? Как може да бъде?

ако аз съм нула, тогава myself.runAfterEveryFrame е nil и съдържанието в if не трябва да се изпълнява, но работи и се срива в if.


person Duck    schedule 26.12.2014    source източник
comment
Как се определям? __weak MyClass *myself = self; ли е?   -  person JuJoDi    schedule 26.12.2014
comment
Съвет: Включете всички разумни предупреждения в Xcode и компилаторът ще отговори на въпроса ви.   -  person gnasher729    schedule 26.12.2014
comment
Документацията за addPeriodicTimeObserverForInterval:queue:usingBlock: (developer.apple.com/library/mac/documentation/AVFoundation/) казва, че опашката трябва да е серийна опашка. Използвате глобална опашка, която е едновременна опашка. В документацията се казва, че използването на едновременна опашка води до недефинирано поведение.   -  person newacct    schedule 27.12.2014
comment
@newacct - прав си за това! Добър улов!!!! БЛАГОДАРЯ +1   -  person Duck    schedule 27.12.2014


Отговори (2)


второто използване на слаба променлива вътре в асинхронен блок не е безопасно, така че винаги прехвърляйте слабата към силна променлива вътре в блока. така че себе си е заловен слаб, но задържан от блока

    __weak myType *weakType = self;

    //dispatch block

   //INSIDE block
    __strong myType *strongType = weakType;
person Daij-Djan    schedule 26.12.2014
comment
БРИЛЯНТНО!!!!!!!!!!!!!!!!!!!!!!!!!!!! Не знаех, че мога да укрепя слаба препоръка! БЛАГОДАРЯ - person Duck; 26.12.2014

Ако приемем, че 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 или безкрайност, за да сте сигурни.

person Aaron Brager    schedule 26.12.2014
comment
това ми е глупаво ;) по-хубаво написано, но глупаво - person Daij-Djan; 26.12.2014