category&extension

作者: koula | 来源:发表于2016-12-12 21:17 被阅读16次

    category

    使用场景

    1.为已经存在的类添加方法。

    2.可以把类的实现放到不同的文件中。

    3.声明私有方法。

    表现形式

    #import "ClassName.h"
    @interface ClassName (CategoryName)
    //method declarations
    @end
    

    使用注意

    category的使用

    声明:

    @interface NSString(Add)
    - (NSString *)Add:(NSString*)string;
    @end
    

    实现:

    @implementation NSString(Add)
    - (NSString *)Add:(NSString*)string
    {
        return [self stringByAppendingString:string];
    }
    @end
    

    调用:

    NSString *testString = @"Hello";
    
    testString = [testString Add:@"World!"];
    NSLog(@"%@", testString);    
    

    输出:

    2015-11-04 20:22:14.000 TestIphone[9986:238906] HelloWorld!
    

    因为category是在运行时决定的,所以其可以在没有类源码的情况下添加category,这也就导致了其不能不能添加实例变量。如果category想要访问类的任何实例变量,则必须导入其所扩展类的接口文件。当类别中的方法与原有类中的方法名冲突是,类别的方法将取而代之(置于方法链表的前面)。当category中出现方法名与原有类方法重名时,category的方法被加入的方法列表的前面,而原来的类方法则处于新方法列表的后面。这就造成了我们所见的category方法覆盖了原有类的同名方法。主要是因为运行时查找方法的时候是沿着方法列表顺序查找的,只要找到对应的方法即返回。

    也正因为category是运行时决定的,所以可以通过runtime机制添加实例变量。主要API为:

    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    id objc_getAssociatedObject(id object, const void *key)
    

    使用示例:
    声明:

    @interface NSString(Add)
    @property (nonatomic, strong)NSString *myNameString;
    - (NSString *)Add:(NSString*)string;
    @end
    

    实现:

    #import "objc/runtime.h"
    
    static const char *myNameString = "myNameString";
    @implementation NSString(Add)
    - (NSString *)Add:(NSString*)string
    {
        return [self stringByAppendingString:string];
    }
    
    // get方法
    - (NSString *)myNameString {
     return (NSString *)objc_getAssociatedObject(self, myNameString);
    }
    // set方法
    - (void)setMyNameString:(NSString *)nameString {
        objc_setAssociatedObject(self, myNameString, nameString, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    

    调用:

    NSString *testName = [[NSString alloc] init];
    testName.myNameString = @"zhanyawei";
    NSLog(@"%@", testName.myNameString);
    

    输出:

    2015-11-04 20:31:58.496 TestIphone[10008:242495] zhanyawei
    

    extension

    使用场景

    1.隐藏类的私有信息。

    表现形式

    #import "ClassName.h"
    @interface ClassName ()
    //method declarations
    @end
    

    使用注意

    常用于声明公有的只读属性和私有的读写属性。
    比如:

    @interface MyClass : NSObject  
    @property (retain, readonly) float value;  
    @end  
    
    // 私有的extension, 隐藏在主实现文件中.  
    @interface MyClass ()  
    @property (retain, readwrite) float value;  
    @end 
    

    extension和category行驶时看起来差不多,但是其行为却差别很大。extension在编译期和原有的类一起编译成一个完整的类,其与原有的类‘同生共死’。所以定义extension需要原有类的源码,也可以定义实例变量。

    参考

    Cocoa Core Competencies

    Dive into Category

    相关文章

      网友评论

        本文标题:category&extension

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