重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
runtime 在iOS中是“运行时”的含义,是一套用c语言写的api,很多人会用但是也仅仅用过最最常用的几个函数,这次,我将详细的带着大家探索下 runtime 的API,这一章就说下 objc/runtime.h 这个文件里的 API ,并且我会把不适用于 ARC 和不支持64位的API剔除掉。
网站建设哪家好,找创新互联建站!专注于网页设计、网站建设、微信开发、小程序开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了含山免费建站欢迎大家使用!
首先,我们先看一个简单的函数:
这个函数是通过传入 Class 类型的 cls 来得到 Class 的名字。那我们测试下这个函数:
其中 [Person class] OC中获得 Class 的方法,当然,你也可以用 runtime 里面的 objc_getClass 等函数,后面我也会讲到。
运行结果:
我们可以看到打印出来的结果就是类的名字。
上面既然用到了 [Person class] ,那我们就看下在 runtime 中 [Person class] 的替代函数,都是通过名字来获得 Class
那这三个有什么区别,从结论上讲, objc_getClass 和 objc_lookUpClass 的效果是一致的,在最新的源码里面,这两个方法调用的底层也是一致的,当你要找的类不存在的话,就返回nil,而 objc_getRequiredClass 里你要找的类不存在的话,就会崩溃。下面我们来测试下,我们创建一个 Person 类。
运行结果:
最后也确实崩溃了,所以大家使用 objc_getRequiredClass 这个函数时候要慎重小心。
除了用名字获得类对象以外,还可以用实例对象来获取:
我们测试下:
运行结果:
完全没问题。
Class 不仅可以代表类对象,也可以代表元类对象,下面这个函数就是通过名字获取元类对象。
如果你读过源码的话,你就会清楚元类对象储存的是类方法,类对象储存的是实例方法,在后面讲到Method相关的API的时候,我们在具体讲他们之间的区别。
讲到元类对象,我们还要关注下这个函数,
这个函数是用来判断是否是元类对象。
运行结果:
我们可以看到 objc_getMetaClass 生成才是元类对象, objc_getClass 生成的只是类对象。
那么有没有函数区分类(元类)对象和实例对象呢?当然有:
这个方法只要是类对象或者元类对象都会返回YES:
运行结果:
当然也可以获得父类对象。
我们新建一个继承 Person 的类 Student ,然后我们通过 Student 类来获得 Person 类。
运行结果:
Student 的父类确实是 Person 。
我们知道OC里面可以强转类型,当然, runtime 里面也有相关方法
这个方法的意思是给一个实例对象设置新的类,返回旧的类
运行结果:
我们可以看出开始的时候 student 的类是 Student ,用了 object_setClass 后就是 Person 类了。
runtime 的动态性还可以动态新增类,下面四个函数分别表示为一个类分配内存,注册一个类,复制一个类,销毁一个类
创建一个新类, superclass 是新类所继承的类,如果为 nil , superclass 就默认为根类,也就是 NSObject , extraBytes 是在类和元类对象的末尾为索引ivars分配的字节数。这一般是0, name 是新类的名字。
注册类,如果这个类 objc_allocateClassPair 好了,就必须 objc_registerClassPair 才能使用。
这个方法在系统KVO的底层用过,系统不推荐我们自己用。
objc_disposeClassPair 只能销毁通过 objc_allocateClassPair 创建的类。
我们写个demo来测试这些方法, objc_duplicateClass 官方不建议使用,那么我们就不测试这函数。
运行结果:
我们可以知道如果仅仅只是 objc_allocateClassPair 的话,你是找不到这个类的,必须再 objc_registerClassPair 才可以找到, objc_disposeClassPair 则是把类销毁掉,所以再实际开发中,如果我们不再使用自建类的时候,就要及时销毁,节省内存。
下面两个函数是关于整个工程的类列表的函数:
这个函数是获得所有注册类的列表,我们试用下:
运行结果:
我们看到注册的类有15765个。
objc_getClassList 也是获取注册类的方法.
第一个参数 buffer 已分配好内存空间的数组指针, bufferCount 是数组的个数,如果 bufferCount 的数量小于实际的数组数量,那么 buffer 返回的是所有数组集合的任意一个子类。如果 buffer 为NULL,那么 bufferCount 为0。无论那种情况,返回结果都是当前注册类的总数。
运行结果:
返回类实例的大小。
运行结果
一个没有变量或属性的继承于NSObject的类占有8个字节。
还有个方法是:
这是一个创建实例的方法, cls 是要创建的类, extraBytes 是额外的字节内存,用来存储类定义中的实例变量之外的其他实例变量。在源码中 alloc 方法底层就是用的这个函数。那么,我们用这个函数来初始化 Person 类:
运行结果:
确实能够成功创建出来。
最后剩下两个方法:
这两个方法都和 version 有关,这个version在实际中我也没发现用处,可能是在改变类的变量或者方法时给定一个标识.
运行结果
下面我们将使用runtime里面最最常用的api,也就是给分类绑定对象,这里,我们先了解下,一个枚举:
objc_AssociationPolicy 是一个枚举,里面的枚举值分别代表要添加的属性的修饰类型。
OBJC_ASSOCIATION_ASSIGN 相当于 weak
OBJC_ASSOCIATION_RETAIN_NONATOMIC 相当于 strong 和 nonatomic
OBJC_ASSOCIATION_COPY_NONATOMIC 相当于 copy 和 nonatomic
OBJC_ASSOCIATION_RETAIN 相当于 strong 和 atomic
OBJC_ASSOCIATION_COPY 相当于 copy 和 atomic
关于分类的runtime函数,主要有下面3个:
含义分别为设置关联对象,获得关联对象,删除关联对象。
我们知道如果在分类的 .h 文件设置属性并没有用,调用的时候会发生闪退,这是因为系统并没有自动为属性生成 Set 和 Get 方法,所以,我们用上面三个方法来手动关联对象。
我们创建一个 Person 的分类 Person+Actor.h ,在.h文件里新建一个新属性 @property(nonatomic, assign)float actingSkill 而不做其他任何处理,这时候, .m 文件就会有警告。
这时候就绑定好了。
在 ViewController 里面去使用下这个属性
运行结果:
说明set和get方法都成功了。
那么还有一个 objc_removeAssociatedObjects 方法还没用,这个方法是解除绑定,为了测试这个效果,我们在ViewController里面 touchesBegan 里面去调用这个方法。
运行结果:
之前绑定的结果被移除了。
今天我们这一篇就讲到这, runtime 还有很多其他的用法我们下一篇见。
对了,这个是 demo ,喜欢的可以点个星。
若要在 Mac 的终端中编译并运行 C 源代码,你首先需要安装 Command Line Tools,里面包含有 GCC 编译器。安装方法为:
打开终端,输入 gcc。
如果你没有安装 Command Line Tools,会弹出一个窗口提示你安装,如图所示,点击安装即可。如果出现提示“clang_error: no input files”,说明你已经安装了 gcc 编译器,可以直接开始编译程序。
安装完成后,定位至你需要编译的 C 源代码所在目录,即使用 cd 命令,例如我现在在根目录下,我的 C 代码位于 ~/Desktop 文件夹中,我便可以在终端中输入以下命令,来跳转到我 C 代码的文件夹:
如果你把.c文件保存或者是存储在桌面上的话你的代码入下所示,
cd desktop1
如果觉得输入文件夹地址比较繁琐,还有一种简单的方法,就是输完 cd 后在 Finder 中找到你的文件夹,直接把它拖到终端里,系统会自动生成这个文件夹的地址。
定位完成后,就可以开始编译了。例如,我要编译的文件叫 test.c,那么就在终端中输入
gcc -Wall -g -o test test.c1
其中,-Wall 代表编译器在编译过程中会输出警告信息(Warning),比如有些变量你并没有使用,指针指向的类型有误,main 函数没有返回整数值等。这类信息虽然不是错误,不影响编译,但是很可能是程序 bug 的源头,也有助于你寻找代码中的错误,规范代码格式。所以建议每次编译时都加上 -Wall 参数。
-g 代表编译器会收集调试(debug)信息,这样如果你的程序运行出错,就可以通过 gdb 或者 lldb 等工具进行逐行调试,方便找出错误原因。如果你不是百分之百确定你的程序毫无问题,建议加上 -g 参数。这样 debug 的时候会方便很多。
-o 代表编译器会将编译完成后的可执行文件以你指定的名称输出到你指定的文件夹下。-o 的空格后的名称就是输出的文件的名称。例如我这里 -o 后是 test,就是说 gcc 会在编译成功后在我的当前目录下生成一个叫 test 的可执行文件。如果不加这个参数,每次编译后生成的可执行文件都会放在根目录下,名字叫做 a.out。每次编译成功后都会把上一次的 a.out 文件覆盖。所以建议加上 -o 参数,这样可以更加条理。
最后一项便是你要编译的的源代码的名称了。我这里是 test.c。注意加上后缀 .c。
输入完毕后按回车,如果编译没有任何问题,不会有任何提示。如果有问题,编译器会提示你问题是什么,在源代码的什么位置。
如果编译成功,你会发现在你的当前目录下多出了一个可执行文件,图标如图所示:
在终端中输入 ./可执行文件的名称 即可执行你的程序。例如,我输入
.\test1
后,就可以执行程序了。如果提示你 Permission Denied,则是因为你没有赋予这个文件执行权限,需要在终端里输入
chmod u+x test //(最后参数为你的文件名,来使其可在你的账户下执行)1
如果运行时出现 Segmentation Fault,则说明你的代码里有 bug 导致程序崩溃。
其实objective-C的语法跟C/C++差不多。。。
Objective-C可以说是标准C的一个扩展,iOS开发是可以用C++,如果你刚开始,建议不用C++,直接学objective-C,把Objective-C完全学通再说。
无论是用C/C++还是Objective-C开发,开发工具都是用Xcode。
1、创建工程的时候选择OSX-Application-Command Line Tool,进入创建工程的对话框,这个时候可以选择语言了,C++,C,Swift,OC都可以。
2、默认情况下会根据选择的语言创建一个main文件,可以直接运行,或者拷贝书上的例子运行。运行的过程中,可以在output面板进行输入和查看输出。
有,就是这个软件:
C/C++ Compiler
这是16块钱的那个地址:
这是免费版的地址:
C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作为系统设计语言, 编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范围广泛。 C语言在很多方面都可以用,不仅仅是在软件开发上,各类科研都是需要用到C语言的。C语言是最受欢迎的语言之一。iOS开发百科全书—C语言百科
1.编程入门
首先介绍C语言的学习路线、环境搭建、iOS编程的行业前景、计算机的基本工作原理,为刚入门的初学者做铺垫,有一个基本概念,方便以后的学习。
2.C语言的基本概念
对学习路线中的各个阶段的是知识点有个简单的了解,并用项目的形式展示出我们学习之后可以做的事情,后续剧情先知先觉,学时豁然开朗,轻松接收。
3.格式化输入输出与基本类型
介绍了最基本的输入输出、进制、整形、浮点型、字符型的数据及其转换,用最简单的方式编最简单的C程序。
4.流程控制
介绍了流程的基本概念、分支语句、循环语句的概念、基本语法、与应用。程序如何判断,判断的条件,把我们解决问题的流程放进程序中表达的基本课程。
5.函数
详细介绍了函数的基本概念,函数的组成,函数的用法。高效编程,一劳永逸,把简单的功能模块化,函数就是利器。