我听说有人说方法调整是一种危险的做法.即使是名字调整也会让人觉得这有点像作弊.
方法Swizzling正在修改映射,以便调用选择器A实际上将调用实现B.这样做的一个用途是扩展封闭源类的行为.
我们能否将风险正式化,以便任何决定是否使用调酒的人都可以做出明智的决定是否值得他们尝试做什么.
例如
如何在Swift 3.0中实现方法调配?
我已经阅读了关于它的nshipster文章,但是在这个代码的块中
struct Static {
static var token: dispatch_once_t = 0
}
Run Code Online (Sandbox Code Playgroud)
编译器给我一个错误
dispatch_once_t在Swift中不可用:改为使用延迟初始化的全局变量
方法调配对于实例方法非常有用.现在,我需要调整一个类方法.知道怎么做吗?
试过这个,但它不起作用:
void SwizzleClassMethod(Class c, SEL orig, SEL new) {
Method origMethod = class_getClassMethod(c, orig);
Method newMethod = class_getClassMethod(c, new);
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
}
Run Code Online (Sandbox Code Playgroud) 我尝试了JRSwizzle和MethodSwizzle.他们在模拟器上编译得很好,但是当我尝试编译Device(3.x)时会抛出一堆错误
有没有人在iPhone上乱跑?什么诀窍?
TIA
在App Store上是否存在关于方法调查的最新信息是合法/非法的?
我能找到的唯一数据点是一段时间后的Three20框架重组,从这个通知开始:
您当前发布到App Store的应用程序xxx正在使用method_exchangeImplementations将Apple提供的API的实现与您自己的实现交换.由于即将发生的更改,应用程序中的此行为可能会导致崩溃或导致iPhone OS 4.0上的用户数据丢失.
xxx使用method_exchangeImplementations与您的方法ttdealloc交换dealloc的实现.它还用你的方法popViewControllerAnimated2:交换方法popViewControllerAnimated:的实现.
请立即解决此问题,并将新二进制文件上传到iTunes Connect.如果我们认为这样做是谨慎或必要的,我们可能会删除您的申请.
当我在搜索时,我可以找到关于调配和应用程序商店的每个最近的对话似乎都引用了同样的Three20事件.通知似乎非常具体,我想知道问题是否是Three20所做的更改或者method_exchangeImplementations被普遍禁止的具体更改问题.
关于是否允许这种做法,还有其他数据吗?在商店中是否有任何使用应用程序的应用程序的开发人员?
谢谢!
在Swift之前,在Objective-C中,我会在类中调用或挂钩方法<objc/runtime.h>
.
如果有人有任何关于修改Swift的运行时和挂钩函数的信息,比如CydiaSubstrate和其他帮助这个领域的库,请通知我.
Objective-C声明了一个类函数initialize(),它在每个类使用之前运行一次.它经常被用作交换方法实现(混合)等的入口点.它的使用在Swift 3.1中被弃用.
这就是我以前做的事情:
extension NSView {
public override class func initialize() {
// This is called on class init and before `applicationDidFinishLaunching`
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有,我怎么能做同样的事情initialize
?
我需要它用于框架,所以要求在AppDelegate中调用一些东西是不行的.我之前需要它applicationDidFinishLaunching
.
我非常喜欢这个解决方案.这正是我正在寻找的,但它适用于iOS.我需要它用于macOS.有人可以推荐一个macOS版本吗?
具体来说,我需要相当于此,但对于macOS:
extension UIApplication {
private static let runOnce: Void = {
// This is called before `applicationDidFinishLaunching`
}()
override open var next: UIResponder? {
UIApplication.runOnce
return super.next
}
}
Run Code Online (Sandbox Code Playgroud)
我试过覆盖各种属性但NSApplication
没有成功.
解决方案需要纯粹的Swift.没有Objective-C.
我在NSObject上有一个类别应该是这样的东西.当我在一个对象上调用它时,我想覆盖它的dealloc方法来进行一些清理.
我想用方法调配来做,但无法弄清楚如何.我发现的唯一例子是关于如何替换整个类的方法实现(在我的例子中,它将覆盖所有NSObjects的dealloc - 我不想这样做).
我想覆盖NSObject的特定实例的dealloc方法.
@interface NSObject(MyCategory)
-(void)test;
@end
@implementation NSObject(MyCategory)
-(void)newDealloc
{
// do some cleanup here
[self dealloc]; // call actual dealloc method
}
-(void)test
{
IMP orig=[self methodForSelector:@selector(dealloc)];
IMP repl=[self methodForSelector:@selector(newDealloc)];
if (...) // 'test' might be called several times, this replacement should happen only on the first call
{
method_exchangeImplementations(..., ...);
}
}
@end
Run Code Online (Sandbox Code Playgroud) 我试图使用SIMBL修改程序的行为(我没有它的来源).我使用了类转储,发现我需要覆盖一个实例方法
此方法位于名为controller的类中.我需要做的就是获得参数arg1,就是这样.也许NSLog它或发布通知...我读到了Objective-c中的方法调配但我怎么能用它?我需要引用我没有的课程MessageController.
谢谢!
我正在处理方法 swizzling,并想在执行method_exchangeImplementations
. 我为此设置了两个项目。
第一个项目是应用程序的主项目。该项目包括应用程序的所有逻辑。请注意,originalMethodName
在视图加载时调用。
@implementation ViewController
- (void)originalMethodName
{
NSLog(@"REAL %s", __func__);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"REAL %s", __func__);
[self originalMethodName];
}
@end
Run Code Online (Sandbox Code Playgroud)
第二个项目仅包含用于 swizzling 的代码。我有一个方法swizzle_originalMethodName
,其中包含我想注入到主应用程序的originalMethodName
代码,并调用函数。
@implementation swizzle_ViewController
- (void)swizzle_originalMethodName
{
NSLog(@"FAKE %s", __func__);
}
__attribute__((constructor)) static void initializer(void)
{
NSLog(@"FAKE %s", __func__);
Class c1 = objc_getClass("ViewController");
Class c2 = [swizzle_ViewController class];
Method m1 = class_getInstanceMethod(c1, @selector(originalMethodName));
Method m2 = class_getInstanceMethod(c2, @selector(swizzle_originalMethodName));
method_exchangeImplementations(m1, m2);
}
@end
Run Code Online (Sandbox Code Playgroud)
swizzle 工作得很好(如下面的输出所示),但现在我希望能够originalMethodName
从 …