iOS--@protocol 和 category 中如何使用 @property

1、category中使用@property

    首先需要明确的一点是,在category中不能添加实例变量。
    在我之前的一篇博客中有讲到,使用@property可以让编译器自动帮我们生成实例变量的setter/getter方法
    现在我们先在类中添加一个实例变量
//in .h
@interface MyClass : NSObject{
    NSString _name;
}
@end
//in  .m
@implementation MyClass{
    //NSString * _name;
}
@end
注意这里把实例变量声明在头文件里和实现文件里会有所不同
  • 实例变量在类的声明处声明,若它的访问权限不是@private,那它是可以被子类继承的,并且可以被其他类访问(若访问权限是@public)

  • 实例变量在类的实现处声明和在extension中声明,该实例变量是私有的,即使加@public访问权限也是私有的,不可以被子类继承,当然在category中也不能访问


然后创建一个类别
//in .h
#import "MyClass.h"
@interface MyClass (Extension)
@property(nonatomic,copy)NSString * name;
@end
//in .m
#import "MyClass+Extension.h"
@implementation MyClass (Extension)
//@synthesize name = _name;
@end
编译器给出了警告
大意是说属性name需要提供setter/getter方法,也就是说现在编译器不能自动给我们生成setter和getter方法了
添加一句@synthesize name = _name;也是不行的


此时就需要我们自己写setter/getter方法了
//in category.m
#import "MyClass+Extension.h"
@implementation MyClass (Extension)
- (void)setName:(NSString *)name{
    _name = name;
}
- (NSString *)name{
    return _name;
}
@end
如果之前我们将实例变量声明在类声明部分的话,这样执行一发,就没问题了。但是很多时候,我们不希望去修改已经写好的类,而且定义的实例变量在类实现部分。那么此时在category中我们就不能直接访问到该实例变量了,例如
//in .h
@interface MyClass : NSObject
@end
//in  .m
#import "MyClass.h"

@implementation MyClass{
    NSString * _name;
}
@end
像这种情况,我们就需要利用到runtime了。
objc_setAssociatedObject 相当于 setValue:forKey 进行关联value对象

objc_getAssociatedObject 用来读取对象

objc_AssociationPolicy  属性 是设定该value在object内的属性,即 assgin, (retain,nonatomic)...等

 objc_removeAssociatedObjects 函数来移除一个关联对象,或者使用objc_setAssociatedObject函数将key指定的关联对象设置为nil。
我们可以使用这四个函数,在category中任意添加实例变量。例如之前的就可以写成
#import "MyClass+Extension.h"
#import <objc/runtime.h>
@implementation MyClass (Extension)
- (void)setName:(NSString *)name{
    objc_setAssociatedObject(self,@selector(name),name,OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
    NSString *n = objc_getAssociatedObject(self, @selector(name));
    return n;
}
@end
就相当于在类中添加了一个名为name的实例变量,与_name不同。
当然使用这种方式并不比使用@property管理内存方便。

2.在@protocol中使用@property

在@protocol中使用@property在编译阶段,编译器会自动帮我们加上setter/getter的声明,但是实现还是需要采用该协议的类去写。因此在协议中使用@property主要是希望采用该协议的类能够实现该属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值