ios - 如何在 Swift 中获取 C 指针的原始值?

标签 ios swift swift2 core-text

我正在从事一个使用 CoreText 的项目;我需要初始化一个 CTRunDelegateCallbacks :

var  imageCallback =  CTRunDelegateCallbacks(version: kCTRunDelegateCurrentVersion, dealloc: { (refCon) -> Void in
    print("RunDelegate dealloc")
    }, getAscent: { ( refCon) -> CGFloat in
        return 0
    }, getDescent: { (refCon) -> CGFloat in
        return 0
    }) { (refCon) -> CGFloat in
        return 0
}

参数refConUnsafeMutablePointer<Void>类型,也称为 void *输入 C。我想获取指针的原始值。怎么做?

最佳答案

我不建议将指针转换为非指针类型。我会在这个答案的最后告诉你如何去做,但首先我会告诉你你应该如何真正处理 refCon .

创建一个结构来保存您需要传递给回调的任何信息。示例:

struct MyRunExtent {
    let ascent: CGFloat
    let descent: CGFloat
    let width: CGFloat
}

然后创建一个 UnsafeMutablePointer使用其 alloc类方法,并初始化分配的存储:

let extentBuffer = UnsafeMutablePointer<MyRunExtent>.alloc(1)
extentBuffer.initialize(MyRunExtent(ascent: 12, descent: 4, width: 10))

在您的回调中,将指针参数转换为 UnsafePointer<MyRunExtent>并从其 memory 中提取您需要的内容:

var callbacks = CTRunDelegateCallbacks(version: kCTRunDelegateVersion1, dealloc: { pointer in
    pointer.dealloc(1)
    }, getAscent: { pointer in
        return UnsafePointer<MyRunExtent>(pointer).memory.ascent
    }, getDescent: { pointer in
        return UnsafePointer<MyRunExtent>(pointer).memory.descent
    }, getWidth: { pointer in
        return UnsafePointer<MyRunExtent>(pointer).memory.width
})

现在您可以使用 callbacks 创建您的委托(delegate)和 extentBuffer :

let delegate = CTRunDelegateCreate(&callbacks, extentBuffer)!

这是一个测试:

let richText = NSMutableAttributedString(string: "hello \u{FFFC} world")
richText.addAttribute(kCTRunDelegateAttributeName as String, value: delegate, range: NSMakeRange(6, 1))
let line = CTLineCreateWithAttributedString(richText)
let runs = (CTLineGetGlyphRuns(line) as [AnyObject]).map { $0 as! CTRun }
runs.forEach {
    var ascent = CGFloat(0), descent = CGFloat(0), leading = CGFloat(0)
    let width = CTRunGetTypographicBounds($0, CFRangeMake(0, 0), &ascent, &descent, &leading)
    print("width:\(width) ascent:\(ascent) descent:\(descent) leading:\(leading)")
}

输出(在 Playground 上):

2015-12-21 12:26:00.505 iOS Playground[17525:8055669] -[__NSCFType encodeWithCoder:]: unrecognized selector sent to instance 0x7f94bcb01dc0
width:28.6875 ascent:9.240234375 descent:2.759765625 leading:0.0
width:10.0 ascent:12.0 descent:4.0 leading:0.0
width:32.009765625 ascent:9.240234375 descent:2.759765625 leading:0.0

输出的第一行是因为 playground 执行过程无法对委托(delegate)进行编码以发送回 Xcode 进行显示,结果证明是无害的。无论如何,你可以看到中间运行的边界是使用我的回调和我的 extentBuffer 的内容计算的。 .

现在,您一直在等待的时刻......

您可以通过这种方式获取指针的“原始值”,if 指针和 Int在运行的系统上大小相同:

let rawValue = unsafeBitCast(refCon, Int.self)

如果它们的大小不同,您将在运行时遇到 fatal error 。

您可以将其转换为 CGFloat这样,if 指针和一个 CGFloat大小相同:

let float = unsafeBitCast(refCon, CGFloat.self)

关于ios - 如何在 Swift 中获取 C 指针的原始值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34222103/

相关文章:

jquery - 是否可以强制 Ios 浏览器焦点从输入转移到另一个元素?

ios - Storyboard中设置的 UITableViewCell 的恢复 ID 和标识符之间有什么区别

ios - self.navigationController?.popViewControllerAnimated 来自 UIAlertController

swift - 终端命令不适用于 Swift

ios - 如何修复 Facebook SDK "does not contain bitcode"错误?

ios - performSegue 动画完成,什么标识符?

ios - 模拟器黑屏(viewDidLoad)?

ios - 代码优化在 ios Swift 中不起作用?

ios - 将 'UITableViewCell' 类型的值转换为自定义单元格

Swift - 从自定义 UITableViewCell 调用 UIViewController 的函数