当前位置: 首页 > 面试题库 >

在不使用桥接头的情况下访问私有UIKit函数

于捷
2023-03-14
问题内容

考虑私有C函数_UICreateScreenUIImage,该函数返回UIImage当前设备屏幕的快照:

OBJC_EXTERN UIImage *_UICreateScreenUIImage(void) NS_RETURNS_RETAINED;

我可以将其放在桥接标头中,然后在Swift中访问它,如下所示:

MyApp-Bridging-Header.h

@import UIKit;
UIImage *_UICreateScreenUIImage(void) NS_RETURNS_RETAINED;

MyClass.swift

let image = _UICreateScreenUIImage()
print(image) // <UIImage: 0x7fc4ba6081c0>, {375, 667}

有没有一种方法可以_UICreateScreenUIImage在不使用桥接头的情况下在纯Swift中访问?

最初的想法是在上创建扩展UIImage,但是该扩展希望我在扩展中声明函数的主体:

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方法的解析。为此,有更强大的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,并将其包装在函数中以方便使用:

@_silgen_name("_UICreateScreenUIImage")
func _UICreateScreenUIImage() -> Unmanaged<UIImage>
func UICreateScreenUIImage() -> UIImage {
    return _UICreateScreenUIImage().takeRetainedValue()
}


 类似资料:
  • 我在项目中定义了一个模型类。和往常一样,它有一些私有变量和公共的获取者和设置者 假设在其他类中我使用这个模型,就像 然后person的私有变量保存值“my name”,我使用类的public getter访问变量,如 所以据我所知的人。getMark()返回私有变量名的引用,因此如果我修改局部变量“localMark”,它将影响Person类的私有变量,因此它会破坏变量的私有属性 前任: 我猜大多

  • 问题内容: 注意:我在使用React Native时遇到了这个特定的问题,但是我想这也同样适用于React。 我有一个使用React.Component构建的React组件。我不需要设置状态,但是我有道具。我建议的语法如下: 我知道我可以使用函数来构造此组件,如下所示: 但是我更喜欢前者,因为我的组件会增长,可能会有状态等,我只想以相似的方式构建所有组件。 现在,我的linter抱怨拥有一个无用的

  • 问题内容: 我试图将配置(例如URLs / etc)放入资源文件夹中,以供实用程序类使用。但是,我不想从任何地方的活动中传递上下文。我希望能够通过路径名(似乎使用assess /是为此用途设计的)来访问资源,而无需使用上下文来访问资源。 在这种特殊情况下,我希望单例实例化时在配置中使用某些东西。除了实例化期间的那一次之外,它不需要任何资源。因此,每次调用getInstance()时都必须传递Con

  • 问题内容: 我可以在没有jQuery的情况下访问数据属性吗? 使用jQuery很容易,但是如果没有jQuery,我在任何地方都看不到该怎么做。 如果我在Google上搜索“没有jQuery”,那么我得到的只是jQuery示例。 可能吗 问题答案: 在这里,我找到了这个例子: 因此,它看起来非常可行。

  • 我正在测试一个使用OAuth机制来授权和访问API的Web应用程序。OAuth使用RS256算法对令牌进行签名。我注意到,当我传递JWT令牌时,我仍然能够访问API,该令牌具有空“Header”值,并且没有JWT令牌中的“验证签名”部分。 示例:原始JWT令牌-

  • 问题内容: 当然,这个问题可能不是树莓派所特有的。另外,我对Linux还比较陌生。 我想编写一个小库(在node.js中,如果有关系的话),以使用sysfs访问树莓派的GPIO。但是,访问sysfs需要sudo访问,这很明显是有原因的。 Quick2Wire似乎有解决方案,但我想更好地理解它,而不仅仅是盲目使用。他们当然使用了C,但是据我了解,代码并不复杂,即使不那么优雅,也可以仅使用bash即可