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

时间:2017-07-03 21:11:50

标签: swift macos

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

鉴于,一般:某些UnsafeMutablePointer<SomeType>其中typealias SomeType = OpaquePointer

特定示例API

// SOURCE: import ApplicationServices.PrintCore
typealias PMPrinter = OpaquePointer
func PMSessionGetCurrentPrinter(_ printSession: PMPrintSession, _ currentPrinter: UnsafeMutablePointer<PMPrinter>)
func PMPrinterGetPaperList(PMPrinter, UnsafeMutablePointer<Unmanaged<CFArray>?>)

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

let printInfo = NSPrintInfo.shared()
let printSession = PMPrintSession(printInfo.pmPrintSession())
var currentPrinterOptional: PMPrinter? = nil
PMSessionGetCurrentPrinter(printSession, &currentPrinterOptional!)
guard let currentPrinter = currentPrinterOptional else { return }

// Get the array of pre-defined PMPapers this printer supports.
// PMPrinterGetPaperList(PMPrinter, UnsafeMutablePointer<Unmanaged<CFArray>?>)
var paperListUnmanaged: Unmanaged<CFArray>?
PMPrinterGetPaperList(currentPrinter, &paperListUnmanaged)
guard let paperList = paperListUnmanaged?.takeUnretainedValue() as [AnyObject]? else { return }

观察到的错误

什么编译不运行。似乎(可能)合理的语法不能编译。

以上示例获取以下(预期)运行时&#34;致命错误:在解包可选值&#34; 时意外发现nil。

有些选择其他尝试:

// Compile Error: Address of variable 'currentPrinter' taken before is is initialized
var currentPrinter: PMPrinter
PMSessionGetCurrentPrinter(printSession, &currentPrinter)

// Compile Error: Nil cannot initialze specified type 'PMPrinter' (aka 'OpaquePointer')
var currentPrinter: PMPrinter = nil
PMSessionGetCurrentPrinter(printSession, &currentPrinter)

// Compile Error: Variable 'currentPrinterPtr' used before being initialized
var currentPrinterPtr: UnsafeMutablePointer<PMPrinter>
PMSessionGetCurrentPrinter(printSession, currentPrinterPtr)

// Compile OK: actually compiles
// Runtime Error: unexpectedly found nil while unwrapping an Optional value
var currentPrinterOptional: PMPrinter? = nil
PMSessionGetCurrentPrinter(printSession, &currentPrinterOptional!)

资源

Apple: Core Printing ⇗
Apple: Using Swift with Cocoa and Objective-C ⇗

虽然文档包含有用的信息,但UnsafeMutablePointer<PMPrinter>的可行实施方案难以理解为UnsafeMutablePointer<OpaquePointer>

1 个答案:

答案 0 :(得分:2)

PMPrinterPMPaper在PrintCore框架中定义 作为指向&#34;不完整类型的指针&#34;

typedef struct OpaquePMPrinter*         PMPrinter;
typedef struct OpaquePMPaper*           PMPaper;

这些被导入到Swift中OpaquePointer,并且有点 使用起来很麻烦。

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

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

这在我的测试中有效:

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)
}