内容简介:下面是编译阶段生成的类信息:根据上面编译器生成的数据,可以得到一些信息:泛型类不会生成类元数据
class PureSwiftClass {
private var private_var_property = 0
@objc private var objc_private_var_property = 0
var instance_property = 0
@objc let objc_instance_let_property = 0
@objc var objc_instance_var_property = 0
func instance_method() {}
@objc func objc_instance_method() {}
@objc dynamic func objc_dynamic_instance_method() {}
}
复制代码
下面是编译阶段生成的类信息:
_$s10TestObjectSwiftClassCN:
struct __objc_class {
_OBJC_METACLASS_$__TtC10TestObjectSwiftClass, // metaclass
_OBJC_CLASS_$_SwiftObject, // superclass
__objc_empty_cache, // cache
0x0, // vtable
__objc_class__TtC10TestObjectSwiftClass_data+1 // data
}
__objc_class__ObjectSwiftClass_data:
struct __objc_data {
0x80, // flags
8,// instance start
48, // instance size
0x0,
0x0, // ivar layout
"ObjectSwiftClass", // name
__objc_class__TtC10TestObjectSwiftClass_methods, // base methods
0x0, // base protocols
__objc_class__TtC10Test6ObjectSwiftClass_ivars, // ivars
0x0, // weak ivar layout
__objc_class__TtC10TestObjectSwiftClass_properties // base properties
}
// methods
__objc_class__ObjectSwiftClass_methods:
struct __objc_method_list {
0x18, // flags
8 // method count
}
struct __objc_method {
"objc_private_instance_var_property", // name
"q16@0:8", // signature
-[_TtC10TestObjectSwiftClass objc_private_instance_var_property] // implementation
}
struct __objc_method {
"setObjc_private_var_property:", // name
}
struct __objc_method {
"objc_instance_var_property", // name
}
struct __objc_method {
"setObjc_instance_var_property:", // name
}
struct __objc_method {
"objc_instance_let_property", // name
}
struct __objc_method {
"objc_instance_method", // name
}
struct __objc_method {
"objc_dynamic_instance_method", // name
}
struct __objc_method {
"init", // name
}
// ivars
__objc_class__TtC10TestObjectSwiftClass_ivars:
struct __objc_ivars {
32, // entsize
5 // count
}
struct __objc_ivar {
"private_var_property", // name
}
struct __objc_ivar {
"objc_private_var_property", // name
}
struct __objc_ivar {
"instance_var_property", // name
}
struct __objc_ivar {
"objc_instance_var_property", // name
}
struct __objc_ivar {
"objc_instance_let_property", // name
}
复制代码
根据上面编译器生成的数据,可以得到一些信息:
class
-
Swift类编译阶段会生成与Objective-C一样的类元数据,这也是为什么Swift和Objective-C可以互相调用。
泛型类不会生成类元数据 __objc_class
结构,不过会生成 roData
。
-
class如果没有显式继承某个类,都被隐式继承SwiftObject。
属性
-
所有属性都会添加到
class_ro_t中的ivars结构中,包括private属性。 -
使用
@objc修饰的属性,var属性会添加set/get方法,let属性只会添加get方法。
Swift
类的 属性
可以通过 objc-runtime
进行修改和获取。
方法
-
使用
@objc修饰的方法会添加到ro_class_t的methods结构中。
Swift结构
ClassMetadata
ClassMetadata
是 Swift
中所有类元数据格式。
struct objc_object {
Class isa;
}
struct objc_class: objc_object {
Class superclass;
cache_t cache;
class_data_bits_t bits;
}
struct swift_class_t: objc_class {
uint32_t flags;//类标示
uint32_t instanceAddressOffset;
uint32_t instanceSize;//对象实例大小
uint16_t instanceAlignMask;//
uint16_t reserved;// 保留字段
uint32_t classSize;// 类对象的大小
uint32_t classAddressOffset;//
void *description;//类描述
};
复制代码
Swift
和 Objective-C
的类元数据是共用的, Swift
类元数据只是 Objective-C
的基础上增加了一些字段。
源代码中也有一些地方直接使用 reinterpret_cast
进行相互转换。
Class objcClass = [objcObject class]; ClassMetadata *classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass); 复制代码
HeapObject
在 Swift
中,一个 class
对象实际上就是一个 HeapObject
结构体指针。 HeapObject
由 HeapMetadata
和 InlineRefCounts
组成, HeapMetadata
是类对象元数据的指针, InlineRefCounts
用于管理引用计数。
struct HeapObject {
HeapMetadata const *metadata;
InlineRefCounts refCounts;
};
复制代码
-
HeapMetadata和Objective-C中的isa_t结构一样,使用ISA_MASK获取到类对象。
@interface ObjcClass: NSObject {
}
ObjcClass *objcObject = [ObjcClass new];
HeapObject *heapObject = static_cast<HeapObject *>(objcObject);
ObjcClass *objcObject2 = static_cast<ObjcClass *>(heapObject);
[heapObject retain];
复制代码
不过因为 Objective-C
和 Swift
引用计数管理方式不一样,所以转换以后依然要使用之前的方式进行引用计数管理。
Objective-C
和 Swift
对象结构:
Objc对象结构 {
isa_t,
实例变量
}
Swift对象结构 {
metadata,
refCounts,
实例变量
}
复制代码
创建对象
swift_allocObject
-
swift_allocObject方法用于创建一个Swift对象。
void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
void *p;
// This check also forces "default" alignment to use AlignedAlloc.
if (alignMask <= MALLOC_ALIGN_MASK) {
p = malloc(size);
} else {
size_t alignment = (alignMask == ~(size_t(0)))
? _swift_MinAllocationAlignment
: alignMask + 1;
p = AlignedAlloc(size, alignment);
}
if (!p) swift::crash("Could not allocate memory.");
return p;
}
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
size_t requiredSize,
size_t requiredAlignmentMask) {
auto object = reinterpret_cast<HeapObject *>(
swift_slowAlloc(requiredSize, requiredAlignmentMask));
// NOTE: this relies on the C++17 guaranteed semantics of no null-pointer
// check on the placement new allocator which we have observed on Windows,
// Linux, and macOS.
new (object) HeapObject(metadata);//创建一个新对象,
return object;
}
复制代码
-
根据对象大小做字节对齐处理,之后调用
malloc分配内存,之后会初始化实例变量。 -
metadata表示类对象元数据。 -
requiredSize和requiredAlignmentMask表示对象大小和字节对齐方式。
swift_initStackObject
-
在某些场景对象创建会被编译器优化为
swift_initStackObject方法。swift_initStackObject在栈上创建一个对象。没有引用计数消耗,也不用malloc内存。
HeapObject *
swift::swift_initStackObject(HeapMetadata const *metadata,
HeapObject *object) {
object->metadata = metadata;
object->refCounts.initForNotFreeing();
return object;
}
复制代码
销毁对象
swift_deallocClassInstance
-
swift_deallocClassInstance用于销毁对象,在对象dealloc时调用。
void swift::swift_deallocClassInstance(HeapObject *object,
size_t allocatedSize,
size_t allocatedAlignMask) {
#if SWIFT_OBJC_INTEROP
objc_destructInstance((id)object);
#endif
swift_deallocObject(object, allocatedSize, allocatedAlignMask);//
}
复制代码
-
调用
objc_destructInstance方法释放关联对象和弱引用释放处理。
Objc runtime
的对象弱引用,不是 Swift
环境的弱引用。
-
调用
swift_deallocObject方法调用free回收内存。
引用计数相关方法
-
swift_retain和objc的实现类似,对引用计数进行+1,溢出时将一部分引用计数值保存到sideTable中。 -
swift_release对引用计数进行-1,当引用计数为0时,调用销毁对象方法。 -
swift_weak相关的方法用于管理weak弱引用。
SwiftObject
在 Swift
中,一个 class
如果没有显式继承其他的类,都被隐式继承 SwiftObject
。 SwiftObject
实现了 NSObject
协议的所有方法和一部分 NSObject
类的方法。主要是重写了一部分方法,将方法实现改为 Swift
相关方法。
@interface SwiftObject<NSObject> {
@private
Class isa;
InlineRefCounts refCounts;
}
@end
复制代码
没有实现 resolveInstanceMethod
, forwardingTargetForSelector
等方法,这些方法可以在找不到特定方法时可以进行动态处理,应该是不想提供纯 Swift
类在这块的能力。
比如 retain
, release
方法改为了使用 swift runtime
进行引用计数管理:
- (id)retain {
auto SELF = reinterpret_cast<HeapObject *>(self);
swift_retain(SELF);
return self;
}
- (void)release {
auto SELF = reinterpret_cast<HeapObject *>(self);
swift_release(SELF);
}
复制代码
因为纯 Swift
类不能直接与 Objective-C
交互,那么 SwiftObject
这样设计的目的是什么?
下面是两种使用场景:
-
就是将纯
Swift类作为id参数传递到Objective-C方法中使用。
- (void)test:(id)object {
[object retain];
[object performSelector:@selector(objc_instance_method)];
}
复制代码
let object = NSObject() test(object) 复制代码
- 使用消息发送的方式调用方法。
class SwiftClass {
@objc dynamic func objc_dynamic_instance_method() {}
}
let object = SwiftClass()
object.objc_dynamic_instance_method()
复制代码
不过以上场景应该是很少使用的,不清楚还有没有其它目的。而且这样设计的话,纯 Swift
类也应该可以被 Objective-C
直接使用。
初始化对象
Objective-C
Objective-C使用Swift-NSObject子类
class SwiftClass: NSObject {
}
复制代码
SwiftClass *object = [[SwiftClass alloc] init]; 复制代码
-
因为二进制文件中
Swift类包含了和Objective-C一样的类数据信息,所以可以直接使用Objective-C的方式创建。
Swift
Swift类
创建一个纯 Swift
类对象。
class SwiftClass {
}
SwiftClass()
复制代码
swift_getInitializedObjCClass
Class swift::swift_getInitializedObjCClass(Class c) {
[c self];// 为了确保objc-runtime realize class
return c;
}
复制代码
Class objcClass = swift_getInitializedObjCClass(SwiftClass); HeapObject *object = swift_allocObject(objcClass); // 释放 swift_release(object); 复制代码
原生 Objective-C
类
创建一个原生 Objective-C
类对象。
@interface ObjectClass @end 复制代码
ObjectClass() 复制代码
Class objcClass = swift_getInitializedObjCClass(ObjectClass); Metadata *metadata = swift_getObjCClassMetadata(objcClass); ClassMetadata *classMetadata = swift_getObjCClassFromMetadata(metadata); ObjectClass *object = [classMetadata allocWithZone] init]; // 释放 objc_release(object); 复制代码
swift_getObjCClassMetadata
和 swift_getObjCClassFromMetadata
有什么作用?
Swift-NSObject子类
创建一个 Swift
- NSObject
子类对象。
class SwiftClass: NSObject {
}
SwiftClass()
复制代码
Class objcClass = swift_getInitializedObjCClass(SwiftClass); HeapObject *object = objc_allocWithZone(objcClass); // 释放 objc_release(object); 复制代码
Swift泛型类
创建一个 Swift
泛型类对象。
class GenericClass<T> {
}
GenericClass<Int>()
复制代码
MetadataResponse response = swift_getGenericMetadata(); ClassMetadata *classMetadata = swift_allocateGenericClassMetadata(); swift_initClassMetadata2(classMetadata); HeapObject *object = swift_allocObject(objcClass); 复制代码
-
根据泛型类型作为参数,调用
swift_getGenericMetadata方法获取类对象缓存。存在缓存直接返回,没有缓存,调用swift_allocateGenericClassMetadata方法。
每一个不同的泛型类型都会创建一个新的 ClassMetadata
,之后保存到缓存中复用。
swift_allocateGenericClassMetadata:
-
创建一个新的
ClassMetadata结构。 -
初始化
objc_class和swift_class_t相关的属性, 同时设置isa和roData。
swift_initClassMetadataImpl:
-
设置
Superclass,如果没有指明父类,会被设置为SwiftObject。 -
初始化
Vtable。 -
设置
class_ro_t的InstanceStart和InstanceSize字段,遍历ivars修改每个ivar的offset。 -
将该类注册到
objc runtime。
以上所述就是小编给大家介绍的《Swift Runtime - 类和对象》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Creative Curve
Allen Gannett / Knopf Doubleday Publishing Group / 2018-6-12
Big data entrepreneur Allen Gannett overturns the mythology around creative genius, and reveals the science and secrets behind achieving breakout commercial success in any field. We have been s......一起来看看 《The Creative Curve》 这本书的介绍吧!