【问题标题】:How to access iOS private APIs in Swift?如何在 Swift 中访问 iOS 私有 API?
【发布时间】:2015-01-28 00:35:04
【问题描述】:

如何调用非公共 iOS 函数并从 Swift 访问非公共属性?具体来说,我想在 QuartzCore 框架中使用一个非公共类。

我想到的一个解决方案是创建“桥接”Objective-C 项目,将这些非公共 API 包装到公共 API 中,然后从 Swift 调用这个 Objective-C 函数。但是,我现在的解决方案是纯 Swift,我更愿意保持这种方式。有没有更稳妥的方法? (例如添加一些东西到Objective-C bridging header file

注意:我知道你在想什么,私有 API 是私有的,因为它们不应该被使用。我知道风险,我知道所有不利因素、应用商店限制等。经过仔细考虑和大量研究,不幸的是,在这种特殊情况下,它似乎仍然是最好的方法。

【问题讨论】:

  • 如果您将私有方法的声明正确地添加到桥接头文件中,就好像它们在一个类别中(例如,命名为PrivateButImmaUseTheseAnyway),是否有效?
  • @TheParamagneticCroissant 我不确定我是否理解您的意思。我不知道是否可以在桥接头文件中声明一个方法。我试图声明整个私有类 - 我收到一个编译错误,说该类不存在,但也许我没有正确地做到这一点。
  • 我的意思是,你声明私有类和一个类别,像这样:@interface NSPrivateClass (PrivateStuff),并在那里添加私有方法的声明。

标签: ios objective-c swift iphone-privateapi quartz-core


【解决方案1】:

如果您的项目在 Objective-C。

创建一个头文件并将类别的声明与您希望公开的私有方法的声明一起放在类上。然后,告诉 Swift 编译器导入这个桥接头。

出于演示目的,我将探索NSBigMutableString 的内部结构,NSMutableString 的私有子类,我将调用它的_isMarkedAsImmutable 方法。

请注意,这里整个类本身是私有的,因此我必须首先将其声明为其真正超类的子类。因此,我也可以在类本身的声明中声明该方法;然而,这并不能证明 (Private) 技巧类别的用法。

如果您的课程是公开的,那么显然您只需要类别,而无需(重新)声明课程本身。

Bridge.h:

#import <Foundation/Foundation.h>

@interface NSMutableString (Private)
- (BOOL)_isMarkedAsImmutable; // this is a lie
@end

@interface NSBigMutableString : NSMutableString
@end

s.swift:

let s = NSBigMutableString()
println(s._isMarkedAsImmutable())

编译运行:

$ xcrun -sdk macosx swiftc -o foo -import-objc-header Bridge.h s.swift
$ ./foo
false
$

【讨论】:

  • 完美运行,在我的情况下(使用 NSWindow 私有 API 的 MacOS SwiftUI 应用程序)我只需要添加一个 #import &lt;SwiftUI/SwiftUI.h&gt;
【解决方案2】:

您可以使用NSClassFromString: 获取私人课程,并使用performSelector 与他们互动。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 2013-04-22
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    相关资源
    最近更新 更多