【问题标题】:Convert an Objective-C method into Swift for NSInputStream (convert bytes into double)为 NSInputStream 将 Objective-C 方法转换为 Swift(将字节转换为双精度)
【发布时间】:2014-11-08 20:00:35
【问题描述】:

我在 Objective-C 中有以下代码:

- (double)readDouble
{
    double value = 0.0;

    if ([self read:(uint8_t *)&value maxLength:8] != 8)
    {
        NSLog(@"***** Couldn't read double");
    }

    return value;
}

它有效。但我不知道如何将其转换为 Swift。这是我的代码:

public func readDouble() -> Double {

    var value : Double = 0.0

    var num = self.read((uint8_t *)&value, maxLength:8) // got compiling error here!
    if num != 8 {

    }
}

错误信息是:

不能使用类型为 '($T4, maxLength: IntegerLiteralConvertible)'

有人可以帮忙吗?谢谢

我正在使用的测试数据(1.25):

14 AE 47 E1 7A 14 F4 3F

更新:

一个简单的 c 解决方案,但如何在 Swift 中做到这一点?

double d = 0;
unsigned char buf[sizeof d] = {0};

memcpy(&d, buf, sizeof d);

【问题讨论】:

    标签: ios swift nsinputstream


    【解决方案1】:

    这是 Swift 3 beta 6 的更新版本,与 Martin 不同。

    func binarytotype <T> (_ value: [UInt8], _ : T.Type) -> T
    {
        return value.withUnsafeBufferPointer
        {
            UnsafeRawPointer($0.baseAddress!).load(as: T.self)
        }
    }
    
    func typetobinary <T> (_ value: T) -> [UInt8]
    {
        var v = value
        let size = MemoryLayout<T>.size
        return withUnsafePointer(to: &v)
        {
            $0.withMemoryRebound(to: UInt8.self, capacity: size)
            {
                Array(UnsafeBufferPointer(start: $0, count: size))
            }
        }    
    }
    
    let dd: Double = 1.23456             // -> 1.23456
    let d = typetobinary(dd)             // -> [56, 50, 143, 252, 193, 192, 243, 63]
    let i = binarytotype(d, Double.self) // -> 1.23456
    

    【讨论】:

      【解决方案2】:

      上面的方法对我不起作用,使用 Swift 2 但我发现了一种更简单的方法来进行这种转换,反之亦然:

      func binarytotype <T> (value: [UInt8], _: T.Type) -> T
      {
          return value.withUnsafeBufferPointer
          {
              return UnsafePointer<T>($0.baseAddress).memory
          }
      }
      
      func typetobinary <T> (var value: T) -> [UInt8]
      {
          return withUnsafePointer(&value)
          {
              Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: sizeof(T)))
          }
      }
      
      let a: Double = 0.25
      let b: [UInt8] = typetobinary(a) // -> [0, 0, 0, 0, 0, 0, 208, 63]
      let c = binarytotype(b, Double.self) // -> 0.25
      

      我已经在 Playground 中使用 Xcode 7.2 对其进行了测试。

      【讨论】:

        【解决方案3】:

        这应该可行:

        let num = withUnsafeMutablePointer(&value) {
            self.read(UnsafeMutablePointer($0), maxLength: sizeofValue(value))
        }
        

        解释withUnsafeMutablePointer() 用唯一的参数调用闭包(块) ($0 简写)设置为value 的地址。

        $0 的类型为 UnsafeMutablePointer&lt;Double&gt;read() 期望 UnsafeMutablePointer&lt;UInt8&gt; 作为第一个参数,因此是另一个转换 有必要的。然后将闭包的返回值赋值给num

        【讨论】:

        • 对不起。它不起作用。我得到 "Cannot invoke 'init' with an argument list of type '(UnsafeMutablePointer, maxLength: IntegerLiteralConvertible)'"
        • 好的,我试试。顺便说一句,我不是拒绝你的答案的人。无论如何我都会投票给你。
        • 但似乎结果不正确。结果在哪里?在价值上,我是对的吗?
        • 结果为:num = 8,value = 3.31609222784626e-296
        • @bagusflyer:根据binaryconvert.com/result_double.html?decimal=049046050053,1.25 的二进制“Double”表示为 0x3FF4000000000000。另请注意,iOS 使用 little-endian 表示。我现在用包含00 00 00 00 00 00 F4 3F的数据文件测试了代码,结果是value = 1.25
        猜你喜欢
        • 2010-11-21
        • 1970-01-01
        • 2015-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-10
        • 2015-04-10
        • 1970-01-01
        相关资源
        最近更新 更多