OC中都有哪些变量呢?
OC中有许多变量类型,在这里简单的记录下这些变量的定义和区别。常用的变量有:成员变量、实例变量、全局变量、局部变量、静态变量、属性变量。
一、成员变量和实例变量
成员变量中包括实例变量(对象类型变量)和基础数据类型变量,实例变量是由类定义声明的对象。
-
声明位置:
成员变量被声明在.h头文件的@interface className : NSObject
和@end
之间的大括号之间或在.m文件的类扩展中声明。
@interface Test : NSObject
{
//声明成员变量,默认访问权限修饰词是protected
NSString *name; //实例变量
NSString *city; //实例变量
NSString *country; //实例变量
int age; // 基础数据类型变量
}
@end
- 作用域
- 成员变量声明在.m文件时:只有本文件内部可以访问;
- 成员变量声明在.文h件时: 其作用于由成员变量的访问权限修饰词控制;
- @public:公开的
实例变量可以在项目中的任何地方被访问- @ protected:受保护的
实例变量只可以在当前类或其子类的对象方法中被访问,默认的访问权限修饰符。- @private:私有的
实例变量只可以在当前类的对象方法中被访问- @package:整个包,框架级别
整个项目中都可以访问,作用域介于私有和公开之间,只要处于同一个框架中相当于@public,在框架外部相当于@private
代码:
#import "ViewController.h"
#import "Test.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Test *test = [[Test alloc] init];
//当Test的country成员变量访问权限未public时,此时可以通过->访问country
NSLog(@"%@",test->country);
}
@end
//Test类
#import <Foundation/Foundation.h>
@interface Test : NSObject
{
@public
NSString *name;
NSString *city;
NSString *country;
int age;
}
@end
修饰符 | 类型 | 继承 | 子类访问 | 外部访问 |
---|---|---|---|---|
@private | 私有 | 不可继承 | 不可以 | 不可以 |
@public | 共有 | 可继承 | 可以 | 可以 |
@protected | 保护 | 可继承 | 可以 | 不可以 |
注意:不建议使用test->country这种方式来访问使用@public修饰的成员变量,因为这样是不安全的。所以建议手动添加自定义成员变量的get/set方法;
代码:
//Test类
#import <Foundation/Foundation.h>
@interface Test : NSObject
{
@public
NSString *name;
NSString *city;
NSString *country;
int age;
}
-(NSString *)getName;
-(void)setName:(NSString *)name;
@end
//test.m中
-(NSString *)getName {
return name;
}
-(void)setName:(NSString *)newName {
name = newName;
}
- 特点
- 访问必须通过实例对象来访问,不能脱离类;
- 声明和初始化是分开的,声明实例变量的时候无法初始化赋值;
+成员变量存储在当前对象对应的堆的存储空间中,不会被自动释放,只能手动释放;
二、属性变量
在OC中用@property来声明一个属性,编译器会自动为实例变量生产setter和getter方法。声明属性时会默认创建格式为“_className”的成员变量。属性简化了我们为成员变量实现set/get方法的操作,属性专用于从类外部对变量进行调用和赋值。
-
声明位置:
可以声明在.h头文件的@interface className : NSObject和@end之间或在.m文件的类扩展的大括号外面声明。 - 作用域
- 声明在.m文件时:只有本文件内部可以访问;
- 声明在.文h件时: 在引用当前类的的文件中可以访问;
- @synthesize和@dynamic
- @synthesize
表示告诉编译器自动实现成员变量的getter/setter方法,并将存取方法作用于系统根据属性名创建的“_className”变量。
- @dynamic
表示告诉编译器不需要自动生产getter/setter方法,由开发者手动实现getter/setter。
- @property修饰符
- 原子性/非原子性:
- 属性默认是atomic原子性的,表示只有一个线程访问变量,原子性影响效率。
- 属性设置nonatomic可以使用多个线程访问变量,优点效率快,大部分情况下使用非原子性 nonatomic。
- 读写属性修饰符:
- readonly只读属性,只生成getter方法,不会生成setter方法。
- readwrite读写属性,生产getter和setter方法,属性默认readwrite。
- 设置setter/getter别名:
- getter = 设置getter新的别名;
- setter = 设置setter新的别名;
- 内存管理
- assign:
默认值,主要用于简单的基础数据类型,例如int、float
等,用于直接赋值,不做任何内存管理。- strong:
在ARC环境下使用,表示强引用指针,相当于retain
,其修饰的对象引用计数会增加1,该对象只要引用计数不为0则不会被销毁。- weak:
在ARC环境下使用,表示弱引用指针,weak
修饰的对象在释放后,指针地址会被置为nil。- copy:
对原有对象进行拷贝,复制每次都会在内存中拷贝一份对象,指针指向不同地址,一般用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary。- retain:
会自动帮我们生成getter/setter
方法内存管理的代码,在setter
方法中,对传入的对象进行引用计数加1的操作,一般用于对象的修饰。
三、全局变量
定义在函数外或大括号外声明定义的变量,全局变量存储在内存的全局(静态)存储区,程序启动时就会分配存储空间,直到程序结束才会被释放。可以跨文件访问
-
声明位置
在OC中可以声明在.h或.m文件的函数外部。 -
作用域
全局变量的作用域是整个程序源。
四、静态变量
可以声明在函数外,也可声明在函数或代码块内部。
- 当声明在函数外部时就是使用
static
关键字将全局变量变为静态全局变量,改变了全局变量的作用域:只限于声明静态全局变量的整个文件访问使用。- 当声明在函数或代码块内部时,被称为静态局部变量,其存储区域也是在全局(静态)存储区。静态局部变量的生命周期是整个程序源,但它的作用域只在代码块内。
注意:1、存储在静态存储区的变量,其内存会直到程序结束才会被销毁,即生命周期是整个程序;2、当静态全局变量声明在.h头文件时,其他类引用静态全局变量所在类头文件后可以访问。
五、局部变量
局部变量也称作自动变量,需要在函数内部声明,在内存中存储在栈区
stack
。并当函数结束后释放内存,局部变量也会被销毁。
网友评论