合成存取方法
为什么要合成 存 - 取 方法
- 前介绍了良好的封装,对每个对象的成员变量都设置一个setter方法来访问他,这种做法虽然很白=准但是一旦我们包含了更多的成员变量的时候为每个变量写一个setter 和 getter 方法是很麻烦
- 从Objective-C 2.0版本开始,它自动合成了setter方法和getter方法。
让系统自动合成setter和getter方法只要如下两步。
-
在类接口部分使用@property指令定义属性。
-
在类实现部分使用@synthesize指令声明该属性。
当采用上述两个步骤合成存取方法之后,不仅会合成成对的stter和getter方法,还会自动在类实现部分定义一个与getter方法同名的成员变量。Xcode编码规范推荐奖成员便利囊定义为下划线开头 @synthesize window = _window; 这个代码告诉编译者 合唱的property 对应的成员变量 是_window @synthesiz 语法如下 @synthesize property 名[= 成员变量名]
合成存取的实例
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKuser : NSObject
@property (nonatomic) NSString* name;
@property NSString* pass;
@property NSDate* birth;
@end
NS_ASSUME_NONNULL_END
#import "FKuser.h"
@implementation FKuser
// 为三个变量合成setter与getter方法
// 我们指定 name = _name 对name property属性进行而外控制
@synthesize name = _name;
@synthesize pass;
@synthesize birth;
- (void) setName :(NSString*) name {
self->_name = [NSString stringWithFormat:@"+++%@" , name];
}
@end
#import <Foundation/Foundation.h>
#import "FKuser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKuser * user = [[FKuser alloc] init];
[user setName:@" 勒布朗"];
[user setPass:@"0120"];
[user setBirth:[NSDate date]];
NSLog(@"NBA球星 %@ 的生日为 %@ 序号为%@", [user name], [user pass], [user birth]);
}
return 0;
}
额外的操作-指示符
何为引用计数
引用计数是Objective-C 内存回收的概念,
当一个对象的引用计数大子0时表明该对象还不应该被回收。由于 NSinteger等基础类型,以及short. float. double、
结构体等各种C数据类型都不存在内存回收的问题,因此使用assign 即可
-
- assign
该指示符指定对属性只是进行简单赋值,不更改对所赋的值的引用计数。这个 指示符主要适用于 NSInteger 等基本类型,以及short、float、double、结构体等各种C 数据类型
-
- atmoic(nonatomic) :
指定合成的存取方法是否为原子操作。所谓原子操作,主要指是否线程安全。如果使用 atomic,那么合成的存取方法都是线程安全。当一个线程进入存取方法的方法体之后,其他线程无法进入该存取方法,这样就可以避免多线程并发破坏对象的数据完整性,atomic 是默认值。虽然 atomic可以保证对象数据的完整性,但atomic 的线程安全会造成性能下降,因此,在大多数单线程环境下
使用nonatomic 来提高存取方法的访问性能。
- atmoic(nonatomic) :
-
- copy
-
如果使用copy 指示符,那么当调用setter 方法对成员变量赋值时,会将被赋值
的对象复制一个副本,再将该副本赋值给成员变量。copy 指示符会将原成员变量所引
用对象的引用计数减 1。当成员变量的类型是可变类型,或其子类是可变类型时,被
赋值的对象有可能在赋值之后被修改,如果程序不需要这种修改影响 setter 方法设置
的成员变量的值,此时就可考虑使用copy 指示符 -
- readonly 和 readwrite:
readonly 指示系统只合成getter 方法,不再合成 setter 方法:readwrite
是默认值,指示系统需要合成 setter、getter 方法。
- readonly 和 readwrite:
-
- retain
-
retain:使用 retain 指示符定义属性时,当把某个对象赋值给该属性时,该属性原来所
引用的对象的引用计数减 1,被赋值对象的引用计数加 1。
当系统启用ARC机制的时候就不需要或者很少使用retain -
- strong 和 weak
-
strongl指示符指定该属性对被赋值对象持有强引用,而 weak 指示符指
定该属性对被赋值对象持有弱引用。 -
-------强引用的意思是,只要该强引用指向被赋值的对
象,那么该对象就不会自动回收
-------弱引用的意思是,即使该弱引用指向被赋值的对象,
该对象也可能被回收。
注意
在启动 ARC 机制时,使用strong、weak 指示符将十分方便。如果程序不希望
被该属性引用的对象被回收,那就应该使用strong 指示符;如果程序需要保证性能,
避免内存溢出,则可以使用 weak 指示符。使用 weak 指示符时需要小心,
当程序通过该weak 属性來访问被引用的对系时,该对象可能已经被回收了。对于声明为 1
weak 的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil,这样能有效的防治悬空指针,weak指示符可有效的防止悬空指针
- unsafe_unretained
unsafe unretained!这个指示符与 weak 指示符基本相似,对于只被 unsafe unretained
指针所指向的对象,该对象也可能被回收。与 weak 指针不同的是,当 unsafe unretained
指针所引用的对象被回收后,unsafe unretaincd 指针不会被赋值为 nil,因此这可能导
致程序崩溃。一般来说,使用 unsafe unretained 指示符不如使用 weak 指示符。
copy字符 实例
不引用copy
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
//copy实例
//NSString 有一个可变的 NSMutableString 子类
@interface fk : NSObject
//
@property (nonatomic) NSString *name;
@end
NS_ASSUME_NONNULL_END
#import "fk.h"
@implementation fk
//其实在xcode4.0之后此处已经不需要 @synthesize name了系统就已经自动合成存取方法
@synthesize name;
@end
#import <Foundation/Foundation.h>
#import "fk.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
fk * book = [[fk alloc] init];
NSMutableString* str = [NSMutableString
stringWithString:@"疯狂3g!"] ;
[book setName:str]; //第一次为book 的name属性赋值域
NSLog(@"book 的 name 为: %@", [book name]);
[str appendString:@"西安邮电大学的iOS俱乐部"];
//修改了str字符串
// 当我们么有在类接口地方加上copy定义的时候,此时的给str再次复制会改变子类
// NSMutableString的内容
NSLog(@"book 的 name 名字为 %@", [book name]);
}
return 0;
}
引用copy
@interface fk : NSObject
//
@property (nonatomic,copy) NSString *name;
@end
对于copy的理解
当在接口部分加上 copy的时候 [book setName:str]的操作会讲把str指向的子类复制出来一个副本,再将副本作为setname的参数值 这样子再次修改str的值的时候 book的name属性不会改变
使用点语法
对于频繁使用setter 和getter语法来获取和引用对象的属性 OC语言专门设置了类似于c语言结构体一样的点语法
点语法实例
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface fkcard : NSObject
@property (nonatomic, copy) NSString *color;
@property (nonatomic, copy) NSString *name;
@end
NS_ASSUME_NONNULL_END
#import "fkcard.h"
@implementation fkcard
//前面提到了不用程序一样运行
//@synthesize name;
//@synthesize color;
@end
#import <Foundation/Foundation.h>
#import "fkcard.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
fkcard *card = [[fkcard alloc] init];
card.color = @"red";
card.name = @"桃心";
NSLog(@"这张牌的名字为 %@, 颜色为 %@", card.name, card.color);
}
return 0;
}