@property @synzhesize 的使用细节

理解一:

1.作用一

@property是在头文件.h中声明一个变量的setter和getter方法。

@synthesize是在m文件中定义setter和getter方法的实现。

2.作用二

@property,在声明变量方法的时候可以附加定义该变量的属性。如retain,assign,readonly,nonautomic等等。


但是,有一个点需要解释一下,就是直接使用 变量名赋值 和使用 self.变量 赋值的区别。比如

.h
......

ObjctName*  nameVarPtr;


@property(nonautomic,retain) ObjctName*  nameVarPtr;


.m
......

self.nameVarPtr = [[ObjectName alloc] init];

int n = [self.nameVarPtr retainCount];                      // n = 2 

nameVarPtr = [[ObjectName alloc] init];

n = [nameVarPtr retainCount];                                  // n = 1


self.nameVarPtr = [[ObjectName alloc] init] 和 nameVarPtr = [[ObjectName alloc] init] 两种赋值方式区别何在呢?


self.nameVarPtr=xxx 这种赋值方式等价于调用 [self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。


nameVarPtr = xxx 的赋值方式,仅仅是对一个指针进行赋值。nameVarPtr仅仅是一个指针变量,记录了xxx的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。


综上,对成员变量进行赋值,为防内存泄露需要注意的点:

1.self调用setter方法的方式

ObjectName*  tmp= [[ObjectName alloc] init];

self.nameVarPtr =tmp;                 //retainCount=2

[tmp release];                               //retainCount=1


2.指针赋值方式,不会调用setter方法

nameVarPtr= [[ObjectName alloc] init]; // retainCount=1



@synthesize window=_window之类的写法的理解

在32位系统中,如果类的 @interface 部分没有进行 ivar 声明,但有 @property 声明,在类的 @implementation 部分有响应的 @synthesize,则会得到类似下面的编译错误
Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar
在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线"_"做前缀。
上面声明部分的 @synthesize window=_window; 意思是说,window 属性为 _window 实例变量合成访问器方法。
也就是说,window属性生成存取方法,这个存取方法就是_window变量的存取方法,它操作的就是_window这个变量.

下面是一个常见的例子

@interface MyClass:NSObject{  

MyObjecct *_myObject;

}

@property(nonamtic, retain) MyObjecct *myObject;

@end
@implementatin MyClass

@synthesize myObject=_myObject;

@end

这个类中声明了一个变量_myObject,又声明了一个属性叫myObject,

然后@synthesize生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject和getmyObject。

@synthesize myObject=_myObject的含义就是属性myObject的存取方法是操作_myObject这个变量的。这种用法在Apple的Sample Code中很常见,


note:.位操作符,在等号左边等于调用setter方法,在等号右边等于调用getter方法。


理解二

一、点语法

1)  点语法基本概念 :当我们使用面向对象的封装特性后,将成员变量私有化,采取使用setter方法和getter方法向外面提供成员变量访问方案。那么我们知道,OC的调用方法的方式是很独特的,采用的是  [对象名(类名)  方法名] 的方式 ,那么很多Java、C#程序员就不习惯了,在Java、C#这些主流的面向对象语言中,调用方法的方式都是采用   对象名(类名).方法名() , 如果成员变量采取public访问权限时,还可以直接   对象名.成员变量 = 值;    的形式。可能是出于让Java、C#程序员迅速习惯OC的语法,苹果公司让OC诞生了点语法。 

 2)点语法代码初体验

首先,我们声明一个Person类

Person.h 

//
//  Person.h
//  04-点语法
//


#import 

@interface Person : NSObject
{
  int _age;
  NSString *_name;
}

- (void)setAge:(int)age;
- (int)age;


- (void)setName:(NSString *)name;
- (NSString *)name;

@end

P erson.m

#import "Person.h"

@implementation Person

- (void)setAge:(int)age
{
  _age = age;
  
}

- (int)age
{
   
  return _age;
   
}

- (void)setName:(NSString *)name
{
  _name = name;
}

- (NSString *)name
{
  return _name;
}

@end

测试程序:

#import 
#import "Person.h"

int main(int argc, const char * argv[])
{
  Person *p = [Person new];
  
  // 点语法的本质还是方法调用
  p.age = 10; // [p setAge:10];
  
  int a = p.age; // [p age];
  
  
  p.name = @"Jack";
  
  NSString *s = p.name;
  
  NSLog(@"%@", s);
  
  return 0;
}

注意点:

1)点语法的本质是调用类的getter方法和setter方法,如果类中没有getter方法和setter方法就不能使用点语法。

点语法本质:

// 点语法的本质还是方法调用
    p.age = 10; // [p setAge:10];
    
    int a = p.age; // [p age];

2)下面的不恰当调用,会导致死循环

// 会引发死循环
    //self.age = age; // 相当于在调用 [self setAge:age];
}
// 会引发死循环
    //return self.age;//相当于 [self age];

二、成员变量作用域

@public : 在任何地方都能直接访问对象的成员变量

  

@private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)

@protected : 可以在当前类及其子类的对象方法中直接访问  (@interface中默认就是@protected)

  

@package : 只要处在同一个框架中,就能直接访问对象的成员变量

  
@public // 在任何地方都能直接访问对象的成员变量
  int _age;
  
  
  @private  // 只能在当前类的对象方法中直接访问
  int _height;
  
  @protected // 能在当前类和子类的对象方法中直接访问
  int _weight;
  int _money;

注意:

1)  @interface和@implementation中不能声明同名的成员变量

2)子类继承父类,子类拥有父类的@public和@protected修饰的成员变量 

3)如果在类中声明一个属性,没有指定访问权限,默认是@protected 

三、@property 和  @synthesize

这两个关键字的出现,就是为了剔除代码中的setter方法和getter方法

1)@property

// @property:可以自动生成某个成员变量的setter和getter声明
@property int age;

//相当于下面这两句:
- (void)setAge:(int)age;
- (int)age;

2)@synthesize

// @synthesize自动生成age的setter和getter实现,并且会访问_age这个成员变量
@synthesize age = _age;

@synthesize height = _height;

@synthesize weight = _weight, name = _name;

这样,我们就省去了写setter方法和getter方法的时间,当然写那个也是极其无聊也是毫无意义。

但是,即便是这样,还是很不爽,在xcode的老版本中,为了避免书写setter方法和getter方法,我们还必须要在@interface 和 @end之间写上 @property int _age; 在@implementation 和 @end 之间写上 @synthesize的代码,很幸运,你们生活在一个幸福的时代,自从xcode4.4之后,@property int _age; 这句代码就把@property和@synthesize的活儿都给干了。

它主要做了下面这几件事: 

1)生成_age成员变量的get和set方法的声明;

2)生成_age成员变量set和get方法的实现; 

3)生成一个_age的成员变量。 

当然,@property方法生成的getter方法和setter方法可能满足不了您的需求,您也可以自己手动添加getter方法和setter方法, 如果手动写了setter方法@property就不会生成setter方法,但还是会生成getter方法,getter同理,如果您将setter方法,getter方法都进行手动书写了,@property将不会为您生成相应的getter方法和setter方法。


你可能感兴趣的:(iOS开发之OC基础)