2017-06-01 51 views
0

在我的應用我有下面的代碼段:編寫等效代碼爲iOS中9

__weak __typeof(self)weakSelf = self; 

_pingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 
              repeats:YES 
               block:^(NSTimer * _Nonnull timer) 

{ 
    __strong __typeof(weakSelf)strongSelf = weakSelf; 
    [strongSelf pingWithBlock:nil]; 
}]; 

這完全在iOS的10+,但我需要的應用程序支持的iOS 9爲好。所以我需要提供一種適用於兩者的方法。

我嘗試這樣做:

__weak __typeof(self)weakSelf = self; 

_pingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 
              target:weakSelf 
              selector:@selector(pingWithBlock:) 
              userInfo:nil 
              repeats:YES]; 

pingWithBlock方法是在同一個類中定義的,它是一個實例方法。

但是,這似乎不工作,這意味着我得到一個不好的內存訪問崩潰。

如果有人有任何建議,將不勝感激。

編輯:下面 感謝@dgatwood解釋代碼修復該問題

- (void)autoPing 
{ 
    _pingTimer = [NSTimer scheduledTimerWithTimeInterval:self.autoCheckInterval 
              target:self 
              selector:@selector(pingWithBlock) 
              userInfo:nil 
              repeats:YES]; 
} 

-(void)pingWithBlock 
{ 
    [self pingWithBlock:nil]; 
} 
+0

你的'pingWithBlock:'方法在哪裏?並定義「不起作用」。 – rmaddy

+0

剛剛更新了我的問題 –

+0

不要編輯你的問題的答案。發佈實際的答案。 – rmaddy

回答

0

這是一種奇怪的。 NSTimer保留其目標。也許這不會發生在這種情況下,因爲__weak,但我認爲它無論如何。 *聳聳肩*

無論哪種方式,這聽起來像一個多線程競爭條件:

  • 您的計時器沒有保留的對象,因此它可能消失在任何時間。
  • 別的東西保留對象。
  • 計時器計劃在構造計時器時正在運行的線程的runloop中。
  • 在別的線程中引用另一個對象的引用。
  • 計時器在第一個線程中觸發,並且歸零弱引用未歸零,因爲該對象仍處於摧毀自身的中途。
  • 發生崩潰。

最好的解決方法是讓計時器保留目標對象(通過刪除所有的weakSelf東西)。如果計時器是重複計時器,請提供一種方法來允許處理封閉對象的代碼取消該計時器,並且要小心始終調用它。

+0

謝謝你,閱讀槽你的解釋給我帶來了正確的實施! –

+0

「也許這不會因爲__weak而發生在這種情況下」這是無關緊要的。弱和強是本函數中局部變量的語義。它與如何通過論證無關。只有*值*被傳遞 - 它與變量或所有權語義無關。 – newacct

+0

我相信也是這種情況,這就是爲什麼行爲沒有意義,除非編譯器中存在ARC錯誤,因爲NSTimer根據文檔保留其對象。 Self被自稱的當前方法強制保留(否則該代碼不會運行),並且定時器增加了保留計數,這意味着它應該由定時器保留,即使在其他任何保留它停止執行之後所以,在這個過程的任何時候,保留數不可能降到0,除非我錯過了一些非常微妙的東西。 – dgatwood