在不使用桥接头的情况下访问专用UIKitfunction
考虑私人C函数_UICreateScreenUIImage
,它返回当前设备屏幕的UIImage
快照:
OBJC_EXTERN UIImage *_UICreateScreenUIImage(void) NS_RETURNS_RETAINED;
我可以把它放在一个桥接头文件中,像Swift一样访问它:
MyApp的桥接,Header.h
@import UIKit; UIImage *_UICreateScreenUIImage(void) NS_RETURNS_RETAINED;
MyClass.swift
let image = _UICreateScreenUIImage() print(image) // <UIImage: 0x7fc4ba6081c0>, {375, 667}
有没有一种方法,我可以访问_UICreateScreenUIImage
纯Swift没有使用_UICreateScreenUIImage
?
最初的想法是在UIImage
上创build一个扩展,但扩展期望我在扩展中声明函数的主体:
extension UIImage { public func _UICreateScreenUIImage(_: Void) -> UIImage // "Expected '{' in body of function declaration" }
这个实现是有缺陷的,因为_UICreateScreenUIImage
不是UIImage
上的一个方法。
在纯Swift中暴露并访问这个方法是可能的吗?
人们似乎把我的问题与“我如何截图?”混淆。 那不是我要问的 我问如何访问方法像UIImage *_UICreateScreenUIImage(void);
在Swift中。 它可以是任何私有方法,例如+(UIImage *)_deviceSpecificImageNamed:(NSString *)name inBundle:(NSBundle *)bundle;
或者+(UIImage *)_pu_PhotosUIImageNamed:(NSString *)name;
。
这比你想象的要容易得多:
@asmname("_UICreateScreenUIImage") func _UICreateScreenUIImage() -> UIImage // That's it – go ahead and call it: _UICreateScreenUIImage()
碰巧, @asmname
实际上只是在2.3版本中修改为@_silgen_name
,所以要做好相应的调整:
@_silgen_name("_UICreateScreenUIImage") func _UICreateScreenUIImage() -> UIImage
据我所知, @_silgen_name
不提供Objective-C方法的parsing。 为此,还有更强大的Objective-C运行时API:
let invokeImageNamed: (String, NSTimeInterval) -> UIImage? = { // The Objective-C selector for the method. let selector: Selector = "animatedImageNamed:duration:" guard case let method = class_getClassMethod(UIImage.self, selector) where method != nil else { fatalError("Failed to look up \(selector)") } // Recreation of the method's implementation function. typealias Prototype = @convention(c) (AnyClass, Selector, NSString, NSTimeInterval) -> UIImage? let opaqueIMP = method_getImplementation(method) let function = unsafeBitCast(opaqueIMP, Prototype.self) // Capture the implemenation data in a closure that can be invoked at any time. return { name, interval in function(UIImage.self, selector, name, interval) } }() extension UIImage { // Convenience method for calling the closure from the class. class func imageNamed(name: String, interval: NSTimeInterval) -> UIImage? { return invokeImageNamed(name, interval) } } UIImage.imageNamed("test", interval: 0)
至于处理NS_RETURNS_RETAINED
,这将不会为您生成。 相反,您可以使用Unmanaged
的返回types,并将其包装在函数中以方便您:
@_silgen_name("_UICreateScreenUIImage") func _UICreateScreenUIImage() -> Unmanaged<UIImage> func UICreateScreenUIImage() -> UIImage { return _UICreateScreenUIImage().takeRetainedValue() }