extension和category(一)

  category 

OC中使用category匿名类的方式来扩展已经存在类,添加方法、“属性”等,有时候为了代码看起来更加清楚,也可以把一系列相关的方法放在一个匿名类中。

一、category不可以添加实例变量(interface的{}中声明的变量) :instance variables may not be placed in categories

// Student+Image.h 

#import <Foundation/Foundation.h>
#import "Student.h"
@class UIImage;

@interface Student(Image){
    //NSString *urlStr; //instance variables may not be placed in categories
}
@property (nonatomic) UIImage *avarta;
-(void)goHome;
@end

 

二、给category匿名类添加属性。由于在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,所以,category中声明的property并不会被自动生成一个对应的 实例变量,并且需要@dynamic 关键字修饰,表示属性对应的get和set方法由我们自己声明。我们可以通过一下两种方式模拟实现property:

  1、objc_setAssociatedObject,设置关联对象。

  2、implementation文件中声明一个局部变量,get、set方法操作此变量即可。

// Student+Image.h 

#import <Foundation/Foundation.h>
#import "Student.h"
@class UIImage;

@interface Student(Image){
    //NSString *urlStr; //instance variables may not be placed in categories
}
@property (nonatomic) UIImage *avarta;
-(void)goHome;
@end

// Student+Image.m
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "Student+Image.h"

//@interface Student(Image)(){
//    
//}
//
//@end    //error

@implementation Student(Image)
@dynamic avarta;
UIImage *avarta_;

-(UIImage *)avarta{
    UIImage *obj = objc_getAssociatedObject(self, @"_avarta");
    if(!obj){
        obj = [UIImage imageNamed:@"invoice"];
    }
    return obj;
}

-(void) setAvarta:(UIImage *)image{
    if(image){
        objc_setAssociatedObject(self, @"_avatar", image, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

@end

// 方法二
-(UIImage *)avarta{
    return avarta_;
}

-(void) setAvarta:(UIImage *)image{
    avarta_ = image
}

 三、category声明属性、方法可以被Student、以及Student的子类访问和继承。当匿名类中声明了与被扩展类中相同的变量时,两个方法会同时存在,方法调用的时候调用最先在方法列表中被找到的那个(有待继续研究)。现在通过对比Student、Student+image、SubStudent的实例变量、属性、方法来研究一下三者的关系。

 Student

   // Student.h 
#import <Foundation/Foundation.h>

@interface Student : NSObject {
   @public NSString *sno;
}
@property (nonatomic, copy,readonly) NSString *name;
-(void)goHome;
@end

   // Student.m
#import "Student.h"

@interface Student(){
   @package NSString *cno;
}
@property (nonatomic, copy) NSString *name;
@end

@implementation Student

-(instancetype)init{
    if(self = [super init]){
        _name = @"lcy";
        sno = @"1";
        cno = @"cno";
       // [self goHome];
    }
    return self;
}

-(NSString *)name{
    [self goHome];
    return _name;
}

-(void)goHome{
    NSLog(@"goHome in Student");
}

@end

Student 的实例变量、属性、方法有(sno、cno、_name)(name)(goHome、init、name、setName)

 

Student+Image

// Student+Image.h
#import <Foundation/Foundation.h>
#import "Student.h"
@class UIImage;

@interface Student(Image){
    //NSString *urlStr; //instance variables may not be placed in categories
}
@property (nonatomic) UIImage *avarta;
-(void)goHome;
@end

// Student+Image.m
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "Student+Image.h"

//@interface Student(Image)(){
//    
//}
//
//@end    //error

@implementation Student(Image)
@dynamic avarta;
UIImage *avarta_;

-(UIImage *)avarta{
    UIImage *obj = objc_getAssociatedObject(self, @"_avarta");
    if(!obj){
        obj = [UIImage imageNamed:@"invoice"];
    }
    return obj;
}

-(void)goHome{
    NSLog(@"goHome in Student(image)");
}

-(void) setAvarta:(UIImage *)image{
    if(image){
        objc_setAssociatedObject(self, @"_avatar", image, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

@end

Student+Image新增的实例变量、属性、方法有()(avarta)(goHome、setAvarta、avarta)

Student目前拥有的实例变量、属性、方法有(sno、cno、_name)(name、avarta)(goHome、init、name、setName、goHome、setAvarta、avarta) ps:同时存在两个同名方法

 

SubStudent

// SubStudent.h
#import <Foundation/Foundation.h>
#import "Student+Image.h"

@interface SubStudent: Student
-(UIImage *)getImage;
@end


// SubStudent.m
#import "SubStudent.h"

@implementation SubStudent
-(UIImage *)getImage{
    NSString *name = sno;   // 子类可引用父类成员变量
    
    return  self.avarta;    // 可引用image category中生命的property
}
@end

SubStudent新增的实例变量、属性、方法有()()(getImage)

SubStudent目前拥有的实例变量、属性、方法有(sno、cno、_name)(name、avarta)(goHome、init、name、setName、goHome、setAvarta、avarta、getImage)

ps:再写要崩接下文http://www.cnblogs.com/beautylcy/p/7214373.html

 

 

 

 

posted @ 2017-07-20 20:39  一坨☁️  阅读(143)  评论(0编辑  收藏  举报