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@objcIf this is the time to add our current methods and properties to@objcWhat happens?

  • At this point the code will output our currentteachMethods andageProperties. However, it is not available for our OC at the momentclassInherited fromNSObject

conclusion

  • For pureSwiftClass does not have dynamic properties. Methods and properties without any modifiers. This time actually has no what we callruntimeFeatures.
  • For pureSwiftClass, method, and attribute additions@objcIdentify the current case we can passRuntime APIYes, but there is no scheduling in OC.
  • For inheriting fromNSObjectFor classes, if we want to get current properties and methods dynamically, we must add them before they are declared@objcKeyword, method exchange:dynamicLogo. Otherwise there is no way to passRuntime APITo obtain.

SwiftObject

  • Through source code debugging, inclass_copyPropertyListMethod hits a breakpoint while executing, and the execution enters a breakpoint

  • Into theclass_copyPropertyListmethods

  • Into thedataMethod, as you can seeswiftThere is a default base class_SwiftObject

  • inSwiftSearch in source code_SwiftObject

  • TargetAnyClassMetadataThe members inside

  • SwiftIn order to interact with the OC, the underlying data structure is partially consistent with the OC.
  • inobjcIt’s also in the source codeswift_class_tThe definition of it is an inheritance fromobjc_classThat is, in theobjc_classAdd 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 pureSwiftClass does not allow us to operate directly like OC; butSwiftThe 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 reflectionjsonparsing
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 oneJSONMapErrorError 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
  • SwiftIn addition to usingtryHandle errors and can also be useddo... catch
    • usetryKeywords are the simplest, and our favorite, to useteyThere 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... catchuse
    do {
    	try t.jsonMap()
    }catch {
       print(error)
    }
    Copy the code
  • sometimesErrorDoes 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 with
  • Any: indicates any type, includingfuncationType orOptionaltype
  • AnyClass: represents the type of any instance
  • T.selfIf:TIs an instance object and returns itself; ifTIt’s a class, and it returns MetaData.
  • T.Type: a type,T.selfisT.Typetype
  • type(of:): The dynamic type used to get a value