編譯階段
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,
實例變量
}
創(chuàng)建對象
swift_allocObject
-
swift_allocObject
方法用于創(chuàng)建一個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);//創(chuàng)建一個新對象收叶,
return object;
}
- 根據對象大小做字節(jié)對齊處理骄呼,之后調用
malloc
分配內存,之后會初始化實例變量。 -
metadata
表示類對象元數據蜓萄。 -
requiredSize
和requiredAlignmentMask
表示對象大小和字節(jié)對齊方式隅茎。
swift_initStackObject
- 在某些場景對象創(chuàng)建會被編譯器優(yōu)化為
swift_initStackObject
方法。swift_initStackObject
在棧上創(chuàng)建一個對象嫉沽。沒有引用計數消耗辟犀,也不用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
環(huán)境的弱引用跃捣。
- 調用
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
等方法,這些方法可以在找不到特定方法時可以進行動態(tài)處理郊霎,應該是不想提供純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)
- 使用消息發(fā)送的方式調用方法购对。
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
的方式創(chuàng)建。
Swift
Swift類
創(chuàng)建一個純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
類
創(chuàng)建一個原生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子類
創(chuàng)建一個Swift
-NSObject
子類對象蝇刀。
class SwiftClass: NSObject {
}
SwiftClass()
Class objcClass = swift_getInitializedObjCClass(SwiftClass);
HeapObject *object = objc_allocWithZone(objcClass);
// 釋放
objc_release(object);
Swift泛型類
創(chuàng)建一個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
方法站粟。
每一個不同的泛型類型都會創(chuàng)建一個新的
ClassMetadata
黍图,之后保存到緩存中復用。
swift_allocateGenericClassMetadata:
- 創(chuàng)建一個新的
ClassMetadata
結構奴烙。 - 初始化
objc_class
和swift_class_t
相關的屬性, 同時設置isa
和roData
助被。
swift_initClassMetadataImpl:
- 設置
Superclass
,如果沒有指明父類切诀,會被設置為SwiftObject
揩环。 - 初始化
Vtable
。 - 設置
class_ro_t
的InstanceStart
和InstanceSize
字段幅虑,遍歷ivars
修改每個ivar
的offset
丰滑。 - 將該類注冊到
objc runtime
。