2017-08-29 45 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