知识点总结

iOS 分类(Category)

2019-04-09  本文已影响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)大揭秘

上一篇下一篇

猜你喜欢

热点阅读