捕获嵌套闭包中的值

时间:2016-10-07 12:48:02

标签: swift closures swift3

在嵌套闭包中使用捕获值的正确语法是什么?

我有以下工作代码,用于使用zlib库从整数值计算CRC32。

func testCrc()
{
    var x: UInt32 = 0xffffffff

    let result = withUnsafePointer(to: &x, {
        $0.withMemoryRebound(to: Bytef.self, capacity: 4) {
            crc32(0, $0, 4)
        }
    })

    XCTAssertEqual(0xffffffff, result)
}

我想创建可以从任何值计算CRC32的独立泛型函数。为了做到这一点,除了值本身,我还必须计算并传递它的大小,所以我不能使用显式大小 - 4 - 就像我在上面的代码中使用的那样。

但是我无法找到正确的语法来将计算出的大小传递给内部闭包。

func calculateCrc32<T>(_ crc: UInt, value: inout T) -> UInt
{
    let size = MemoryLayout.size(ofValue: value)
    let result = withUnsafePointer(to: &value, {
        $0.withMemoryRebound(to: Bytef.self, capacity: size) {
            crc32(crc, $0, size) // error
        }
    })
    return result
}

上面的代码显示参数$0的编译器错误相当混乱:

  

无法转换'UnsafeMutablePointer&lt; _&gt;'类型的值预期   参数类型'UnsafePointer!'

令人困惑,因为如果我用crc32(crc, $0, size)编译器替换crc32(crc, $0, 4)并不抱怨,并且函数适用于大小为4字节的值。

如何解决上述问题?

1 个答案:

答案 0 :(得分:4)

错误消息具有误导性。你的代码几乎是正确的 &#34;仅&#34;问题是crc32()需要的最后一个参数 是uInt

func calculateCrc32<T>(_ crc: UInt, value: inout T) -> UInt
{
    let size = MemoryLayout.size(ofValue: value)
    let result = withUnsafePointer(to: &value, {
        $0.withMemoryRebound(to: Bytef.self, capacity: size) {
            crc32(crc, $0, uInt(size))
        }
    })
    return result
}

如果你拨打crc32(crc, $0, 4),那么&#34;整数字面值&#34; 4 作为最后一个参数传递,编译器推断其类型 作为uInt匹配函数定义。

它不会与crc32(crc, $0, size)一起编译,因为Swift会这样做 不是隐式地在类型之间转换

或者,使用numericCast(),这是一个泛型函数,可以在不同的有符号和无符号整数类型(以及溢出时的陷阱)之间进行转换。

我还建议改为使用该值的局部变量副本 使用inout参数,这使得更容易调用 功能:

func calculateCrc32<T>(_ crc: UInt, value: T) -> UInt {
    var value = value
    let size = MemoryLayout.size(ofValue: value)
    let result = withUnsafePointer(to: &value, {
        $0.withMemoryRebound(to: Bytef.self, capacity: size) {
            crc32(crc, $0, numericCast(size))
        }
    })
    return result
}