【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 [email protected]"这是改变了之后的内容";

看清楚,这里使用的是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的特色,结果却带来这么个麻烦。

时间: 2024-11-09 13:52:26

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

【转】 IOS,objective_C中用@interface和 @property 方式声明变量的区别

原文: http://blog.csdn.net/ganlijianstyle/article/details/7924446 1.在  @interface :NSObject{} 的括号中,当然NSObject 是指一个父类,可以是其他的. 形式如下: @interface GCTurnBasedMatchHelper : NSObject {     BOOL gameCenterAvailable;     BOOL userAuthenticated; } 2.另外一种是直接在 @in

OC中用@interface和 @property 方式声明变量的区别

用了@property去定义,一般要在.m文件中用@synthsize去合成相应的setter,getter方法.否则会得到一个警告.当然@synthsize是可选的,但是是Apple推荐的,不用会有什么后果 两种方式有什么区别: 1. 只在@interface中定义变量的话,你所定义的变量只能在当前的类中访问,在其他类中是访问不了的:而用@property声明的变量可以在外部访问. 2.用了@property去声明的变量,可以使用“self.变量名”的方式去读写变量.而用@interface的

PHP 闭包获取外部变量和global关键字声明变量的区别

最近在学习workerman的时候比较频繁的接触到回调函数,使用中经常会因为worker的使用方式不同,会用这两种不同的方式去调用外部的worker变量,这里就整理一下PHP闭包获取外部变量和global关键字声明变量的区别. 闭包 闭包是一个常见的概念,我们通常可以将其与回调函数配合使用,可以使代码更加简洁易读. 闭包可以通过拷贝的方式让函数使用父作用域中的变量.如: $global = 'hello'; $bbb = function()use($global){ echo $global.

【iOS开发】@property跟成员变量区别

@property在xcode 4.5之前只是单纯的告诉编译器,“我在后面实现了对那个变量的setter和getter方法,你放心吧”,但是如果你不写synthesize配合的话就会出错.synthesize才是代替setter和getter的关键部分. @synthesize在xcode4.5之前是配合@property使用,帮助你隐式了实现了一个setter和getter.如果你没有在interface里声明变量,它会帮你隐式的创建一个已下划线开头的同名变量,比如@synthesize my

iOS中copy和strong修饰变量的区别

大部分的时候NSString的属性都是copy,那copy与strong的情况下到底有什么区别呢? 比如:@property (retain,nonatomic) NSString *rStr;@property (copy, nonatomic)   NSString *cStr; - (void)test:{    NSMutableString *mStr = [NSMutableStringstringWithFormat:@"abc"];    self.rStr   = m

ES6的let和var声明变量的区别

关于let的描述 let允许你声明一个作用域被限制在块级中的变量.语句或者表达式.与var关键字不同的是,它声明的变量只能是全局或者整个函数块的. 作用域规则 let声明的变量只在其声明的块或子块中可用,这一点,与var相似.二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数,是全域的 . function varTest() { var x = 1; if (true) { var x = 2; // 同样的变量! console.log(x); // 2 } console.lo

使用var和不使用声明变量的区别

相信你对全局变量一定不陌生,在函数作用域里用a=1这种形式定义的变量会是一个全局变量,在全局作用域里,用下面3种形式都可以创建对全局可见的命名: <script> var a = 1; b = 2; window.c = 3; </script> 对于b=2这种方式, 它其实和c是一样的,在执行这个赋值语句的时候,会沿着作用域链寻找名字叫做b的变量,一直找到作用域链的顶端还没有找到,于是给window添加一个属性b然后赋值. var与不var有两个区别: 1 var的全局变量不能被

成员变量的声明@interface 和@property

刚开始接触OC再看别人写的代码的时候,常常困惑于人家在声明属性时的写法,总结出来有三中方式,不知道哪一种比较规范化,现在我把三种方式贴出来,然后再一一探讨每个方式声明属性的区别. 方式一:直接在@interface中的大括号中声明. @interface MyTest : NSObject{ NSString *mystr; } 方式二:在@interface中声明,然后再在@property中声明. @interface MyTest : NSObject{ NSString *_mystr;

IOS OC声明变量在@interface括号中与使用@property的区别

方式一:直接在@interface中的大括号中声明. @interface MyTest : NSObject{ NSString *mystr; } 方式二:在@interface中声明,然后再在@property中声明. @interface MyTest : NSObject{ NSString *_mystr; } @property (strong, nonatomic) NSString *mystr; 随后在.m文件中加入 @synthesize mystr = _myStr; 方