【问题标题】:iOS RunTime: Use Case [closed]iOS 运行时:用例 [关闭]
【发布时间】:2013-10-19 07:08:16
【问题描述】:

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

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

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

谢谢!

【问题讨论】:

    标签: ios objective-c runtime


    【解决方案1】:

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

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

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

    【讨论】:

    • 我强烈不同意这里写的几乎所有内容。你是什​​么意思它使用私有类/方法?这是一个公共框架,由许多苹果文档记录。诸如关联对象或对给定类的属性(class_copyPropertyList 等)的操作之类的东西并不复杂,而且是非常强大的工具。
    • 我没有说它使用私有API,我说它通常用于与私有API交互/更改响应。我还举了一个与私有 API 无关的完全“合法”且有用的用例示例。我也不否认这些方法非常强大,但大多数程序员不会经常使用它们,因为这种内省代码并不经常需要。出去寻找用例是一项有趣的游戏活动,但在生产环境中使用时应该小心。 @PeterSarnowski
    【解决方案2】:

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

    调酒

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

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

    请参阅https://stackoverflow.com/a/8636521/412916 了解危险列表。

    动态方法(某种)

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

    关联引用

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

    Google it.

    自省

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

    您应该阅读Objective-C Runtime Programming Guide

    使用表情符号作为方法名

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

    #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;
    }
    

    【讨论】:

    • 谢谢,我和您的导游度过了一个愉快的周末!
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-10
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-22
      相关资源
      最近更新 更多