如何在Swift中访问iOS私有API?

17

如何在Swift中调用非公开的iOS函数和访问非公开的属性?具体而言,我想在QuartzCore框架中使用一个非公开的类。

一个我想到的解决方案是创建一个"桥接"Objective-C项目,将这些非公开API封装成公共API,然后从Swift中调用这些Objective-C函数。但是,我的解决方案现在是纯Swift的,我更喜欢保持它这样。是否有更直接的方法?(例如向Objective-C桥接头文件添加一些内容)

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


如果您将私有方法的声明正确添加到桥接头文件中,就好像它们在一个类别(例如PrivateButImmaUseTheseAnyway)中一样,那么这是否有效? - The Paramagnetic Croissant
@TheParamagneticCroissant,我不确定我理解你的意思。我不知道是否可以在桥接头文件中仅声明一个方法。我尝试声明整个私有类 - 我得到了一个编译错误,说该类不存在,但也许我没有做正确。 - Rasto
我的意思是,你可以在类的声明中同时声明一个私有类和一个分类,就像这样:@interface NSPrivateClass (PrivateStuff),然后在那里添加私有方法的声明。 - The Paramagnetic Croissant
2个回答

22

你可以使用与Objective-C中相同的技巧。

创建一个头文件并在其中声明一个类别(category)和你想要公开的私有方法的声明。然后,告诉Swift编译器导入这个桥接头文件。

为了演示,我将深入研究NSBigMutableString的内部,这是NSMutableString的一个私有子类,并调用它的_isMarkedAsImmutable方法。

请注意,整个类本身都是私有的,因此我必须先将其声明为真实超类的子类。因此,我也可以在类的声明中直接声明该方法;但是,这样做不能演示使用(Private)技巧的用法。

如果你的类是公共的,那么你只需要类别(category),而不需要(重新)声明类本身。

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
$

完美运行,在我的情况下(MacOS SwiftUI 应用程序使用 NSWindow 私有 API),我只需要添加 #import <SwiftUI/SwiftUI.h> - Giovazz89

8
您可以使用NSClassFromString:获取私有类,并使用performSelector与它们进行交互,这在IT技术方面非常相关。请注意不要改变HTML标签的格式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接