Swift進階-類與結(jié)構(gòu)體
Swift-函數(shù)派發(fā)
Swift進階-屬性
Swift進階-指針
Swift進階-內(nèi)存管理
Swift進階-TargetClassMetadata和TargetStructMetadata數(shù)據(jù)結(jié)構(gòu)源碼分析
Swift進階-Mirror解析
Swift進階-閉包
Swift進階-協(xié)議
Swift進階-泛型
Swift進階-String源碼解析
Swift進階-Array源碼解析
課前知識儲備
-
AnyObject
代表 - 任意類的實例沿癞、類的類型杯活、僅類遵守的協(xié)議
class Teacher {
var age = 18
}
var t = Teacher()
var t1: AnyObject = t // 類的實例對象
var t2: AnyObject = Teacher.self // 類的類型
// 協(xié)議只允許被類遵守
protocol MyProtocol: AnyObject {
}
extension Teacher: MyProtocol {
}
-
Any
:代表任意類型,包含function類型或者optional類型谴咸。
let array: [AnyObject] = [1, "aaa"] // 報錯!Int是基本數(shù)據(jù)類型
let array: [Any] = [1, "aaa"] // 修改后寫法
-
AnyClass
: 代表任意實例對象的類型
class Teacher {
var age = 18
}
var t: AnyClass = Teacher.self // 它屬于Teacher.Type
-
type(of: T)
: 獲取動態(tài)類型
let age = 10
// value靜態(tài)類型是Any
func test(_ value: Any) {
print(type(of: value))
}
test(age) // Int
-
T.self
:如果T是實例對象骗露,那T.self返回的是實例自己岭佳;如果T是類型,那T.self返回的是元類型萧锉。
class Teacher {
var age = 18
}
var t = Teacher()
var t1 = t.self // 返回的是 t
var t2 = t.self.self // 返回的是 t
var t3 = Teacher.self // 返回的是 Teacher的元類型
-
self
與Self
self的使用場景
class Teacher {
var age = 18
func test() {
print(self) // self是當(dāng)前實例對象
}
static func test1() {
print(self) // Teacher類對象
}
}
Self的使用場景
1.作為方法的返回類型珊随,Self指代返回當(dāng)前類的對象
2.在協(xié)議中方法返回類型 ,Self指代返回遵循這個協(xié)議的類型的對象
3.可用于使用靜態(tài)屬性
class Teacher {
static let age = 18
func test() -> Self {
return self // 返回當(dāng)前實例對象
}
}
class Person {
static let age = 18
let age1 = age
var age2 = age
lazy var age3 = Self.age
}
protocol MyProtocol {
func get() -> Self
}
一、Mirror的基本用法
反射就是可以動態(tài)獲取 類型叶洞、成員信息鲫凶,在運行時可調(diào)用方法、屬性 等行為的特性衩辟。
基于原生Swift
使用Runtime
的諸多局限性螟炫,它的標(biāo)準(zhǔn)庫提供了反射機制來讓我們訪問成員信息。
Swift
的反射機制是基于一個叫Mirror
的結(jié)構(gòu)體來實現(xiàn)的惭婿。
class Teacher {
var age = 18
func teach() {
print("teach")
}
}
let t = Teacher()
let mirror = Mirror(reflecting: t)
for property in mirror.children {
print("\(property.label!): \(property.value)")
}
// age: 18
ps: 沒有辦法訪問到當(dāng)前的函數(shù)teach不恭,如果想要訪問函數(shù),需要把函數(shù)定義成屬性信息财饥。
那我們可以簡單地封裝一下换吧,得到一個對象的key-value:
// 調(diào)用函數(shù)直接得到一個對象的key-value
func getKeyValue(_ mirrorObj: Any) -> [String: Any] {
let mirror = Mirror(reflecting: mirrorObj)
guard !mirror.children.isEmpty else{ return mirrorObj }
var result: [String: Any] = [:]
for child in mirror.children{
if let key = child.label{
result[key] = test(child.value)
}else{
print("No Keys")
}
}
return result
}
然而我們還可以定義出更高級Mirror的封裝
:
class Teacher {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
enum JSONMapError: Error{
case emptyKey
case notConformProtocol
}
protocol JSONMap{
func jsonMap() throws -> Any
}
//rethrows
extension JSONMap{
func jsonMap() throws -> Any{
let mirror = Mirror(reflecting: self)
guard !mirror.children.isEmpty else{ return self }
var result: [String: Any] = [:]
for child in mirror.children{
if let value = child.value as? JSONMap{
if let key = child.label{
result[key] = try? value.jsonMap()
}else{
return JSONMapError.emptyKey
}
}else{
return JSONMapError.notConformProtocol
}
}
return result
}
}
extension Teacher: JSONMap{}
extension Int: JSONMap{}
extension String: JSONMap{}
// 使用:
var t = Teacher(age: 18, name: "安老師")
do {
try t.jsonMap()
} catch {
print(error)
}
二、Mirror源碼解析
打開Swift源碼搜索到Mirror.swift
钥星,很快清晰地發(fā)現(xiàn)Mirror是一個結(jié)構(gòu)體沾瓦,快速定位到初始化函數(shù):
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
self = customized.customMirror
} else {
self = Mirror(internalReflecting: subject)
}
}
首先看到初始化函數(shù)接收一個 Any
參數(shù) subject
。要么subject是遵循 CustomReflectable
協(xié)議谦炒,如果是則調(diào)用 customized.customMirror
得到Mirror對象贯莺,要么去創(chuàng)建Mirror。
我們來看一下CustomReflectable
協(xié)議具體用法:
class Teacher: CustomReflectable {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var customMirror: Mirror{
let info = KeyValuePairs<String, Any>.init(dictionaryLiteral: ("age", age),("name", name))
let mirror = Mirror.init(self, children: info, displayStyle: .class, ancestorRepresentation: .generated)
return mirror
}
}
當(dāng)實現(xiàn)這個 CustomReflectable
最直觀的區(qū)別在與我們在 lldb debug
中會出現(xiàn)更詳細(xì)的 debug 信息:
沒有實現(xiàn)這個協(xié)議的時候就會只打印地址宁改。
了解完CustomReflectable
就需要往下了解Mirror的初始化方法 Mirror(internalReflecting: subject)
缕探,全局搜索一下Mirror(internalReflecting:
找到在 ReflectionMirror.swift
找到_getNormalizedType
在哪里聲明的
編譯器字段@_silgen_name
是swift的一個隱藏符號,作用是將某個c/c++函數(shù)直接映射為swift函數(shù)还蹲。
番外知識舉例 @_silgen_name
的使用:
1.新建一個 C file 文件爹耗,取名為TestC
2.在TestC.c寫一個C函數(shù)實現(xiàn)
#include "TestC.h"
int c_add(int a, int b) {
return a + b;
}
3.在.swift 文件聲明一個映射函數(shù)
@_silgen_name("c_add")
func swift_add(a: Int32, b: Int32) -> Int32
4.直接調(diào)用 swift_add
var value = swift_add(a: 10, b: 20)
print(value)
再回到 Mirror初始化源碼
里邊,在獲取subject的真實類型信息的時候谜喊,調(diào)用了_getNormalizedType
潭兽,而源碼里這個函數(shù)的聲明看出,實際上這個函數(shù)是在調(diào)用 swift_reflectionMirror_normalizedType
函數(shù).
找到ReflectionMirror.cpp
里邊的函數(shù)名為swift_reflectionMirror_normalizedType
:
// func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
return call(value, T, type, [](ReflectionMirrorImpl *impl) { return impl->type; });
}
它調(diào)用了一個 call函數(shù)(它返回了一個閉包)斗遏,當(dāng)前呢調(diào)用了call函數(shù)返回了類型信息山卦。
template<typename F>
auto call(OpaqueValue *passedValue, const Metadata *T, const Metadata *passedType,
const F &f) -> decltype(f(nullptr))
{
const Metadata *type;
OpaqueValue *value;
std::tie(type, value) = unwrapExistential(T, passedValue);
if (passedType != nullptr) {
type = passedType;
}
auto call = [&](ReflectionMirrorImpl *impl) {
impl->type = type;
impl->value = value;
auto result = f(impl);
return result;
};
auto callClass = [&] {
if (passedType == nullptr) {
// Get the runtime type of the object.
const void *obj = *reinterpret_cast<const void * const *>(value);
auto isa = _swift_getClass(obj);
// Look through artificial subclasses.
while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
isa = isa->Superclass;
}
passedType = isa;
}
#if SWIFT_OBJC_INTEROP
// If this is a pure ObjC class, reflect it using ObjC's runtime facilities.
// ForeignClass (e.g. CF classes) manifests as a NULL class object.
auto *classObject = passedType->getClassObject();
if (classObject == nullptr || !classObject->isTypeMetadata()) {
ObjCClassImpl impl;
return call(&impl);
}
#endif
// Otherwise, use the native Swift facilities.
ClassImpl impl;
return call(&impl);
};
switch (type->getKind()) {
case MetadataKind::Tuple: {
TupleImpl impl;
return call(&impl);
}
case MetadataKind::Struct: {
StructImpl impl;
return call(&impl);
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
EnumImpl impl;
return call(&impl);
}
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
case MetadataKind::Class: {
return callClass();
}
case MetadataKind::Metatype:
case MetadataKind::ExistentialMetatype: {
MetatypeImpl impl;
return call(&impl);
}
case MetadataKind::Opaque: {
#if SWIFT_OBJC_INTEROP
// If this is the AnyObject type, use the dynamic type of the
// object reference.
if (type == &METADATA_SYM(BO).base) {
return callClass();
}
#endif
// If this is the Builtin.NativeObject type, and the heap object is a
// class instance, use the dynamic type of the object reference.
if (type == &METADATA_SYM(Bo).base) {
const HeapObject *obj
= *reinterpret_cast<const HeapObject * const*>(value);
if (obj->metadata->getKind() == MetadataKind::Class) {
return callClass();
}
}
SWIFT_FALLTHROUGH;
}
/// TODO: Implement specialized mirror witnesses for all kinds.
default:
break;
// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
}
// If we have an unknown kind of type, or a type without special handling,
// treat it as opaque.
OpaqueImpl impl;
return call(&impl);
}
} // end anonymous namespace
可以看到call函數(shù)體里面return
之前使用switch做了一系列的類型判斷,來確定返回是call回調(diào)
還是callClass回調(diào)
而最終所有的結(jié)果信息(type诵次、value) 都是由當(dāng)前的 ReflectionMirrorImpl
這個結(jié)構(gòu)體去實現(xiàn)的账蓉。
看看switch里面怎么做判斷的:
switch (type->getKind()) {
case MetadataKind::Tuple: {
TupleImpl impl;
return call(&impl);
}
case MetadataKind::Struct: {
StructImpl impl;
return call(&impl);
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
EnumImpl impl;
return call(&impl);
}
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
case MetadataKind::Class: {
return callClass();
}
case MetadataKind::Metatype:
case MetadataKind::ExistentialMetatype: {
MetatypeImpl impl;
return call(&impl);
}
case MetadataKind::Opaque: {
#if SWIFT_OBJC_INTEROP
// If this is the AnyObject type, use the dynamic type of the
// object reference.
if (type == &METADATA_SYM(BO).base) {
return callClass();
}
#endif
// If this is the Builtin.NativeObject type, and the heap object is a
// class instance, use the dynamic type of the object reference.
if (type == &METADATA_SYM(Bo).base) {
const HeapObject *obj
= *reinterpret_cast<const HeapObject * const*>(value);
if (obj->metadata->getKind() == MetadataKind::Class) {
return callClass();
}
}
SWIFT_FALLTHROUGH;
}
/// TODO: Implement specialized mirror witnesses for all kinds.
default:
break;
// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
}
// If we have an unknown kind of type, or a type without special handling,
// treat it as opaque.
OpaqueImpl impl;
return call(&impl);
}
判斷類型如果是 Tuple
則返回TupleImpl
,如果是Struct
則返回StructImpl
等...
那如果想反射不同類型的信息逾一,就要把要反射的類型去繼承這個ReflectionMirrorImpl
抽象結(jié)構(gòu)體剔猿,提供具體的類型信息。
ReflectionMirrorImpl
是反射實現(xiàn)的抽象基類:
// Abstract base class for reflection implementations.
struct ReflectionMirrorImpl {
const Metadata *type;
OpaqueValue *value;
virtual char displayStyle() = 0;
virtual intptr_t count() = 0;
virtual intptr_t childOffset(intptr_t index) = 0;
virtual const FieldType childMetadata(intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *)) = 0;
virtual AnyReturn subscript(intptr_t index, const char **outName,
void (**outFreeFunc)(const char *)) = 0;
virtual const char *enumCaseName() { return nullptr; }
#if SWIFT_OBJC_INTEROP
virtual id quickLookObject() { return nil; }
#endif
// For class types, traverse through superclasses when providing field
// information. The base implementations call through to their local-only
// counterparts.
virtual intptr_t recursiveCount() {
return count();
}
virtual intptr_t recursiveChildOffset(intptr_t index) {
return childOffset(index);
}
virtual const FieldType recursiveChildMetadata(intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *))
{
return childMetadata(index, outName, outFreeFunc);
}
virtual ~ReflectionMirrorImpl() {}
};
EnumImpl
的源碼聲明:
// Implementation for enums.
struct EnumImpl : ReflectionMirrorImpl {
//是否能反射
bool isReflectable() {
//做一個metadata的強轉(zhuǎn)
const auto *Enum = static_cast<const EnumMetadata *>(type);
//找到metadata的Description
const auto &Description = Enum->getDescription();
//根據(jù)Description中的isReflectable字段來判斷是否可以反射
return Description->isReflectable();
}
const char *getInfo(unsigned *tagPtr = nullptr,
const Metadata **payloadTypePtr = nullptr,
bool *indirectPtr = nullptr) {
// 'tag' is in the range [0..NumElements-1].
unsigned tag = type->vw_getEnumTag(value);
StringRef name;
FieldType info;
//獲取FieldDescriptor的信息嬉荆,也就是屬性信息存放的地方
std::tie(name, info) = getFieldAt(type, tag);
const Metadata *payloadType = info.getType();
bool indirect = info.isIndirect();
if (tagPtr)
*tagPtr = tag;
if (payloadTypePtr)
*payloadTypePtr = payloadType;
if (indirectPtr)
*indirectPtr = indirect;
return name.data();
}
char displayStyle() override {
return 'e';
}
//獲取count
intptr_t count() override {
if (!isReflectable()) {
return 0;
}
// No fields if reflecting the enumeration type instead of a case
if (!value) {
return 0;
}
const Metadata *payloadType;
//獲取掛載類型,也就是Metadata
getInfo(nullptr, &payloadType, nullptr);
return (payloadType != nullptr) ? 1 : 0;
}
...
}
獲取FieldDescriptor的信息是怎么獲取的呢酷含?
看看getFieldAt
的源碼:
static std::pair<StringRef /*name*/, FieldType /*fieldInfo*/>
getFieldAt(const Metadata *base, unsigned index) {
using namespace reflection;
// If we failed to find the field descriptor metadata for the type, fall
// back to returning an empty tuple as a standin.
auto failedToFindMetadata = [&]() -> std::pair<StringRef, FieldType> {
auto typeName = swift_getTypeName(base, /*qualified*/ true);
missing_reflection_metadata_warning(
"warning: the Swift runtime found no field metadata for "
"type '%*s' that claims to be reflectable. Its fields will show up as "
"'unknown' in Mirrors\n",
(int)typeName.length, typeName.data);
return {"unknown", FieldType(&METADATA_SYM(EMPTY_TUPLE_MANGLING))};
};
//獲取TargetxxxDescriptor信息
auto *baseDesc = base->getTypeContextDescriptor();
if (!baseDesc)
return failedToFindMetadata();
//獲取descriptor里的FieldDescriptor的信息
auto *fields = baseDesc->Fields.get();
if (!fields)
return failedToFindMetadata();
auto &field = fields->getFields()[index];
// Bounds are always valid as the offset is constant.
//獲取屬性的名稱
auto name = field.getFieldName();
...
}
- 此時的源碼可以分析出上一篇文章Swift進階-屬性通過
Mach-O
找到我們的屬性名稱是一致的鄙早。
Mirror
的工作原理:可以看出Mirro
是通過Metadata
(當(dāng)前類型的元數(shù)據(jù))汪茧、getDescription
(當(dāng)前類型的描述)、FieldDescription
(當(dāng)前類型屬性的描述)來實現(xiàn)的限番。
三舱污、enum數(shù)據(jù)結(jié)構(gòu)還原
來看源碼全局搜索在Metadata.h
找到 TargetEnumMetadata
的源碼:
/// The structure of type metadata for enums.
template <typename Runtime>
struct TargetEnumMetadata : public TargetValueMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
using TargetValueMetadata<Runtime>::TargetValueMetadata;
const TargetEnumDescriptor<Runtime> *getDescription() const {
return llvm::cast<TargetEnumDescriptor<Runtime>>(this->Description);
}
// The first trailing field of enum metadata is always the generic
// argument array.
/// True if the metadata records the size of the payload area.
bool hasPayloadSize() const {
return getDescription()->hasPayloadSizeOffset();
}
/// Retrieve the size of the payload area.
///
/// `hasPayloadSize` must be true for this to be valid.
StoredSize getPayloadSize() const {
assert(hasPayloadSize());
auto offset = getDescription()->getPayloadSizeOffset();
const StoredSize *asWords = reinterpret_cast<const StoredSize *>(this);
asWords += offset;
return *asWords;
}
StoredSize &getPayloadSize() {
assert(hasPayloadSize());
auto offset = getDescription()->getPayloadSizeOffset();
StoredSize *asWords = reinterpret_cast<StoredSize *>(this);
asWords += offset;
return *asWords;
}
bool isStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isStaticSpecialization();
}
bool isCanonicalStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isCanonicalStaticSpecialization();
}
const MetadataTrailingFlags *getTrailingFlags() const {
auto description = getDescription();
auto flags = description->getFullGenericContextHeader()
.DefaultInstantiationPattern->PatternFlags;
if (!flags.hasTrailingFlags())
return nullptr;
auto offset =
getGenericArgumentOffset() +
description->getFullGenericContextHeader().Base.getNumArguments() +
(hasPayloadSize() ? 1 : 0);
auto asWords = reinterpret_cast<const void *const *>(this);
return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
}
static constexpr int32_t getGenericArgumentOffset() {
return sizeof(TargetEnumMetadata<Runtime>) / sizeof(StoredPointer);
}
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
}
};
using EnumMetadata = TargetEnumMetadata<InProcess>;
繼承自TargetValueMetadata
:
/// The common structure of metadata for structs and enums.
template <typename Runtime>
struct TargetValueMetadata : public TargetMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
TargetValueMetadata(MetadataKind Kind,
const TargetTypeContextDescriptor<Runtime> *description)
: TargetMetadata<Runtime>(Kind), Description(description) {}
/// An out-of-line description of the type.
TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
|| metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
}
ConstTargetMetadataPointer<Runtime, TargetValueTypeDescriptor>
getDescription() const {
return Description;
}
typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
return Description;
}
};
using ValueMetadata = TargetValueMetadata<InProcess>;
繼承自TargetMetadata
:
template <typename Runtime>
struct TargetMetadata {
using StoredPointer = typename Runtime::StoredPointer;
/// The basic header type.
typedef TargetTypeMetadataHeader<Runtime> HeaderType;
constexpr TargetMetadata()
: Kind(static_cast<StoredPointer>(MetadataKind::Class)) {}
constexpr TargetMetadata(MetadataKind Kind)
: Kind(static_cast<StoredPointer>(Kind)) {}
#if SWIFT_OBJC_INTEROP
protected:
constexpr TargetMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
: Kind(reinterpret_cast<StoredPointer>(isa)) {}
#endif
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
/// the kind value.
StoredPointer Kind;
public:
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
/// Set the metadata kind.
void setKind(MetadataKind kind) {
Kind = static_cast<StoredPointer>(kind);
}
protected:
const TargetAnyClassMetadata<Runtime> *getClassISA() const {
return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
}
void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
Kind = reinterpret_cast<StoredPointer>(isa);
}
public:
/// Is this a class object--the metadata record for a Swift class (which also
/// serves as the class object), or the class object for an ObjC class (which
/// is not metadata)?
bool isClassObject() const {
return static_cast<MetadataKind>(getKind()) == MetadataKind::Class;
}
/// Does the given metadata kind represent metadata for some kind of class?
static bool isAnyKindOfClass(MetadataKind k) {
switch (k) {
case MetadataKind::Class:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
return true;
default:
return false;
}
}
/// Is this metadata for an existential type?
bool isAnyExistentialType() const {
switch (getKind()) {
case MetadataKind::ExistentialMetatype:
case MetadataKind::Existential:
return true;
default:
return false;
}
}
/// Is this either type metadata or a class object for any kind of class?
bool isAnyClass() const {
return isAnyKindOfClass(getKind());
}
const ValueWitnessTable *getValueWitnesses() const {
return asFullMetadata(this)->ValueWitnesses;
}
const TypeLayout *getTypeLayout() const {
return getValueWitnesses()->getTypeLayout();
}
void setValueWitnesses(const ValueWitnessTable *table) {
asFullMetadata(this)->ValueWitnesses = table;
}
// Define forwarders for value witnesses. These invoke this metadata's value
// witness table with itself as the 'self' parameter.
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \
template<typename...A> \
_ResultOf<ValueWitnessTypes::WITNESS ## Unsigned>::type \
vw_##WITNESS(A &&...args) const { \
return getValueWitnesses()->WITNESS(std::forward<A>(args)..., this); \
}
#define DATA_VALUE_WITNESS(LOWER, UPPER, TYPE)
#include "swift/ABI/ValueWitness.def"
unsigned vw_getEnumTag(const OpaqueValue *value) const {
return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast<OpaqueValue*>(value), this);
}
void vw_destructiveProjectEnumData(OpaqueValue *value) const {
getValueWitnesses()->_asEVWT()->destructiveProjectEnumData(value, this);
}
void vw_destructiveInjectEnumTag(OpaqueValue *value, unsigned tag) const {
getValueWitnesses()->_asEVWT()->destructiveInjectEnumTag(value, tag, this);
}
size_t vw_size() const {
return getValueWitnesses()->getSize();
}
size_t vw_alignment() const {
return getValueWitnesses()->getAlignment();
}
size_t vw_stride() const {
return getValueWitnesses()->getStride();
}
unsigned vw_getNumExtraInhabitants() const {
return getValueWitnesses()->getNumExtraInhabitants();
}
/// Allocate an out-of-line buffer if values of this type don't fit in the
/// ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *allocateBufferIn(ValueBuffer *buffer) const;
/// Get the address of the memory previously allocated in the ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *projectBufferFrom(ValueBuffer *buffer) const;
/// Deallocate an out-of-line buffer stored in 'buffer' if values of this type
/// are not stored inline in the ValueBuffer.
void deallocateBufferIn(ValueBuffer *buffer) const;
// Allocate an out-of-line buffer box (reference counted) if values of this
// type don't fit in the ValueBuffer.
// NOTE: This *is* a box for copy-on-write existentials.
OpaqueValue *allocateBoxForExistentialIn(ValueBuffer *Buffer) const;
// Deallocate an out-of-line buffer box if one is present.
void deallocateBoxForExistentialIn(ValueBuffer *Buffer) const;
/// Get the nominal type descriptor if this metadata describes a nominal type,
/// or return null if it does not.
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>
getTypeContextDescriptor() const {
switch (getKind()) {
case MetadataKind::Class: {
if (Runtime::ObjCInterop) {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadataObjCInterop<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
} else {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadata<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
}
}
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
return static_cast<const TargetValueMetadata<Runtime> *>(this)
->Description;
case MetadataKind::ForeignClass:
return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)
->Description;
default:
return nullptr;
}
}
/// Get the class object for this type if it has one, or return null if the
/// type is not a class (or not a class with a class object).
const typename Runtime::template TargetClassMetadata<Runtime> *
getClassObject() const;
/// Retrieve the generic arguments of this type, if it has any.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *
getGenericArgs() const {
auto description = getTypeContextDescriptor();
if (!description)
return nullptr;
auto generics = description->getGenericContext();
if (!generics)
return nullptr;
auto asWords = reinterpret_cast<
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
return asWords + description->getGenericArgumentOffset();
}
bool satisfiesClassConstraint() const;
const TypeContextDescriptor *getDescription() const;
bool isStaticallySpecializedGenericMetadata() const;
bool isCanonicalStaticallySpecializedGenericMetadata() const;
#if SWIFT_OBJC_INTEROP
/// Get the ObjC class object for this type if it has one, or return null if
/// the type is not a class (or not a class with a class object).
/// This is allowed for InProcess values only.
template <typename R = Runtime>
typename std::enable_if<std::is_same<R, InProcess>::value, Class>::type
getObjCClassObject() const {
return reinterpret_cast<Class>(
const_cast<TargetClassMetadata<
InProcess, TargetAnyClassMetadataObjCInterop<InProcess>> *>(
getClassObject()));
}
#endif
#ifndef NDEBUG
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
"Only meant for use in the debugger");
#endif
protected:
friend struct TargetOpaqueMetadata<Runtime>;
/// Metadata should not be publicly copied or moved.
constexpr TargetMetadata(const TargetMetadata &) = default;
TargetMetadata &operator=(const TargetMetadata &) = default;
constexpr TargetMetadata(TargetMetadata &&) = default;
TargetMetadata &operator=(TargetMetadata &&) = default;
};
TargetEnumMetadata
繼承于 TargetValueMetadata
繼承于 TargetMetadata
; 同時要注意 TargetRelativeDirectPointer
數(shù)據(jù)結(jié)構(gòu)是相對地址信息 - 存儲的是偏移量。(只粘貼了部分源碼弥虐,自行下載源碼看著分析就得出)
TargetEnumMetadata
的數(shù)據(jù)結(jié)構(gòu):
// 枚舉Metadata
struct TargetEnumMetadata {
var kind: Int
var typeDescriptor: UnsafeMutablePointer<TargetEnumDescriptor>
}
// 枚舉描述器
struct TargetEnumDescriptor {
var flags: Int32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar>
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor>
var NumPayloadCasesAndPayloadSizeOffset: UInt32
var NumEmptyCases: UInt32
}
// 相對地址信息
struct TargetRelativeDirectPointer<Pointee> {
var offset: Int32 // 存儲偏移量
// 獲取相對偏移指針
mutating func getmeasureRelativeOffset() -> UnsafeMutablePointer<Pointee>{
let offset = self.offset
return withUnsafePointer(to: &self) { p in
return UnsafeMutablePointer(mutating: UnsafeRawPointer(p).advanced(by: numericCast(offset)).assumingMemoryBound(to: Pointee.self))
}
}
}
// 屬性描述器
struct FieldDescriptor {
var MangledTypeName: TargetRelativeDirectPointer<CChar>
var Superclass: TargetRelativeDirectPointer<CChar>
var kind: UInt16
var fieldRecordSize: Int16
var numFields: Int32 // 屬性個數(shù)
var fields: FiledRecordBuffer<FieldRecord> // 屬性列表
}
// 屬性
struct FieldRecord {
var fieldRecordFlags: Int32 // flags
var mangledTypeName: TargetRelativeDirectPointer<CChar> // 屬性類型
var fieldName: TargetRelativeDirectPointer<UInt8> // 屬性名稱
}
struct FiledRecordBuffer<Element>{
var element: Element
mutating func buffer(n: Int) -> UnsafeBufferPointer<Element> {
return withUnsafePointer(to: &self) {
let ptr = $0.withMemoryRebound(to: Element.self, capacity: 1) { start in
return start
}
return UnsafeBufferPointer(start: ptr, count: n)
}
}
mutating func index(of i: Int) -> UnsafeMutablePointer<Element> {
return withUnsafePointer(to: &self) {
return UnsafeMutablePointer(mutating: UnsafeRawPointer($0).assumingMemoryBound(to: Element.self).advanced(by: i))
}
}
}
注意:TargetRelativeDirectPointer
是相對地址信息扩灯,比如說TargetEnumDescriptor
里的name
存儲的是相對于當(dāng)前對象的偏移量,通過這個偏移量找到真實的內(nèi)容霜瘪。
那么我們設(shè)計出了Enum
的Metadata
珠插,該如何使用呢?請看舉例:
自定義一個枚舉類 TerminalChar
enum TerminalChar {
case plain(Bool)
case bold
case empty
case cursor
}
通過按位轉(zhuǎn)換成指針 UnsafeMutablePointer<TargetEnumMetadata>
颖对,就可以對指針進行操作了(給個小案例叭捻撑,請自己運行看結(jié)果):
// 元類 Metadata
// var clazz = TerminalChar.self
// 使用按位轉(zhuǎn)換成指針去操作(當(dāng)前的元類clazz 就是 TargetEnumMetadata 這個結(jié)構(gòu)體)
let enumMetadata_ptr = unsafeBitCast(TerminalChar.self as Any.Type, to: UnsafeMutablePointer<TargetEnumMetadata>.self)
let namePtr = enumMetadata_ptr.pointee.typeDescriptor.pointee.name.getmeasureRelativeOffset()
print(String(cString: namePtr)) // TerminalChar
print(enumMetadata_ptr.pointee.typeDescriptor.pointee.NumPayloadCasesAndPayloadSizeOffset) // 1
print(enumMetadata_ptr.pointee.typeDescriptor.pointee.NumEmptyCases) // 3
// 拿到屬性描述器指針
let fieldDesc_ptr = enumMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset()
print(String(cString: fieldDesc_ptr.pointee.MangledTypeName.getmeasureRelativeOffset()))
print(String(cString: fieldDesc_ptr.pointee.Superclass.getmeasureRelativeOffset()))
print(fieldDesc_ptr.pointee.kind) // 2
print(fieldDesc_ptr.pointee.fieldRecordSize) // 12
print(fieldDesc_ptr.pointee.numFields) // 4
print(String(cString: fieldDesc_ptr.pointee.fields.index(of: 0).pointee.fieldName.getmeasureRelativeOffset())) // plain
注意:
let enumMetadata_ptr = unsafeBitCast(clazz as Any.Type, to: UnsafeMutablePointer<TargetEnumMetadata>.self)
這句代碼為什么一定要把TerminalChar.self
強轉(zhuǎn)成Any.Type
?
unsafeBitCast
需要兩個參數(shù)的內(nèi)存大小相同缤底。必須使用:TerminalChar.self as Any.Type
進行轉(zhuǎn)換顾患,因為根據(jù)測試發(fā)現(xiàn)TerminalChar.self
獲取內(nèi)存大小為0(這個地方是真的坑),先來看看MemoryLayout
輸出結(jié)果:
番外小知識 unsafeBitCast
舉例 :
var age = 10
var age1 = unsafeBitCast(age, to: Double.self)
print(age1) // 5e-323
注意:unsafeBitCast(age, to: Double.self)
中的age
是以二進制位的方式塞進Double
類型里邊个唧,本質(zhì)上age1上存儲的是0xa江解,當(dāng)print(age1)的時候是輸出科學(xué)技術(shù)的Double。來看看 x/8g 后的 age1:
言歸正傳徙歼!上面那個小案例可以把TerminalChar
enum類的屬性輸出出來了犁河,試想一下,我們是不是可以從源碼得出StructMetadata
鲁沥,從而把一個結(jié)構(gòu)體對象的屬性內(nèi)容打印出來呼股。
如果你想學(xué)習(xí)ClassMetadata
、StructMetadata
和更詳細(xì)的EnumMetadata
画恰,可以查看我分享的這篇文章彭谁。