在不使用桥接头的情况下访问专用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() }