Swift是否和OC一样有runtime机制

OC语言最大的特性无疑是其的动态性,可以利用OC的动态性能够获得一个类的方法和属性,从而实现灵活的程序,但Swift是否也包含了runtime机制呢?

参考链接:http://mp.weixin.qq.com
/s?__biz=MzA3ODg4MDk0Ng==&mid=403153173&idx=1&sn=c631f95b28a0eb4b842a9494e43a30e5&scene=23&srcid=0331ZwO8t6uWiBON621r1GhC#rd

下面我们将从纯Swift的类和继承OC的Swift类来阐述Swift的runtime机制

分析用例:

方法,属性

动态性最重要的一点就是拿到某个类的方法和属性,使用如下的方法打印类的方法和属性

调用showClsRuntime打印方法

打印如下:

对于纯Swift的TestASwiftClass来说任何方法、属性都未获取到。

对于TestSwiftClass来说除testReturnTuple、testReturnVoidWithaCharacter两个方法外,其他的都获取成功了。

这是为什么呢?

1:纯Swift类的函数调用已经不是OC那样的运行时消息了,而是类似C++似得vtable,在编译时就确定了调用那个函数了.

2:而TestSwiftClass继承自UIViewController也就是NSObject,Swift为了兼容OC,所以继承自NSObject的类都保留了他的动态性,所以我们能通过runtime拿到他的属性和方法.

可是为什么testReturnTuple、testReturnVoidWithaCharacter这两个函数却无法通过runtime获得呢?

从OC的动态特性可知,所有运行时方法都依赖TypeEcoding,也就是method_getTypeEncoding函数,它指定了参数类型以及参数在入栈时的内存空间,没有这个标识则没法入栈.而元祖,和字符类型是Swift独有的,所以不能利用runtime获得他的方法.

方法替代

动态性最常用的方法就是方法替代,将某个类的方法替代为自定义的方法,从而起到hook的作用.

  • 对于纯Swift类(如TestASwiftClass)来说,无法通过objc runtime替换方法,因为由上面的测试可知拿不到这些方法、属性
  • 对于继承自NSObject类(如TestSwiftVC)来说,无法通过runtime获取到的方法肯定没法替换了。那能通过runtime获取到的方法就都能被替换吗?我们测一把

    Method Swizzling的代码如下

@objc

找到官方文档读读。

可以知道@objc是用来将Swift的API导出给Objective-C和Objective-C runtime使用的,如果你的类继承自Objective-c的类(如NSObject)将会自动被编译器插入@objc标识。

我们在把TestASwiftClass(纯Swift类)的方法、属性前都加个@objc 试试,如图:

dynamic

文档里还有一句说明: 
加了@objc标识的方法、属性无法保证都会被运行时调用,因为Swift会做静态优化。要想完全被动态调用,必须使用dynamic修饰。使用dynamic修饰将会隐式的加上@objc标识。
这也就解释了为什么testReturnVoidWithaId无法被替换,因为写在Swift里的代码直接被编译优化成静态调用了。

而viewDidAppear是继承Objective-C类获得的方法,本身就被修饰为dynamic,所以能被动态替换。

时间: 2024-11-14 12:10:18

Swift是否和OC一样有runtime机制的相关文章

iOS runtime机制 和数据库结合 使用方便开发

1 首先说一下 runtime 运行机制 对于OC 这门高级编程语言 其实在语言底层的实现 是用C语言来实现的 一个OC的类 翻译成C 语言其实就是一个结构体的类型,当然结构体是非常复杂的包括了这个类的所有信息,类的继承还是有点难度的,暂时不用考虑类的继承的问题,只要知道OC类 底层是转换成 C语言的结构体! 我们先看一下 OC 是怎样发送消息的 也就是对应C语言是如何实现函数的调用的过程! [obj makeText];   //obj 这个类发送了一个  makeText的消息 之后runt

Objective-C isa 指针 与 runtime 机制

一.isa指针 要认识什么是isa指针,我们得先明确一点: 在Objective-C中,任何类的定义都是对象.类和类的实例(对象)没有任何本质上的区别.任何对象都有isa指针. 那么什么是类呢?在xcode中用快捷键Shift+Cmd+O 打开文件objc.h 能看到类的定义: 可以看出: Class 是一个 objc_class 结构类型的指针, id是一个 objc_object 结构类型的指针. 我们再来看看 objc_class 的定义: 稍微解释一下各个参数的意思: isa:是一个Cl

ios开发新手浅谈强大的runtime机制

runtime机制,实际上是一套底层的C语言代码,里面提供了很多的C数据类型和一些功能强大的C语言函数.我们所写的OC代码,在底层都是基于runtime来实现的.所以我们可以说OC实际就是披着面向对象外衣的C语言,因为在运行时,OC代码会编译成C/C++ 来运行.runtime中有很多的C函数,有着很强大的功能,比如 : 1. 能动态类的增删改 成员变量,方法 2.IOS Swizzle 能底层动态的交换两个方法(类方法和对象方法)的实现 IOS swizzle的具体做法: 1.在分类的load

Objective-C中runtime机制的应用

Objective-C中runtime机制的应用 一.初识runtime Objective-C是一种动态语言,所谓动态语言,是在程序执行时动态的确定变量类型,执行变量类型对应的方法的.因此,在Object-C中常用字符串映射类的技巧来动态创建类对象.因为OC的动态语言特性,我们可以通过一些手段,在程序运行时动态的更改对象的变量甚至方法,这就是我们所说的runtime机制. 二.你还有什么办法操作这样的变量么? 首先,我们先来看一个例子,这里有我创建的一个MyObject类: ? 1 2 3 4

RunTime机制--原理(一)

原文地址:http://my.oschina.net/panyong/blog/297640 对于runtime机制,在网上找到的资料大概就是怎么去用这些东西,以及查看runtime.h头文件中的实现,当然这确实是一种很好的学习方法,但是,其实我们还是不会知道runtime底层编译成C++语言之后做了什么? 查到一个大牛给资料,顿时对runtime有了一定认识! 我们随便写一个小程序,代码如下: person类头文件如下, <!-- lang: cpp --> #import <Foun

Objective-C的对象模型和runtime机制

内容列表 对象模型(结构定义,类对象.元类和实例对象的关系) 消息传递和转发机制 runtime系统功能理解 对象模型 结构定义 对象(Object): OC中基本构造单元 (building block),用于存储和传递数据. 可以在objc.h的文件中查找到对象结构的定义,如下所示即对象结构为Class类型的isa,而Class是 objc_class结构类型指针.objc_class即我们理解的类对象结构,其也包含一个isa类对象结构指针. 类和对象的最终实现都是一种数据结构,(subcl

我理解的iOS中的RunTime机制(1)

一.首先我们要先知道object-c是一门编译型.动态语言(这里强调下oc是静态类型语言),这在开发语言中是并多见的,一般的动态语言多为解释性语言.oc之所以能够做到即使编译型语言,又是动态语言.就是得益于RunTime机制. 由于本文主要讲解的是RunTime机制,所以语言类型不做过多描述,之后可以另写一篇语言类型的介绍. 二.这里主要讲解RunTime如何使用,其中主要的知识点如下: 1.class_copyPropertyList  获取一份拷贝的成员列表数组 2.property_get

iOS的Runtime机制下给类别(category)添加属性、替换原有类的方法执行

一.Runtime的理解 OC是面向对象的语言这是常识,其实就是通过Runtime机制动态创建类和对象,这里只是简单的运用runtime的使用! 二.类别(category)添加属性_使用前记得导入头文件#import <objc/runtime.h> 通过这三个方法动态的绑定属性 OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy poli

【《Objective-C基础教程 》笔记ch05】(六)OC中的复合机制Composition

 1.复合通过包含作为实例变量的的对象指针实现的.        @interface Unicycle : NSObject        {           Pedal*pedal;           Tire*tire;         }//Pedal和tire通过复合的方式组成了Unicycle 2.存取方法--用来读取或者改变某个对象属性的方法. #import <Foundation/Foundation.h> @interface Car : NSObject { Eng