1. 点语法
p.age = 10 == [p setAge:10]
int a = p.age == [p age];
点语法的实质是方法调用,属于编译器特性,在编译的时候将点语法变为方法,通过断点调试即可证明。另外,如果我们在setter中定义:
- (void)setAge:(int)age
{
// _age = age;
self.age = age;
}
运行会导致死循环,因为self.age在编译器编译编译的时候将self.age 转换成 [self setAge:(参数)]。
同理,在getter中
- (int)age
{
return self.age;
}
一样会导致死循环。
2. 成员变量作用域
成员变量思维修饰是@public时,在任何地方都能访问对象的成员变量
@prvate :只能在当前类的对象方法中直接调用(声明在@implementation中得变量默认属性)。
@protected:能在当前类和子类的对象方法中直接访问(声明在@interface中得变量默认属性)。
@package:处在同一个框架中得变量都可以访问。
另外,声明在.m文件中的@implementation里面的变量只能在本文件中访问。
代码示例,定义一个Person类,另外定义一个Student类,并且让Student类继承Person类:
@interface Person : NSObject
{
int _no;
@public // 在任何地方都能直接访问对象的成员变量
int _age;
@private // 只能在当前类的对象方法中直接访问
int _height;
@protected // 能在当前类和子类的对象方法中直接访问
int _weight;
int _money;
}
// 变量的setter和getter 此处省略
@end
age变量可以在整个程序中访问,_height只可以在Person类的对象方法中访问,即在Person.m中可以使用语句“_height =20;”或者“self.height=20”直接设置_height的值,而在Student.m中使用以上语法将会报错。而_weight和_money不仅可以在Person中使用以上方法,并且在Person的子类Student中也可以使用。
3.@property和@synthesize
使用@property关键字可以快速生成成员变量setter和getter声明
使用方法:@property变量类型 变量名
例如:
@property int weight;
该段代码就等同于:
- (void)ssetAge:(int)age;
- (int)age;
@synthesize关键字可以帮我们快速生成成员变量setter和getter的实现,使用方法:@synthesize 变量名 = (参数)
例如:
@synthesize age = _age;
该段代码就等同于:
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
如果在@interface中没有_age这个变量,那么@synthesize会新建该成员变量,其参数是@private;如果不设置参数的话,即 @synthesizeage; 那么@synthesize默认访问的是age变量;假如我们已经实现了该成员变量的setter或者getter,那么Xcode就会跳过我们已经实现的方法,只生成未实现的方法。另外,在Xcode4.4以后的版本中,只需要@property就可以生成成员变量的声明和实现,即@synthesize可以省略。
4. id
id是一种类型,本质是一种万能指针,其定义如下:
typdef struct objc object{
Class isa;
}*id;
OC对象:除基本类型(int char enum)以外的类型。
通过id可以指向或者操作任何的OC对象:
id p2 = [Personnew];
等价于:
Person *p = [Personnew];
5.构造方法
完整的创建一个可用的对象的步骤:
1)分配存储空间:
即创建一个类方法的空间 +alloc
Person *p = [Personalloc];
2)初始化:-init
Person *p2 = [pinit];
两步实现的功能就等同于:
Person *p3 = [[Personalloc]init];
这样我们创建出来的对象所有属性默认值为0。如果想设置默认值不为0,可以通过重写 –init方法来达到目的,例如要将Person新建的对象_age属性的初始化值设置为10,则在@implementation中使用以下代码:
- (id)init
{
// 1.首先调用super的init方法:初始化父类中声明的一些成员变量和其它属性
self = [super init]; // 当前对象self
// 2.如果对象初始化成功,才有必要进行接下来的初始化
if(self != nil)
{
_age = 10;
}
// 3.返回一个已经初始化完毕的对象
return self;
}
以上代码可以精简为:
- (id)init
{
if(self = [super init])
{
_age = 10;
}
return self;
}
自定义构造方法的规范:
1. 一定是对象方法,一定以“-”开头;
2. 返回值一般是id类型
3. 方法名一般以initWith开头。
代码演示:
- (id)initWithAge:(int)age
{
if(self = [super init])
{
_age = age;
}
return self;
}
6. 分类
在不改变原来类内容的基础上,可以为类增加一些方法。
但是分类只能增加方法,不能增加成员变量。分类方法实现中可以访问原来类中的成员变量。在含有分类的类中,查找方法优先从分类中查找,分类中没有的时候才会从原来类中找,如果分类含有与原来类中相同的方法的时候会覆盖掉原来类的方法。在含有多个分类中都含有同一个方法时,会保留最后一个编译的分类中的方法。
Xcode6以后创建分类的方法:
代码示例(要为NSString类添加一个能统计数字个数的功能):
NSString+Numcount.h代码:
#import <Foundation/Foundation.h>
// 注意格式:原类名 (扩充名)
@interface NSString (NumberCount)
/********声明代码**********/
@end
在NSString+NumCount.m中代码:
#import "NSString+NumCount.h"
@implementation NSString (NumberCount)
/********实现代码**********/
@end