2017-08-29 66 views
1

我來自Swift到Objective-C,我碰到的一個問題是NSData似乎沒有方法來枚舉Swift數據的UInt8值。其他答案也有類似的標題,但它們都涉及屬性列表,而我只有一桶ASCII字節。具體而言,我想在OBJ - C的複製的代碼是:NSData的NSArray的NSData?

//Find the next newline in ASCII data given a byte offset 
let subset = myData.advanced(by: offset) 
var lineEnd: Data.Index = myData.endIndex 

subset.enumerateBytes({ (memory, idx, stop) in 
    let newline: UInt8 = 10 

    for idx in memory.indices { 
     let charByte = memory[idx] 

     if charByte == newline { 
      lineEnd = idx 
      stop = true; return; 
     } 
    } 
}) 

理想我想辦法一個NSArray轉換爲NSNumbers我可以從提取intValues的陣列。當然,如果有更好的方法,請告訴我。目標是儘可能保持Obj-C代碼與Swift類似,因爲我將同時維護兩個代碼庫。

+0

爲什麼要維護Swift和Objective-C?將Objective-C置於維護模式並跨越新的Swift代碼來覆蓋您替換的內容。維護兩個不合理的代碼庫就是重複工作和錯誤的根源。 – ColGraff

+0

我最初在Swift中編寫了該應用程序,但事實證明,它在App Store二進制託管限制上是4 MB。應用程序中的所有資源都是ASCII文本,我真的無法刪除,所以Swift運行時是唯一可以削減的。所以我重寫Obj-C中的應用程序。當Swift ABI穩定時,我將交換代碼庫。是的,我知道這種情況的荒謬。 – PopKernel

+0

@PopKernel可以在用戶安裝應用程序時遠程下載一些額外資源,以避免重新編碼所有內容。 :) – 2017-08-29 03:09:04

回答

1

訪問NSData字節的唯一好方法是調用它的-bytes方法,該方法爲您提供指向其內部存儲的C指針。

NSData *data = ...; 
const uint8_t *bytes = data.bytes; 
NSUInteger length = data.length; 

for (NSUInteger i = 0; i < length; i++) { 
    uint8_t byte = bytes[i]; 

    // do something with byte 
} 
+0

謝謝,我看到了這種方法,但簽名是const * void使我困惑。這個例子很有幫助! – PopKernel

+1

'const * void'就在那裏,因爲'NSData'對象引用的數據在技術上可以是任何類型,而不僅僅是字節。例如,它可以是一個'uint32_t'數組。你只要把它轉換成任何正確的類型,在這種情況下就是字節。當然,如果你喜歡做一些事情,你也需要注意對齊問題。 –

+1

我應該提到的另一件事:由於'bytes'指針指向'NSData'的內部存儲,所以不要掛在它上面的時間比掛到'NSData'更長。如果你在'NSData'對象被釋放之後嘗試使用'bytes'指針......那麼...... https://www.youtube.com/watch?v=6Ls5j5iz2eA –

0

最接近相當於advancesubdataWithRange。相當於enumerateBytes的是enumerateByteRangesUsingBlock。這會產生這樣的:

NSData *subset = [data subdataWithRange:NSMakeRange(offset, data.length - offset)]; 
__block NSUInteger lineEnd = data.length; 

Byte newline = 10; 

[subset enumerateByteRangesUsingBlock:^(const void * _Nonnull bytes, NSRange byteRange, BOOL * _Nonnull stop) { 
    for (NSInteger index = 0; index < byteRange.length; index++) { 
     Byte charByte = ((Byte *)bytes)[index]; 

     if (charByte == newline) { 
      lineEnd = index + byteRange.location; 
      *stop = true; 
      return; 
     } 
    } 
}]; 

注意,我從你的斯威夫特例如一些變化:

  1. 如果數據是不連續的,你斯威夫特例如返回當前塊中的索引。但我懷疑你想要的位置在subset之內,而不是當前塊。我敢打賭,你從未注意到這一點,因爲NSData塊不連續是非常罕見的。

    但是Swift代碼對我來說看起來不正確。此Objective-C示例報告subset內的偏移量,不在subset內的當前塊內。

  2. 這不是可觀察到的性能差異,但我將newline的定義從枚舉塊中提取出來。爲什麼重複定義?

  3. 如果你真的在尋找一個NSData中的字符,我建議完全避免創建subset。只需使用rangeOfData:options:range:。這會找到你想要的任何東西。

+0

對myData事物有很好的理解。我明天會更詳細地看你的答案,我不應該這樣遲到! ⌛️ – PopKernel