如何在 Swift 中使用 UnsafeMutablePointer<OpaquePointer> ?

l -*_*c l 5 macos swift

如何UnsafeMutablePointer<OpaquePointer>在 Swift 中使用 Core Foundation 框架?为什么有一个UnsafeMutablePointer<OpaquePointer>

\n\n

给定,一般:UnsafeMutablePointer<SomeType>某处typealias SomeType = OpaquePointer

\n\n

具体API示例

\n\n
// SOURCE: import ApplicationServices.PrintCore\ntypealias PMPrinter = OpaquePointer\nfunc PMSessionGetCurrentPrinter(_ printSession: PMPrintSession, _ currentPrinter: UnsafeMutablePointer<PMPrinter>)\nfunc PMPrinterGetPaperList(PMPrinter, UnsafeMutablePointer<Unmanaged<CFArray>?>)\n
Run Code Online (Sandbox Code Playgroud)\n\n

具体示例用例:获取打印机支持的纸张列表

\n\n
let printInfo = NSPrintInfo.shared()\nlet printSession = PMPrintSession(printInfo.pmPrintSession())\nvar currentPrinterOptional: PMPrinter? = nil\nPMSessionGetCurrentPrinter(printSession, &currentPrinterOptional!)\nguard let currentPrinter = currentPrinterOptional else { return }\n\n// Get the array of pre-defined PMPapers this printer supports.\n// PMPrinterGetPaperList(PMPrinter, UnsafeMutablePointer<Unmanaged<CFArray>?>)\nvar paperListUnmanaged: Unmanaged<CFArray>?\nPMPrinterGetPaperList(currentPrinter, &paperListUnmanaged)\nguard let paperList = paperListUnmanaged?.takeUnretainedValue() as [AnyObject]? else { return }\n
Run Code Online (Sandbox Code Playgroud)\n\n

观察到的错误

\n\n

编译的东西不会运行。看起来(也许)合理的语法无法编译。

\n\n

上面的示例得到以下(预期)运行时“致命错误:在解包可选值时意外发现 nil”

\n\n

有些选择其他尝试:

\n\n
// Compile Error: Address of variable \'currentPrinter\' taken before is is initialized\nvar currentPrinter: PMPrinter\nPMSessionGetCurrentPrinter(printSession, &currentPrinter)\n\n// Compile Error: Nil cannot initialze specified type \'PMPrinter\' (aka \'OpaquePointer\')\nvar currentPrinter: PMPrinter = nil\nPMSessionGetCurrentPrinter(printSession, &currentPrinter)\n\n// Compile Error: Variable \'currentPrinterPtr\' used before being initialized\nvar currentPrinterPtr: UnsafeMutablePointer<PMPrinter>\nPMSessionGetCurrentPrinter(printSession, currentPrinterPtr)\n\n// Compile OK: actually compiles\n// Runtime Error: unexpectedly found nil while unwrapping an Optional value\nvar currentPrinterOptional: PMPrinter? = nil\nPMSessionGetCurrentPrinter(printSession, &currentPrinterOptional!)\n
Run Code Online (Sandbox Code Playgroud)\n\n

资源

\n\n

Apple:核心打印 \xe2\x87\x97
\n Apple:将 Swift 与 Cocoa 和 Objective-C 一起使用 \xe2\x87\x97

\n\n

虽然文档提供了有用的信息,但UnsafeMutablePointer<PMPrinter>typealias as的可行实现UnsafeMutablePointer<OpaquePointer>一直难以捉摸。

\n

Mar*_*n R 4

PMPrinterPMPaper在 PrintCore 框架中定义为指向“不完整类型”的指针

typedef struct OpaquePMPrinter*         PMPrinter;
typedef struct OpaquePMPaper*           PMPaper;
Run Code Online (Sandbox Code Playgroud)

这些都是作为 导入到 Swift 中的OpaquePointer,使用起来有点麻烦。

的第二个参数是指向非可选PMSessionGetCurrentPrinter()变量的指针,在 Swift 中,它必须在作为 inout 参数传递之前进行初始化。初始化空指针的一种可能方法是使用. PMPrinterunsafeBitCast

PMPaper从数组中获取对象的最简单方法似乎是使用CFArrayGetValueAtIndex()而不是将其桥接到 Swift 数组。返回 a ,UnsafeRawPointer可以将其转换为OpaquePointer

这在我的测试中有效:

let printInfo = NSPrintInfo.shared()
let printSession = PMPrintSession(printInfo.pmPrintSession())

var currentPrinter = unsafeBitCast(0, to: PMPrinter.self)
PMSessionGetCurrentPrinter(printSession, &currentPrinter);

var paperListUnmanaged: Unmanaged<CFArray>?
PMPrinterGetPaperList(currentPrinter, &paperListUnmanaged)
guard let paperList = paperListUnmanaged?.takeUnretainedValue() else {
    fatalError()
}
for idx in 0..<CFArrayGetCount(paperList) {
    let paper = PMPaper(CFArrayGetValueAtIndex(paperList, idx))!
    var width = 0.0, height = 0.0
    PMPaperGetWidth(paper, &width)
    PMPaperGetHeight(paper, &height)
    print(width, height)
}
Run Code Online (Sandbox Code Playgroud)