美文网首页
iOS原理之Category的关联对象

iOS原理之Category的关联对象

作者: yqc5521 | 来源:发表于2019-05-18 19:18 被阅读0次
    import UIKit 
    //类似于hash表
    class CustomMutableDictionary: NSObject {
        var dict:NSMutableDictionary?
        
        override init() {
            super.init()
            dict = NSMutableDictionary()
        }
      
        func setObject(_ anObject: Any?, forKey aKey: NSCopying) { 
            dict?.setValue(anObject, forKey: aKey as! String)
        }
        func object(forKey aKey: Any) -> Any? {
            return dict?.value(forKey: aKey as! String)
        }
    }
    
    //
    //  ObjcReference.swift
    //  iOS底层
    //
    //  Created by yanqunchao on 2019/5/18.
    //  Copyright © 2019 yanqunchao. All rights reserved.
    //
    
    import UIKit
    
    enum AccociationPolicy:Int {
        case OBJC_ASSOCIATION_ASSIGN = 0
        case OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1
        case OBJC_ASSOCIATION_COPY_NONATOMIC = 2
    }
    
    class ObjcReference: NSObject {
        //对象关联者
        class ObjcAssociation: NSObject {
            var value:Any?   //关联的值
            var policy: AccociationPolicy?  //关联的策略
        }
        
        //关联对象表
        class ObjectAssociationMap: CustomMutableDictionary {
            
            
          
            // key    refs:Int?  //对象关联属性的标记
            // value  objectAsscociate: ObjcAssociation? //与属性标记对应的关联者
        }
        
        //关联者哈希表
        class AssociationsHashMap: CustomMutableDictionary {
            //        key disguised_ptr_t:Int?  //存放关联对象的地址
            //        value objectAsscociateMap: ObjectAssociationMap?  //与对象地址对应的关联对象表
        }
        
        
        /**
         * 全局关联对象管理者
         */
        class AssociationsManager: NSObject {
            static let map: AssociationsHashMap =  AssociationsHashMap()
        }
        
        //为某个对象的某个属性关联值
        static func objectSetAssociativeReference(object: AnyObject, key: String, value: Any?, policy: AccociationPolicy) {
            
            let map = AssociationsManager.map
    
            
            let keyAddr = Unmanaged.passUnretained(object as AnyObject).toOpaque()
            let keyAddrStr = "\(keyAddr)"
          
            //先找object对应的map
            var objectAsscociationMap = map.object(forKey: keyAddrStr) as? ObjectAssociationMap
            
            if objectAsscociationMap == nil { //如果没有找到,创建一个map
                objectAsscociationMap = ObjectAssociationMap()
            }
          
            if value == nil { //设置的值为空
                objectAsscociationMap!.setObject(nil, forKey: key as NSCopying)
            }else{
                let objcAssociation = ObjcAssociation()
                objcAssociation.value = value
                objcAssociation.policy = policy
                objectAsscociationMap!.setObject(objcAssociation, forKey: key as NSCopying)
            }
            
            map.setObject(objectAsscociationMap, forKey: keyAddrStr as NSCopying)
            
         }
        //获取某个对象的某个属性
        static func objectGetAssociativeReference(object: AnyObject, key: String) -> Any?{
            
            let map = AssociationsManager.map
            
            
            let keyAddr = Unmanaged.passUnretained(object as AnyObject).toOpaque()
            let keyAddrStr = "\(keyAddr)"
             
            guard  let objectAsscociationMap = map.object(forKey: keyAddrStr) as? ObjectAssociationMap  else {
                return nil
            }
    
            
            guard  let objcAssociation = objectAsscociationMap.object(forKey: key) as? ObjcAssociation
                else {
                return nil
            }
            
            return objcAssociation.value
        }
        
        //移除某个对象的所有关联属性
        
        static func objectRemoveAssocations(object: AnyObject) {
            
            let map = AssociationsManager.map
            
            let keyAddr = Unmanaged.passUnretained(object as AnyObject).toOpaque()
            let keyAddrStr = "\(keyAddr)"
            
            guard  (map.object(forKey: keyAddrStr) as? ObjectAssociationMap) != nil  else {
                
                return
            }
            
            map.setObject(nil, forKey: keyAddrStr as NSCopying)
        }
    }
    
    
    //
    //  CategoryBasementAssociateObjectViewController.swift
    //  iOS底层
    //
    //  Created by yanqunchao on 2019/5/18.
    //  Copyright © 2019 yanqunchao. All rights reserved.
    //
    
    import UIKit
    ///关联对象
    class CategoryBasementAssociateObjectViewController: UIViewController {
     
        class Category1: NSObject {
            
            
            var name:String? {
                get{
                    return (ObjcReference.objectGetAssociativeReference(object: self, key: "name") as? String) ?? ""
                }
                set{
                    ObjcReference.objectSetAssociativeReference(object: self, key: "name", value: newValue, policy: AccociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
                }
            }
            
            var number:String? {
                get{
                    return (ObjcReference.objectGetAssociativeReference(object: self, key: "number") as? String) ?? ""
                }
                set{
                     ObjcReference.objectSetAssociativeReference(object: self, key: "number", value: newValue, policy: AccociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
                }
            }
        }
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = .white
            
         
            let category1 = Category1()
            category1.name = "小明"
            category1.number = "12345"
            
            let category2 = Category1()
            category2.name = "小明2"
            category2.number = "67890"
            
            print(category1.name ?? "")
            print(category1.number ?? "")
            
            print(category2.name ?? "")
            print(category2.number ?? "")
            
            category1.name = nil
            
            print(category1.name ?? "")
            
            
            //调用结束时,清除关联对象
            ObjcReference.objectRemoveAssocations(object: category1)
            ObjcReference.objectRemoveAssocations(object: category2)
            
        }
    }
    

    相关文章

      网友评论

          本文标题:iOS原理之Category的关联对象

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