美文网首页知识点总结
iOS 分类(Category)

iOS 分类(Category)

作者: 飞不越疯人院 | 来源:发表于2019-04-09 16:50 被阅读26次

    1:日常开发中用分类做哪些工作?

    1. 声明调用Framework或者类的私有方法;

    例如Cat类有一个私有方法
    -(void)privateEat:(NSString *)somthing;
    viewDidLoad方法中想要使用Cat的这个方法;
    Cat* d = [[Cat alloc] init];
    [d privateEat:@"Fish"];
    这样不能编译通过, 但是我们给Cat添加一个分类, 并且在分类.h中声明这个方法, 就可以正常调用这个方法了;示例代码

    1. 为体积庞大的类减负;

    例如我们的工程中在LaunchVC中有很多逻辑处理(不讨论合理不合理), 其中路由部分有上千行代码, 这时采用Category方式将路由部分剥离开来很好的增加可读性;


    Category的.h文件
    Category的.m文件
    在LaunchVC的合适地方调用
    1. 添加非正式协议;示例代码

    2: 分类的特点?

    1. 运行时生效: 编写好分类后并没有立即将分类添加到相应的类中, 在运行时通过runtime将分类内容绑定到相应的类中;
    2. 为系统类添加分类; 例如对UIView添加分类用self.x直接获取到x坐标;
    3. 多个分类有同名方法时, 最后编译的分类的方法会被实现(覆盖前面的);
    4. 分类添加的方法可以"覆盖"宿主类方法;
    5. 名字相同的分类会引起编译报错;

    3: 分类中可以添加哪些内容?

    1. 添加实例方法;
    2. 添加类方法;
    3. 添加(非正式)协议;
    4. 添加属性; 实际上是只声明了settergetter, 并没有添加成员变量;

    4: 能不能为分类添加成员变量?

    可以添加; 不能在分类声明和定义实现的过程中添加成员变量; 但是可以通过关联对象的方式添加;通过这种方式添加的成员变量没有添加到元数组中; 所有不同的类添加的关联对象被放到了一个统一的全局容器中(AssociationsHashMap);

    @property属性 = 成员变量+ getter + setter ; 通过对象关联方式,添加属性进而实现添加成员变量(能不能调用?如何调用?)

    关联对象所用到方法:
    const void *NameKey = nil;
    
    - (void)setName:(NSString *)name {
      /**
         objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>)
         把value通过key, 用policy这种策略关联给object;
       */
        objc_setAssociatedObject(self, NameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)name {
        /**
           objc_getAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>)
           根据指定key从objectz中获取对应关联值;
         */
        return objc_getAssociatedObject(self, NameKey);
    }
    
    /**
       objc_removeAssociatedObjects(<#id  _Nonnull object#>)
       移除obeject的所有关联对象
     */
    

    5: 附加: 成员变量, 属性, 实例变量区别

    #import <Foundation/Foundation.h>
    NS_ASSUME_NONNULL_BEGIN
    
    @interface Cat : NSObject  {
        ///成员变量
        NSString    *color;
        NSInteger   age;
    }
    
    ///属性
    @property (nonatomic, copy) NSString *kind;
    
    @end
    NS_ASSUME_NONNULL_END
    

    声明在大括号内是成员变量, 下面的property修饰的是属性; 实例变量本质上就是成员变量, 实例变量是相对于类的概念;

    成员变量 属性
    不会自动生成setter和getter, 需要自己手动实现 自动生成setter和getter方法
    外部不能用"."语法, 要用"->" 外部可以使用"."语法(本质上是settergetter)
    默认是@protected修饰 默认是@protected修饰(外部并不能直接访问这个成员变量, 而是需要通过gettersetter)

    成员变量外部不能用"."语法调用, 需要用"->"方式


    成员变量的默认修饰为@protected, 如果外部想调用需要手动修改为@public; 如图:


    示例代码下载

    有理解错误的地方,请指正;


    参考文章
    iOS 成员属性和成员变量的区别
    iOS 属性(property)大揭秘

    相关文章

      网友评论

        本文标题:iOS 分类(Category)

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