美文网首页Dev.DeepiOSARC 小知识系列
讲讲你不知道的 ARC (一)

讲讲你不知道的 ARC (一)

作者: 酷酷的哀殿 | 来源:发表于2016-09-26 19:07 被阅读1071次

    本文首发地址:http://www.jianshu.com/p/b55513801435

    内容提要

    通过阅读本篇文章,希望您能了解:如何在 ARC 下,强制某个变量调用指定的方法?

    前言

    首先让我们先感谢以 Blaine Garst 和 Patrick Beard 为代表的开发者。他们为 Objective-C 这门语言添加了众多特性,而其中最令人喜爱的莫过于 ARC。

    相信所有和我一样经历过手动管理内存时代的人,都会对这个特性感到非常的喜爱。

    然而,有所得必有所失。本文将会讲讲 ARC 带来的一些“麻烦”。

    一道简单的面试题

    在 MRR 环境下,下面的代码会?Compile Error / Runtime Crash / NSLog…?

    //NSObject+Sun.h
     @interface NSObject (Sun)
     - (void)shining;
     @end
    
    //NSObject+Sun.m
     @implementation NSObject (Sun)
     - (void)shining
     {
        NSLog(@"shining");
     }
    
     @end
     
    //main.m
    #import <Foundation/Foundation.h>
    
     int main(int argc, const char * argv[]) {
      @autoreleasepool {
          [NSObject shining];
    }
    return 0;
    }
    

    答案很简单,虽然会产生一个警告⚠️ Class method '+shining' not found (return type defaults to 'id'),但是可以正常输出 shining

    对此感到困惑的读者可以查看拙作 http://www.jianshu.com/p/e30977484a66

    具体到此问题,可以查看 @halfrost 的文章 神经病院Objective-C Runtime住院第二天—消息发送与转发

    升级版面试题

    刚才的代码在 ARC 环境下,也能正常输出 shining 吗?
    答案是,不会。它会产生一个编译错误❗️。错误的定义如下所示。

    def err_arc_may_not_respond : Error<
      "no visible @interface for %0 declares the selector %1">;
    

    解决方案也很简单。在 main.m 文件中添加一行代码即可。

    #import "NSObject+Sun.h"
    

    问题分析

    为什么在 MRR 下面能够正常运行的代码,却无法在 ARC 下编译呢?

    实际上,在默认情况下,在 ARC 下面进行编译时,编译器需要知道该方法是如何声明的,只有这样,编译器才能自动插入相关的内存管理代码并进行代码优化。

    那么,是否可以强制某个变量执行指定的方法呢?答案是:有。
    可以通过下面主动声明的方式,告诉编译器,请执行该方法。

    [[NSObject new] performSelector:@selector(shining)];
    [NSObject performSelector:@selector(shining)];
    

    下期预告

    相信很多人都没有看明白,为什么在默认情况下,编译器需要知道方法是如何声明的?

    如果你知道原因,欢迎在下方进行评论。

    如果你感到好奇,敬请期待下期。

    相关文章

      网友评论

      • RemisKrlet:ARC下有些针对方法selector,返回类型定义的内存管理策略,比如是否加入自动释放池,是否retain等,可能是这个原因?。
      • wxiubin:xcode什么时候这么厉害了
      • Charles___:NSobject加号方法?shinning?
        酷酷的哀殿: @无聊的猫草 推荐您阅读文章里面的扩展链接
        无聊的猫草:恕我不懂啊,你定义的shinning是instance method,调用的时候是NSObject的class调用,你确定可以通过编译?也确定runtime可以自动帮你找到?
        酷酷的哀殿:@一只孤独的iOS http://www.jianshu.com/p/e30977484a66
        通过路径 4 和 6,可以实现在调用类方法 `-shinning ` 时,查找到 NSObject 的实例方法 `+shinning `

      本文标题:讲讲你不知道的 ARC (一)

      本文链接:https://www.haomeiwen.com/subject/msvqyttx.html