属性
@interface Circle {
float radius; // 通过此方法定义属性需要自己手动编写setter和getter
@property float radius1; // @property预编译指令会自动声明setter和getter
}
@end
@implementation Circle
@synthesize radius1; // @synthesize预编译指令会生成setter和getter的实现代码,但不可见
@end
// @property变量的声明可以是在@interface中也可以是在@implementation中区别在于
// 前者的变量子类可以进行访问,而后者只能在本类中访问,另外不能来个地方都进行声明
属性特性
在特性声明的时候,可以添加以下关键字,告诉编译器如何实现setter和getter方法。
assign //简单赋值,主要用于基本数据类型
copy //创建一个新的对象,新的对象和旧对象是独立的两个对象
retain //将对象计数器加1
readonly //表示只读属性 只会生成getter方法 不会生成setter方法
readwrite //默认值,表求生成setter和getter方法
nonatomic //非原子访问,不加同步 ,多线程并发访问提高性能 (对多线程的保护,防止在未写完,被另一个线程读取,造成数据错误)
atomic // 原子访问,提供线程保护
@dynamic
指令告诉编译器不要生成变量和代码,则可以编写自己的访问方法
当要修改自动生成的方法名时,可以采用@property(getter=mygetter) BOOL flag
指定对于的getter
和setter
对应的方法
类别(Category)
通过oc的动态运行时分配机制,可以对现有的类添加新方法,这些方法在oc中称为类别
通常类别代码会放到单独的文件中,通常以"类名称+类别名称
"风格进行命名
以上为一个NSString
的类别,添加了一个方法将字符串的长度直接转为NSNumber
对象返回,使用上如何NSString对象都能响应lengthAsNumber方法
类别的缺陷
类别的优势
- 将类的实现代码分散到不同文件或框架中
- 创造对私有方法的前向引用
- 向对象添加非正式协议
类扩展,一种特殊的类别
非正式协议和委托类别
非正式协议是相对于正式协议而言的,其中的区别查看此篇 非正式协议和正式协议的区别
正式协议
在编码中经常会用到委托(delegate)
的技术,即一个类委托另一个类执行某些工作,假设目前有两个类,一个是用户的UI交互控制类,另一个是数据处理类,通常逻辑中UI交互控制类中会拥有一个数据处理类处理由用户交互产生的数据变化,但有时候数据变化又会导致UI变化,这个时候除了通过UI类传递一个block给数据类调用外还可以通过delegate的方式使得数据类可以调用UI类的相关更新方法。
/**
* 协议
*/
// 协议的声明
@protocol UIUpdate
// 方法声明
- (void) updateButton: (NSString *)text;
@optional
// 此修饰符下什么的方法可选择性实现
@required
// 此修饰下的方法必须实现
// 没有带修饰符的方法也必须实现
@end
// 协议可可以继承父协议
// @protocol UIUpdate<superProtocol>
// 当某个类采用这个协议时,意味该类将实现其中声明的方法
//采用协议
/**
* UI控制类
*/
@interface UIController : NSObject <UIUpdate, 协
议可有多个>
//...
@end
@implementation UIController
- (void) updateButton: (NSString *)text {
// 相关更新UI操作
}
@end
/**
* 数据处理类
*/
@interface DataHandler : NSObject
// 定义一个代理对象,用以调用协议中的方法
@property(nonatomic,weak)id <UIUpdate>delegate;
- (void) handlerData;// 某个执行中需要更新UI的方法
@end
@implementation DataHandler
(void) handlerData {
//通过respondsToSelector判断对象是都有能响应的特定方法
if ([_delegate respondsToSelector:@selector(updateButton:)]) {
[_delegate updateButton: @"xxx"];
// 调用委托对象此方法
}
}
@end
/**
* main
*/
int main(int argc,constchar * argv[]) {
@autoreleasepool {
UIController *uiController = [[UIController alloc] init];
DataHandler *dataHandler = [[DataHandler alloc] init];
dataHandler.delegate = uiController;
}
}
在使用的数据类型和方法参数中可以指定协议名称,如某个方法传递一个id对象时可以指定-(void)oneMethods:(id<某协议>)obj;