2016-05-04 187 views
2

我有2個函數將數據追加到數組和一個函數來處理它。我使用dispatch_barrier_sync來防止其他函數在處理它時更改數據。dispatch_barrier_sync上的數組損壞

內追加功能:

autoreleasepool { 
      dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self]() -> Void in    
       self?.bufferVector_.append(data) 
      } 
     } 

處理功能內:

autoreleasepool { 
      dispatch_barrier_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [weak self] in 
       let len = self!.bufferVector_.count 

       if len > numToExtract { 

        isMoreInBuffer = true 
       } 

       for bufferData in self!.bufferVector_ { 

        datas.append(bufferData) 

        cnt += 1 

        if cnt == numToExtract { 

         break; 
        } 
       } 

       self!.bufferVector_.removeRange(Range(start: 0, end: cnt)) 
      } 
     } 

在上述功能,bufferVector是NSData的([NSData的])的陣列

功能工作正常,它不久之後,似乎陣列內的NSData已損壞,並且我收到了EXC_BAD_ACCESS

這是什麼節目,當我嘗試從調試程序來查看bufferVector內容

bufferVector_ = ([NSData]) 8 values 
    [0] = (NSData) 98 bytes 
    [1] = (NSData) 0x16595320 
    [2] = (NSData) 52 bytes 
    [3] = (NSData) 52 bytes 

我可以說,它已損壞,因爲NSData的顯示內存地址,而不是在字節長度

乾杯

+0

與這個問題無關:使用'weak self'然後使用'self!'是沒有意義的。如果你斷言'self'在這個塊完成之前永遠不會消失,那麼使用'unowned self'。如果你想確保'self'在這個塊完成之前不能消失(這是你幾乎可以肯定的意思),那麼就使用默認的(strong)'self'。如果你的意思是「如果在這個運行之前'自我'發生了消失,忽略它',使用'弱'和'自我'。你目前的代碼強加「弱」的成本,但沒有獲得任何安全性。 –

+0

謝謝,我會改變我的邏輯。我可能會用強而不是弱。 – Adrian

+0

@RobNapier你覺得用strongSelf = self來使用守衛怎麼樣? –

回答

2

You can't apply a barrier to a global queue:

您指定的隊列應該是您使用dispatch_queue_create函數創建的併發隊列。如果傳遞給此函數的隊列是串行隊列或全局併發隊列之一,則此函數的行爲與dispatch_sync函數相同。

1

添加到羅布的回答,您可以創建一個隊列,你可以訪問或傳遞給任一方法:

let qosClassUserInit    = QOS_CLASS_USER_INITIATED 
let newConcurrentQueueAttributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, qosClassUserInit, 0) 
let newConcurrentQueue    = dispatch_queue_create("SynchronizedArrayAccess", newConcurrentQueueAttributes) 

然後使用它像:

// Getting elements 
dispatch_sync(newConcurrentQueue) { 

} 

// Setting elements 
dispatch_barrier_async(newConcurrentQueue) { 

} 

相關評論關於你的問題,我個人喜歡早期的迴歸模式,並且防止自己被消失:

someBlock { [weak self]() -> Void in 

    guard let strongSelf = self else { 
    return 
    } 
}