首页 > 代码库 > 【IOS】@interface和 @property 方式声明变量的区别

【IOS】@interface和 @property 方式声明变量的区别

在IOS编程中,很多人没有理解实例变量与属性的区别,我根据自己的经验,这这里与大家分享下这里面的区别,下面我写一个简单的例子:

.h

@interface MyController :UIViewController

{

  UILabel *_myLabel;//这里是实例变量声明

}

@property (nonatomic, retain) UILabel*myLabel;//这里是你的属性声明

@end

.m

@implementation MyController

@synthesize myLabel = _myLabel;

...

@end

相信大家都看到过这样的程序,但我们一般写的程序是下面这样子的:

.h

@interface MyController :UIViewController

{

  UILabel *myLabel;//这里是实例变量声明

}

@property (nonatomic, retain) UILabel*myLabel;//这里是你的属性声明

@end

.m

@implementation MyController

@synthesize myLabel;

...

@end

 

其实,实例变量跟属性在cocoa里面应该是分开的,而下面这种我们平时写的这种代码因为实力变量跟属性是同一个名字,所以就不用使用等号来把实例变量赋值给属性了,实例变量一般是用在一个类的内部,而我们平时用的时候会在其他的类里面创建另一个类的对象,比如我们想改变我们上面创建的这个类的myLabel的text属性,这时,我们使用的是什么呢?要讲清楚这个问题,使用我们最上面的那段代码是最好的,现在我们假设已经创建了MyController的一个对象,叫做myController,要改变myLabel的text应该如下:

myController.myLabel.text =@"这是改变了之后的内容";

看清楚,这里使用的是myLabel(属性),不是_myLabel(实例变量),在MyController这个类里面"self."的时候也只能属性,实例变量都是assign类型的,你需要直接alloc内存赋值给它,同样在最后dealloc里面的release的也是实例变量而非属性,属性其实就是在外部或者内部调用时候使用实例变量的一种方式(个人理解),而真正占用内存的却是实例变量。

用了一段oc;会发现有2种定义变量的方式

      1.在  @interface :NSObject{} 的括号中,当然NSObject 是指一个父类,可以是其他的。

      形式如下:

  @interface GCTurnBasedMatchHelper : NSObject {
   BOOL gameCenterAvailable;
   BOOL userAuthenticated;
   }

  2.另外一种是直接在 @interface : NSObject{}括号之后,用 @property 去定义一个变量。

  @property (assign, readonly) BOOL gameCenterAvailable;

  你会发现,有人会再@interface中定义了变量后,又在 @property中重复定义相同的变量,而且很常见。

     结果可能是这样:

 
  @interface GCTurnBasedMatchHelper : NSObject {
   BOOL gameCenterAvailable;
   BOOL userAuthenticated;
   }
  @property (assign, readonly) BOOL gameCenterAvailable;
 

  而且你可以单独在@interface中定义变量,而不用@property定义;也可以只用@property去定义,而不在@interface中定义,当然用了@property去定义,一般要在.m文件中用@synthsize去合成相应的setter,getter方法。否则会得到一个警告。当然@synthsize是可选的,但是是Apple推荐的,不用会有什么后果,我没试过,有兴趣的童鞋可以试一下。

     那这两种方式有什么区别呢?

    1. 只在@interface中定义变量的话,你所定义的变量只能在当前的类中访问,在其他类中是访问不了的;而用@property声明的变量可以在外部访问。

    2.用了@property去声明的变量,可以使用“self.变量名”的方式去读写变量。而用@interface的方式就不可以。

这里给出一个链接:http://stackoverflow.com/questions/9702258/difference-between-properties-and-variables-in-ios-header-file里面讲到:我英语菜,简单翻一下:

在括号中定义一个变量只是简单的声明了一个实例变量(实例变量应该指的成员变量)。  博主注:老外对variable 和instance variable是有不同理解的。所以下文中 用了一个模糊的词 ivar。

声明(和 @synthsize)一个属性会为成员变量生成 getter 和setter方法,根据括号内的标准,在oc中经常用setter和getter 做内存管理,这是很重要的。(例如: 当一个值被赋给这个变量,对象是通过setter函数去分配,修改计数器,并最后释放的)。更高一个层次来说,这种做法也促进了封装,减少了一些不必要的代码。

在@interface括号中定义一个变量并用@property 重复定义一次是很普遍的,实际上不是必要的。用@property和@synthszie就够了,因为在用@synthsize合成这个属性的读写方法时就会创建一个变量。

重点是下面红色字体!!!!!或者看千锋3G语法知识第二讲后半部分有讲。

目前苹果(在模板中)建议的方法是这样的:

先在头文件中定义一个属性

@property int gameCenter;

然后在实现文件中  synthsize和declare成这样:

@synthesize gameCenter = __ gameCenter;
 

最后一行synthsize  gameCenter 属性并说明了不管什么值被分配给这个属性,都会存储到_gameCenter这个变量中。 再次说明,这不是必要的,但是,这样写了之后,你能减少输入已经明确命名的变量名。

最后一句的意思you are reducing the locations where you have to type the name of the ivar while still explicitly naming it .不好翻。

据千锋的第2节语法课课程的讲解,这样写之后可以使得 @synthsize 时内部getter方法会展成

-(int)gameCenter {
    return _gameCenter;
  }

而直接写  @synthsize  gameCenter;

setter函数会在内部展开成

-(int)gameCenter {
  return gameCenter;
  }

  注意到:函数名和变量名是一样的。在斯坦福的课程中,白胡子教授也模糊的说道这样的同名有可能带来bug,具体什么bug他没说,我也没见过,所以还是养成这样写的习惯为好。其他语言的getter函数  一般会在变量前加 get;但oc没有,可能是为了与其他语言做区分,算是oc的特色,结果却带来这么个麻烦。

【IOS】@interface和 @property 方式声明变量的区别