5

我知道 iOS 运行时很强大,但我有一个问题:我们应该在哪里使用运行时?

例如,我发现很多文章都会讨论类和方法混合。在什么情况下我应该使用它?

我也google了一下,发现它被广泛用于越狱开发。不过我是非越狱开发者,请不要覆盖越狱~

谢谢!

4

3 回答 3

7

这是一个非常普遍的问题。运行时是一个与你的程序链接的库,它实现了 Objective-C 的一部分,因此它可以出现在任何地方。如果你不得不问,不要使用它。但仅供参考,这里有一些常见用途:

酣畅淋漓

Swizzling 是两个方法的标识符的交换,因此它们指向彼此的实现。这两种方法仍然可用。

使用 swizzling 代替类别来保留方法的原始实现以及避免两个类别覆盖同一方法(结果将是未定义的)很有用。

有关危险列表,请参阅https://stackoverflow.com/a/8636521/412916

动态方法(某种)

https://stackoverflow.com/a/13646650/412916

关联参考

关联引用是一种将实例变量添加到对象而不更改其代码的方法。当对象被释放时,关联引用会被自动删除。

谷歌它

内省

内省类的属性。例如,在 JSON 和模型的普通类之间进行映射。我猜MantleOvercoat包装就是这样的例子。

您应该阅读Objective-C 运行时编程指南

使用表情符号作为方法名

这可能是最重要的用途。代码不是我的,我不记得原作者了。

#include <objc/runtime.h>
#import <Foundation/Foundation.h>

@interface A: NSObject
@end

@implementation A

void pileOfPoo(id self, SEL _cmd) {
    NSLog(@"");
}

+ (BOOL)resolveInstanceMethod: (SEL)name {
    if ([NSStringFromSelector(name) isEqualToString: @""]) {
    class_addMethod([self class], name, (IMP)pileOfPoo, "v@:");
        return YES;
    } else return NO;
}
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        A *a = [[A alloc] init];
        SEL aSelector = NSSelectorFromString(@"");
        [a performSelector: aSelector];
    }
    return 0;
}
于 2013-10-11T11:57:39.630 回答
1

一般不应该使用。使用时应非常小心,因为当您犯错时破坏一切的风险很高。通常它应该只在使用良好的代码中完成,最好作为开源项目维护,以便许多人检查有效性。

它不仅用于越狱,而且通常涉及私有类/方法,并允许您解决/扩展 API 中的限制。但它也可以用于扩展,例如,将您自己的类作为观察者插入到某种关系中,以便它可以采取一些行动,然后将信息转发给“真正的”观察者(AFNetworking 曾经这样做)。

通常,您应该使用类别或标准子类等特性来添加功能。

于 2013-10-11T10:09:51.707 回答
0

运行时的方法调配是一个很好的措施来“挂钩”任何你想要的方法。为什么我们需要挂钩?hooking的应用有很多种,比如用户行为统计,自动序列化等等。
这里我们以用户行为为例。借助方法调配,我们可以在任何 UIViewController 子类中挂钩“viewWillAppear”方法。这意味着我们可以知道何时调用了“viewWillAppear”,因此我们可以在“viewWillAppear”方法之前或之后注入用户行为代码(例如页面访问次数、页面访问时长)。综上所述,借助方法混合,我们可以轻松实现用户行为统计。其他类型的应用程序相同。

于 2015-12-25T01:07:57.273 回答