Swift, explore the Runtime
- Run the following code
class XQTeacher { var age = 18 func teach() { print("teach") } } func test() { var properCount : UInt32 = 0 let properList = class_copyPropertyList(XQTeacher.self, &properCount) for i in 0.. <numericCast(properCount) { if let proper = properList? [I] {let properName = property_getName(proper) print(" property :\(String(utf8String: properName)! ")}else{print(" no attribute ")}} var methodCount: UInt32 = 0 let methodList = class_copyMethodList(XQTeacher.self, &methodCount) for i in 0.. <numericCast(methodCount) { if let method = methodList? [I] {let methodName = method_getName(method) print(" \(String(describing: MethodName)) ")} else {print (" no way ")}}} the test () print (" end ")Copy the code
- Run this code and you’ll see that both our method list and our property list are currently empty at this time
- inSwift value type and reference type, method schedulingWe know that
@objc
If this is the time to add our current methods and properties to@objc
What happens?
- At this point the code will output our current
teach
Methods andage
Properties. However, it is not available for our OC at the momentclass
Inherited fromNSObject
conclusion
- For pure
Swift
Class does not have dynamic properties. Methods and properties without any modifiers. This time actually has no what we callruntime
Features. - For pure
Swift
Class, method, and attribute additions@objc
Identify the current case we can passRuntime API
Yes, but there is no scheduling in OC. - For inheriting from
NSObject
For classes, if we want to get current properties and methods dynamically, we must add them before they are declared@objc
Keyword, method exchange:dynamic
Logo. Otherwise there is no way to passRuntime API
To obtain.
SwiftObject
- Through source code debugging, in
class_copyPropertyList
Method hits a breakpoint while executing, and the execution enters a breakpoint
- Into the
class_copyPropertyList
methods
- Into the
data
Method, as you can seeswift
There is a default base class_SwiftObject
- in
Swift
Search in source code_SwiftObject
TargetAnyClassMetadata
The members inside
Swift
In order to interact with the OC, the underlying data structure is partially consistent with the OC.- in
objc
It’s also in the source codeswift_class_t
The definition of it is an inheritance fromobjc_class
That is, in theobjc_class
Add your own member variables to the base of the
reflection
- Reflection is the ability to dynamically retrieve type, member information, invoke methods, properties, and so on at run time. And we did the analysis above, for a pure
Swift
Class does not allow us to operate directly like OC; butSwift
The library still provides a reflection mechanism to access member information, and reflection is very simple to use.
class XQTeacher {
var age = 18
}
var t = XQTeacher()
let mir = Mirror(reflecting: t)
for pro in mir.children {
print("\(String(describing: pro.label)):\(pro.value)")
}
Copy the code
- To implement a simple one by reflection
json
parsing
func test(_ obj:Any) -> Any { let mirror = Mirror(reflecting: obj) guard ! mirror.children.isEmpty else { return obj; } var keyValue : [String:Any] = [:] for child in mirror.children { if let keyName = child.label { keyValue[keyName] = test(child.value) }else{print("label is empty ")}} print(keyValue) return keyValue} test(t)Copy the code
- Encapsulate it as a protocol
protocol CustomJSONMap { func jsonMap() -> Any } extension CustomJSONMap { func jsonMap() -> Any { let mirror = Mirror(reflecting: self) guard ! mirror.children.isEmpty else { return self; } var keyValue : [String:Any] = [:] for child in mirror.children { if let value = child.value as? CustomJSONMap {if let keyName = child.label {keyValue[keyName] = value.jsonmap ()}else{print(" Label is empty ")}}else{if let keyName = child.label {keyValue[keyName] = value.jsonMap()} Print (" not comply with the protocol ")}} print(keyValue) return keyValue}} class XQTeacher: CustomJSONMap{ @objc var age = 18 @objc func teach() { print("teach") } } extension Int : CustomJSONMap {} var t = XQTeacher() let result = t.jsonmap () --------- // Result :["age": 18]Copy the code
Error handling
- In the json parsing above, we didn’t handle the error but just printed it and defined one
JSONMapError
Error throws are commonly usedthrow
.
enum JSONMapError : Error { case emptyKey case notConformProtocol } protocol CustomJSONMap { func jsonMap() throws -> Any } extension CustomJSONMap { func jsonMap() throws -> Any { let mirror = Mirror(reflecting: self) guard ! mirror.children.isEmpty else { return self; } var keyValue : [String:Any] = [:] for child in mirror.children { if let value = child.value as? CustomJSONMap { if let keyName = child.label { keyValue[keyName] = try? Value. JsonMap ()} else {throw JSONMapError. EmptyKey}} else {/ / print (" did not comply with the agreement ") throw JSONMapError. NotConformProtocol}} return keyValue } } class XQTeacher : CustomJSONMap{@objc var age = 18 var height = 1.98 @objc func () {print("teach")}} extension Int: CustomJSONMap{@objc var age = 18 var height = 1.98 @objc func teach() {print("teach")}} extension Int: CustomJSONMap {} var t = XQTeacher() let result = try? t.jsonMap() print(result)Copy the code
Swift
In addition to usingtry
Handle errors and can also be useddo... catch
- use
try
Keywords are the simplest, and our favorite, to usetey
There are two things to note hereThe try?
One is thetry!
try?
An optional type is returned. There are two types of results: one is success, which returns a specific dictionary value; One type of error, but we don’t care which type of error, we return onenil
try!
This means that you are absolutely confident that this line of code will never go wrong
do... catch
use
do { try t.jsonMap() }catch { print(error) } Copy the code
- use
- sometimes
Error
Does not achieve the error message you want to elaborate on, can be usedLocalError
,JSONMapError
, the usage is as follows
Meta-types, AnyClass, Self
AnyObject
: represents any classinstance
, the type of the class, and only the protocol that the class complies withAny
: indicates any type, includingfuncation
Type orOptional
typeAnyClass
: represents the type of any instanceT.self
If:T
Is an instance object and returns itself; ifT
It’s a class, and it returns MetaData.T.Type
: a type,T.self
isT.Type
typetype(of:)
: The dynamic type used to get a value