我想使用 dispatch IO channel从文件描述符中读取一些数据。创建 channel 后,下一步是调用 read
,声明如下:
func read(offset: off_t,
length: Int,
queue: DispatchQueue,
ioHandler: @escaping (Bool, DispatchData?, Int32) -> Void)
length
参数的文档说:
The number of bytes to read from the channel. Specify SIZE_MAX to continue reading data until an EOF is reached.
看起来很简单。就我而言,我想这样做 — 一直读到 EOF。所以我将通过 SIZE_MAX
:
// `queue` and `handler` defined elsewhere
channel.read(offset: 0, length: SIZE_MAX, queue: queue, ioHandler: handler)
精明的读者已经猜到编译器不喜欢这样:
Cannot convert value of type 'UInt' to expected argument type 'Int'
SIZE_MAX
是 UInt
类型,但是 length
是 Int
类型。编译器提供修复它:
channel.read(offset: 0, length: Int(SIZE_MAX), queue: queue, ioHandler: handler)
当然,在运行时,这并不是很好:
fatal error: Not enough bits to represent a signed value
自然如果SIZE_MAX
是UInt
可以表示的最大值,那么Int
就不能表示了。快速搜索后,我找到了 this exact issue on the Swift bug tracker .因为它似乎还没有得到解决——而且我不确定我自己是否有能力通过拉取请求来解决它——我该如何解决这个问题?还是我缺少一种方法来做我想做的事?
Swift Stdlib 基本原理文档 covers the explicit decision to import size_t
as Int
rather than UInt
.它归结为“更少的类型转换,无论如何谁都需要指定 2^63 以上的数字(抱歉,32 位平台)”。很公平,但这不包括像我这样的问题,其中 SIZE_MAX
的使用是 API 的一部分。
最佳答案
只需使用 Int.max
如果您在 64 位平台上,您仍然几乎可以保证在读取 Int.max
字节之前到达文件末尾。在 32 位平台上,如果您的文件非常大,您可能需要执行多次读取。
然后你应该向 Apple 报告这个问题。我不确定 Dispatch IO 库是属于 Apple 还是属于 Swift 开源项目,或者它只是一个文档错误。
更新
源代码是开源的,读取操作只是对长度为size_t
的C函数的简单包装。
https://github.com/apple/swift-corelibs-libdispatch/blob/master/src/swift/IO.swift
我还没有尝试过,但您几乎可以肯定地使用位模式或者甚至可能是 -1
。不过,我想我还是会选择 Int.max
。
关于swift - Swift GCD 覆盖中的类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46400483/