编译阶段
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。