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
。