美文网首页
iOS原理之Category的initialize原理

iOS原理之Category的initialize原理

作者: yqc5521 | 来源:发表于2019-05-18 12:15 被阅读0次
    //
    //  CategoryBasementInitializeViewController.swift
    //  iOS底层
    //
    //  Created by yanqunchao on 2019/5/17.
    //  Copyright © 2019 yanqunchao. All rights reserved.
    //
    
    import UIKit
    
    
    class CategoryBasementInitializeViewController: UIViewController { 
    
        /**
         * 方法类
         */
        class MethodT: NSObject {
            var name:Selector?
            var type:String?
            var imp:String?
        }
        /**
         * 方法列表类
         */
        class MethodListT: NSObject {
            var size:Int?  //方法列表内存大小
            var methodCount:Int?  //方法数量
            var methodList:[MethodT]?  //方法数组
        }
        /**
         * 只读类类信息
         */
        class ClassRoT: NSObject {
            var name:String = ""
            var baseMethodList:[MethodListT]?  // 实例方法列表
        }
        
        /**
         * 可读可写的类信息
         */
        class ClassRwT: NSObject {
            var ro:ClassRoT?
            var methods:[MethodListT]?  //方法列表
        }
      
       /**
         * 方法缓冲区类
         */
     class BucketT: NSObject {
            var key:Selector?  //SEL
            var imp:String? //IMP
        }
        
        /**
         * 方法缓存类
         */
        class CacheT: NSObject {
            var buckets:[BucketT] = Array.init(repeating: BucketT(), count: 4)
            var mask:Int = 3
            var occupied:Int?
        }
        
        /**
         * 类对象
         */
        class ClassT: NSObject {
            var isa:ClassT?  //指针
            var superClass:ClassT? //父类
            var cache:CacheT?  //方法缓存
            var rw:ClassRwT? //可读可写类
            var name:String?
            var isInitialized:Bool = false
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = .white
         
            
            objMessageSend(inst: studentClass, sel: NSSelectorFromString("alloc"))
            
            objMessageSend(inst: personClass, sel: NSSelectorFromString("alloc"))
    
            objMessageSend(inst: personClass, sel: NSSelectorFromString("alloc"))
    
            
        }
        
        //消息发送
        func objMessageSend(inst:ClassT, sel:Selector){
            
            let cls = inst.isa //找到元类,通过元类找到类方法。
           
    //        print("\(cls!.name!)------执行了\(sel)")
            
            classLookupMethodAndLoadCache3(inst: inst, sel: sel, cls: cls!)
        }
     
        //消息发送机制入口函数(从类中查找方法,并加载缓存)
        func classLookupMethodAndLoadCache3(inst:ClassT, sel:Selector, cls:ClassT){
            lookUpImpOrForward(cls: cls, inst: inst, sel: sel, initialize: true, cache: false)
        }
        
        //方法寻找或转发
        func lookUpImpOrForward(cls:ClassT, inst:ClassT, sel:Selector, initialize:Bool, cache:Bool){
            
            //先从自己缓存中找
            if cacheLookup(inst: cls, sel: sel) == nil{ //找不到
                //            print("\(inst.name!)的缓存中没找到\(NSStringFromSelector(sel))")
                //去方法列表中找
                if methodTableLookup(inst: cls, sel: sel) == nil { //找不到
                    // 消息动态处理 、消息转发
                    
                } else{
                    //                print("调用\(inst.name!)的\(sel)")
                }
            }else{
                //            print("调用\(inst.name!)的\(sel)")
            }
            
            
            //该类没有调用过+initialize方法时,调用classInitialize
            
            if (initialize  &&  !isInitialized(cls: cls) ) {
                
                let noMetaCls = getNoMetaClass(clsName: cls.name!)!
                
                classInitialize(cls: noMetaCls) //调的非元类对象
            }
        }
        
        
        //从缓存中找
        func cacheLookup(inst:ClassT, sel:Selector) ->String?{
            let cls = inst
            let bucket = find(key: sel, id: cls)
            if bucket != nil {
    //            print("从\(cls.name!)的缓存中找到了\(NSStringFromSelector(sel))方法")
                return bucket?.imp
            }else{
                return nil
            }
        }
        
        func find(key:Selector,id:ClassT) ->BucketT? {
            
            let buckets = id.cache?.buckets
            
            let m = id.cache?.mask
            
            if m == nil || m == -1{
                return nil
            }
            
            //获取起始索引
            let begin = cacheHash(key: key, mask: m!)
            var i = begin
            
            repeat {
                let bucket = buckets![i!]
                
                if bucket.key == nil{
                    
                }else if bucket.key! == key{
                    
    //                print("\(id.name!)查找到的索引\(i!)")
                    
                    return bucket
                }
    //            print("\(id.name!)查找索引\(i!)")
                i = cacheNext(i: i!, mask: m!)
              
            }while(i != begin)
            
            return nil
        }
        
        //缓存方法
        func cache(bkt:BucketT,id:ClassT) {
            
    //        print("缓存\(id.name!)的\(NSStringFromSelector(bkt.key!))方法")
    
            var buckets = id.cache?.buckets
            let m = 3
            let key = bkt.key
            //获取起始索引
            let begin = cacheHash(key: key!, mask: m)
    
            var i = begin
    
            var bucket = buckets![i!]
    
            repeat {
                if bucket.key == nil{
                    buckets![i!] = bkt
                    id.cache?.buckets = buckets!
                    break
                }
                i = cacheNext(i: i!, mask: m)
                bucket = buckets![i!]
            }while(i != begin)
        }
        
        
        func cacheNext(i:Int,mask:Int) ->Int? {
            var index = i
            if index != 0 {
                index = index - 1
                return index
            }else {
                return mask
            }
        }
        func cacheHash(key:Selector,mask:Int) ->Int? {
            
            let keyAddr = Unmanaged.passUnretained(key as AnyObject).toOpaque()
            let keyAddrStr = "\(keyAddr)"
            let lastKeyStr = keyAddrStr.suffix(keyAddrStr.count - 2)
            
            let keyInt = ConvertUtil.hexTodec(number: String(lastKeyStr))
            return keyInt & mask
        }
        
        //从类的方法列表中找
        lazy var lookupedCls:[ClassT] = []
        func methodTableLookup(inst:ClassT, sel:Selector) ->String? {
            
            lookupedCls.append(inst)
            
            let methodList = inst.rw?.methods
            
            if methodList != nil && methodList?.count != 0 {
                //先遍历自己类的方法
                for methodListT in methodList! {
                    for method in methodListT.methodList! {
                        if method.name == sel { //找到,直接返回
                            //                        print("\(inst.name!)找到了\(NSStringFromSelector(sel))")
                            let bucket = BucketT()
                            bucket.key = sel
                            bucket.imp = "\(NSStringFromSelector(sel))的实现"
                            let recCls = lookupedCls.first!
                            cache(bkt: bucket, id: recCls)  //找到该方法,缓存到自己的类中。
                            lookupedCls.removeAll()
                            return method.imp!
                        }
                    }
                }
            }
            
            //        print("\(inst.name!)没找到\(NSStringFromSelector(sel))")
            
            let superClass = inst.superClass
            
            if superClass == nil {
                return nil
            }else{
                return methodTableLookup(inst: superClass!, sel: sel)
            }
        }
        
        
        
        
      
        //方法初始化
        func classInitialize(cls:ClassT){
            //获取父类
            let superClass = cls.superClass
            
            if (superClass != nil) && !isInitialized(cls: superClass!) {
                classInitialize(cls: superClass!)  //递归调用
            }
            print("\r\n\r\n\r\n----------\(cls.name!)-----------")
            callInitialize(cls: cls)
        }
        
        //调用初始化方法
        func callInitialize(cls:ClassT?) {
    //        print("--------------------初始化了\(cls!.name!)的方法")
            let metaCls = cls?.isa
            metaCls?.isInitialized = true
            
            objMessageSend(inst: cls!, sel: NSSelectorFromString("--------initialize"))
        }
        
        //该类是否已经初始化
        func isInitialized(cls:ClassT) -> Bool{ //判断传入的类是否是元类
            if (cls.name?.contains("Meta"))! {//是,直接返回
                return cls.isInitialized
            }else{ //不是,获取其元类
                return cls.isa!.isInitialized
            }
        }
     
    //    lazy var goodStudentClass:ClassT = {
    //        let cls = ClassT()
    //        cls.name = "MJGoodStudent"
    //        cls.isa = goodStudentMetaClass
    //        cls.superClass = studentClass
    //        return cls
    //    }()
        lazy var studentClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJStudent"
            cls.isa = studentMetaClass
            cls.superClass = personClass
            return cls
        }()
        lazy var personClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJPerson"
            cls.isa = personMetaClass
            cls.superClass = objectClass
            return cls
        }()
        lazy var objectClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJObject"
            cls.isa = objectMetaClass
            cls.superClass = nsObjectClass
            return cls
        }()
        
        lazy var nsObjectClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJNSObject"
            cls.isa = nsObjectMetaClass
            cls.superClass = nil
            return cls
        }()
        
      
    //    lazy var goodStudentMetaClass:ClassT = {
    //        let cls = ClassT()
    //        cls.name = "MJMetaGoodStudent"
    //        let cache = CacheT()
    //        cls.cache = cache
    //        let rw = ClassRwT()
    //        rw.methods = []
    //        cls.rw = rw
    //        cls.superClass = studentMetaClass
    //        return cls
    //    }()
        
        lazy var studentMetaClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJMetaStudent"
            
            cls.superClass = personMetaClass
            
            let cache = CacheT()
            cls.cache = cache
            let rw = ClassRwT()
            rw.methods = []
            cls.rw = rw
            return cls
        }()
        lazy var personMetaClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJMetaPerson"
            
            cls.superClass = objectMetaClass
            let cache = CacheT()
            cls.cache = cache
            let rw = ClassRwT()
            rw.methods = []
            cls.rw = rw
            return cls
        }()
        lazy var objectMetaClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJMetaObject"
            
            cls.superClass = nsObjectMetaClass
    
            let cache = CacheT()
            cls.cache = cache
            let rw = ClassRwT()
            rw.methods = []
            cls.rw = rw
            return cls
        }()
        
        lazy var nsObjectMetaClass:ClassT = {
            let cls = ClassT()
            cls.name = "MJMetaNSObject"
            let cache = CacheT()
            cls.cache = cache
            let ro = ClassRoT()
            let method = MethodT()
            method.name = NSSelectorFromString("alloc")
            method.imp = "实现了alloc方法"
            let methodList = MethodListT()
            methodList.methodList = [method]
            ro.baseMethodList = [methodList]
            let rw = ClassRwT()
            rw.methods = ro.baseMethodList
            cls.rw = rw
            return cls
        }()
        
        class func alloc(){
            
        }
        func getNoMetaClass(clsName:String) -> ClassT?{
    //        if clsName == "MJMetaGoodStudent" {
    //            return goodStudentClass
    //        }else
            if clsName == "MJMetaStudent" {
                return studentClass
            }else if clsName == "MJMetaPerson" {
                return personClass
            }else if clsName == "MJMetaObject" {
                return objectClass
            }else if clsName == "MJMetaNSObject" {
                return nsObjectClass
            }else{
                return nil
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:iOS原理之Category的initialize原理

          本文链接:https://www.haomeiwen.com/subject/yjttzqtx.html