@property是OC中最为常见的关键字之一,实际的项目开发中@property在类中出现的频率甚至达到了100%。但是对于@property的使用规则,你真的完全掌握吗?我觉得我做不到!所以在这里针对@property的相关内容,进行记录,省的将来再学第三遍iOS......
在这里我按照@property的发展顺序进行代码书写,注意点在代码中可以清晰的看到。@property大约是在Xcode4.4的时候提出来的,在此之前,对于类中的属性,我们需要去手动编写繁琐的setter-getter方法。Apple就是为了简化我们的代码编写,所以才引入了@property和@synthesize关键字。
@property诞生之初的基本用法
#Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
int _age;
double _height;
double _weight;
NSString *_name;
}
/*
setter:
作用: 用于给成员变量赋值
1.一定是对象方法
2.一定没有返回值
3.方法名称以set开头, 后面跟上需要赋值的成员变量名称, 并且去掉下划线, 然后首字母大写
4.一定有参数, 参数类型和需要赋值的成员变量一直, 参数名称就是需要赋值的成员变量名称去掉下划线
*/
//- (void)setAge:(int)age;
- (void)setHeight:(double)height;
- (void)setWeight:(double)weight;
- (void)setName:(NSString *)name;
/*
@porperty是一个编译器指令
在Xocde4.4之前, 可以使用@porperty来代替getter/setter方法的声明
也就是说我们只需要写上@porperty就不用写getter/setter方法的声明
编译器只要看到@property, 就知道我们要生成某一个属性的getter/setter方法的声明
- (void)setAge:(int)age;
- (int)age;
*/
@property int age;
/*
- (void)set_age:(int)_age;
- (int)_age;
*/
@property int _age;
/*
getter:
作用: 用于获取成员变量的值
1.一定是对象方法
2.一定有返回值, 返回值类型和需要获取的成员变量的类型一致
3.方法名称就是需要获取的成员变量的名称去掉下划线
4.一定没有参数
*/
//- (int)age;
- (double)height;
- (double)weight;
- (NSString *)name;
@end
#Person.m
#import "Person.h"
@implementation Person
- (void)setAge:(int)age
{
_age = age;
}
- (void)setHeight:(double)height
{
_height = height;
}
- (void)setWeight:(double)weight
{
_weight = weight;
}
- (void)setName:(NSString *)name
{
_name = name;
}
- (int)age
{
return _age;
}
- (double)height
{
return _height;
}
- (double)weight
{
return _weight;
}
- (NSString *)name
{
return _name;
}
@end
@synthesize的基本用法
说过了@property的最初是用法,我们不得不提一下@synthesize这个关键字,Apple在最初设计@property之初,为了与@property相照应,完成完善的setter-getter方法,引入了@synthesize,因为在最初的设计中,@property只负责setter-getter方法的生命,而没有setter-getter方法的实现,所以引入了@synthesize,具体用法如下:
#Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
@public
int _age;
int age;
int _number;
}
/*
@porperty是一个编译器指令
在Xocde4.4之前, 可以使用@porperty来代替getter/setter方法的声明
也就是说我们只需要写上@porperty就不用写getter/setter方法的声明
编译器只要看到@property, 就知道我们要生产某一个属性的getter/setter方法的声明
- (void)setAge:(int)age;
- (int)age;
*/
@property int age;
@end
#Person.m
#import "Person.h"
@implementation Person
/*
@synthesize是一个编译器指令, 它可以简化我们getter/setter方法的实现
什么是实现:
在声明后面写上大括号就代表着实现
1.在@synthesize后面告诉编译器, 需要实现哪个@property生成的声明
2. 告诉@synthesize, 需要将传入的值赋值给谁和返回谁的值给调用者
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
*/
//@synthesize age = _age;
/*
- (void)setAge:(int)age
{
_number = age;
}
- (int)age
{
return _number
;
}
*/
//@synthesize age = _number;
// 如果在@synthesize后面没有告诉系统将传入的值赋值给谁, 系统默认会赋值给和@synthesize后面写得名称相同的成员变量
// _age? age;
@synthesize age;
/*
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
*/
@end
#mian.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *p = [Person new];
[p setAge:88];
// NSLog(@"age = %i , p->_age = %i", [p age], p->_age);
// NSLog(@"_age = %i, _number = %i", p->_age, p->_number);
NSLog(@"_age = %i, age = %i", p->_age, p->age);
return 0;
}
@porperty功能的增强
看完前面的例子,我们不难分析出,为什么会蹩脚的提出@property和@synthesize,而不是将两个功能集成到一个关键字呢?同样也是出于这方面考虑,Apple对@property进行了功能增强,具体代码如下:
#Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
/*
{
@public
int _age;
int age;
}
*/
/*
从Xcode4.4以后apple对@property进行了一个增强, 以后只要利用一个@property就可以同时生成setter/getter方法的声明和实现
没有告诉@property要将传入的参数赋值给谁, 默认@property会将传入的属性赋值给_开头的成员变量
@property有一个弊端: 它只会生成最简单的getter/setter方法的声明和实现, 并不会对传入的数据进行过滤
如果想对传入的数据进行过滤, 那么我们就必须重写getter/setter方法
如果不想对传入的数据进行过滤, 仅仅是提供一个方法给外界操作成员变量, 那么就可以使用@property
如果利用@property来生成getter/setter方法, 那么我们可以不写成员变量, 系统会自动给我们生成一个_开头的成员变量
注意: @property自动帮我们生成的成员变量是一个私有的成员变量, 也就是说是在.m文件中生成的, 而不是在.h文件中生成的
*/
// age? _age;
/*
- (void)setAge:(int)age;
- (int)age;
*/
@property int age;
@end
#Person.m
#import "Person.h"
@implementation Person
/*
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
*/
// 如果重写了setter方法, 那么property就只会生成getter方法
// 如果重写了getter方法, 那么property就只会生成setter方法
// 如果同时重写了getter/setter方法, 那么property就不会自动帮我们生成私有的成员变量
- (void)setAge:(int)age
{
if (age < 0) {
age = 0;
}
_age = age;
}
//- (int)age
//{
// return _age;
//}
@end
#mian.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *p = [Person new];
[p setAge:-88];
// NSLog(@"age = %i", [p age]);
// NSLog(@"_age = %i, age = %i", p->_age, p->age);
return 0;
}
@porperty修饰符
#Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
/*
如果给一个属性同时提供了getter/setter方法, 那么我们称这个属性为可读可写属性
如果只提供了getter方法, 那么我们称这个属性为只读属性
如果只提供了setter方法, 那么我们称这个属性为只写属性
如果既没有提供getter也没有提供setter方法, 那么我们称这个属性为私有属性
格式:
@property(属性修饰符) 数据类型 变量名称;
*/
// readwrite: 代表既生成getter方法 , 也生成setter方法
// 默认情况下 @property就是readwrite的
@property(readwrite) int age;
/*
- (void)setHeight:(double)height;
- (double)height;
- (void)setHeight:(double)height;
- (double)abc;
*/
@property(getter=abc) double height;
/*
- (void)setWeight:(double)weight;
- (void)tiZhong:(double)weight;
*/
@property(setter=tiZhong:) double weight;
// readonly: 代表只生成getter方法不生成setter方法
@property(readonly) NSString * name;
// 是否已婚
// 程序员之间有一个约定, 一般情况下获取BOOL类型的属性的值, 我们都会将获取的方法名称改为isXXX
@property(getter=isMarried) BOOL married;
@end
#Person.m
#import "Person.h"
@implementation Person
@end
#mian.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *p = [Person new];
// p.age = 30;
// p.name = @"猪立叶";
// p.height = 1.88;
// p.weight = 200.0;
// [p setName:@"lnj"];
p.height = 99;
NSLog(@"height = %f", [p abc]);
[p tiZhong:100.0];
NSLog(@"weight = %f", [p weight]);
[p setMarried:YES];
/*
if ([p married]) {
NSLog(@"已婚");
}else
{
NSLog(@"未婚");
}
*/
if ([p isMarried]) {
NSLog(@"已婚");
}else
{
NSLog(@"未婚");
}
return 0;
}
欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!
![](https://img.haomeiwen.com/i1678515/5d337549f5ca7ed4.jpg)
网友评论