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() {}
}
复制代码
下面是编译阶段生成的类信息:swift
_$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
}
复制代码
根据上面编译器生成的数据,能够获得一些信息:缓存
Swift
类编译阶段会生成与Objective-C
同样的类元数据,这也是为何Swift
和Objective-C
能够互相调用。泛型类不会生成类元数据
__objc_class
结构,不过会生成roData
。bash
class
若是没有显式继承某个类,都被隐式继承SwiftObject
。class_ro_t
中的ivars
结构中,包括private
属性。@objc
修饰的属性,var
属性会添加set/get
方法,let
属性只会添加get
方法。
Swift
类的属性
能够经过objc-runtime
进行修改和获取。ide
@objc
修饰的方法会添加到ro_class_t
的methods
结构中。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
的基础上增长了一些字段。ui
源代码中也有一些地方直接使用
reinterpret_cast
进行相互转换。this
Class objcClass = [objcObject class];
ClassMetadata *classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass);
复制代码
在Swift
中,一个class
对象实际上就是一个HeapObject
结构体指针。HeapObject
由HeapMetadata
和InlineRefCounts
组成,HeapMetadata
是类对象元数据的指针,InlineRefCounts
用于管理引用计数。spa
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
对象。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
在栈上建立一个对象。没有引用计数消耗,也不用malloc
内存。HeapObject *
swift::swift_initStackObject(HeapMetadata const *metadata,
HeapObject *object) {
object->metadata = metadata;
object->refCounts.initForNotFreeing();
return object;
}
复制代码
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
弱引用。在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
直接使用。
class SwiftClass: NSObject {
}
复制代码
SwiftClass *object = [[SwiftClass alloc] init];
复制代码
Swift
类包含了和Objective-C
同样的类数据信息,因此能够直接使用Objective-C
的方式建立。建立一个纯Swift
类对象。
class SwiftClass {
}
SwiftClass()
复制代码
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
子类对象。
class SwiftClass: NSObject {
}
SwiftClass()
复制代码
Class objcClass = swift_getInitializedObjCClass(SwiftClass);
HeapObject *object = objc_allocWithZone(objcClass);
// 释放
objc_release(object);
复制代码
建立一个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
。