众所周知,变量是用来存储数据的
围绕着变量,有很多知识点,总结归纳一下
变量大致分为两大类型:
int/float/double/bool/enum/struct
NSInteger:typedef long NSInteger;
CGFloat: typedef CGFLOAT_TYPE CGFloat;
而CGFLOAT_TYPE的定义是:
#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
#else
# define CGFLOAT_TYPE float
#endif
也就是,CGFloat就是float或double,依然是基本数据类型
bool:其实就是C语言中的bool
BOOL: typedef bool BOOL;
也就是BOOL和bool没有任何区别
apple官方文档关于BOOL的定义
Boolean:typedef unsigned char Boolean;
(进入Xcode,可以看到)
存储的指针类型的变量类型,也就是存储的是地址的变量类型
根据变量写在的位置不同,有不同的作用区域
全局变量:在全局写的变量,整个文件都可以访问该变量
局部变量:在函数内部的变量,只有该函数内部才能访问,出了作用域不可访问
以上,默认都是auto修饰
静态变量:使用static修饰的全局变量或局部变量
静态局部变量:
静态全局变量:只有当前类可以访问该变量
//测试static
- (void)testStatic
{
int c = 1;
static int d = 1;
for(int i = 0; i < 3; i++)
{
int a = 1;
printf("int a变量为 %d \n",a);
a++;
static int b = 1;//因为static变量只初始化一次,所以第二次for循环及以后都不执行这一句代码
printf("static int b变量为 %d\n",b);
b++;
printf("int c变量为 %d \n",c);
c++;
printf("static int d变量为 %d \n",d);
d++;
}
}
打印结果:
int a变量为 1
static int b变量为 1
int c变量为 1
static int d变量为 1
int a变量为 1
static int b变量为 2
int c变量为 2
static int d变量为 2
int a变量为 1
static int b变量为 3
int c变量为 3
static int d变量为 3
auto: 表明变量具有自动存储类型
auto说明符只能用在具有代码块作用域的变量的声明中, 但是由于这类变量本身就具有自动存储类型(存储于运行时堆栈中), 所以auto通常只是起显式说明的作用.
register: 表明变量具有硬件寄存器存储类型
register也只能用在具有代码块作用域的变量的声明中, 表示程序员希望将该变量放在CPU的寄存器中, 从而可以比普通变量更快的访问和操作该变量. 但是无法获得寄存器存储类型的变量的地址, 并且具体是否会将register声明的变量存放于寄存器中由编译器决定
register声明的变量常称为寄存器变量
static: 表明变量具有静态存储类型或则标识符具有内部链接属性
extern: 表明标识符具有外部链接属性或者该变量在别处定义
static修饰的函数是一个内部函数,只能在本文件中调用,其他文件不能调用
变量根据访问访问,可以分为:public、protected、private、package
声明为 @public 的实例变量是访问控制中开放范围最广的,其允许外界可以直接访问(当然,前提是引入包含该声明的头文件)。
声明为 @protected 的实例变量只能在本类、本类的分类以及子类中使用。注意,当不使用任何访问控制修饰符时,类中实例变量默认即为 @protected(注意:类扩展中是个例外,详见「类扩展」一节)
声明为 @private 的实例变量是访问控制中开放范围最小的,只能被本类和本类的分类访问到,子类中也无法访问。在类声明中的属性(@property),系统会自动为我们创建一个 _ 开头的实例变量,这个实例变量的可见程度默认也是 @private。
同一个“体系内(框架)"可以访问,介于@private和@public之间
属性,property,是指的右@property建立的
例如:@property (copy, nonatomic) NSString *postId;
@property负责三个事情:
成员变量指的是
@interface
{
int age;
NSObject *obj1;
}
@end
大括号中间的内容
实例变量ivar(instance variables
),指的是{}中,是对象的一类,也就是有指针的,非基本数据类型。例如NSObject *obj1;
也就是说,成员变量 = 实例变量 + 基本数据类型变量
需要注意⚠️的是:如果既有成员变量,又有属性,则先写成员变量,再写属性
参考:OC中属性和成员变量(一)概念篇
也有资料说,成员变量 = 实例变量
属性property
实例变量ivar
成员变量的英文单词是?
synthesize: 合成
Xcode4时,@property只能在.h中生成getter、setter方法的声明, 需要在.m中手动加上@synthesize,才会有setter\getter的实现,以及对应的变量_property;
Xcode4之前 :
property = setter方法声明 + getter方法声明
synthesize = ivar + setter实现 + getter实现
在之前的OC中,写一个@property,还需要对应写一个@synthesize
@synthesize age = _age;
其作用是,将你写的age属性,和_age成员变量联系起来(@synthesize 合成访问器方法)
既是生成成员变量+方法实现,也是将成员变量和属性关联起来
现在,Xcode不需要写@synthesize age = _age;
,在写@property的时候,会自动给加上
从Xcode5开始, 编译器有了自动合成机制(Auto property synthesis),只写@property就可以自动生成_property成员变量和getter、setter方法的声明和实现, 不需要写synthesize了。
Xcode5之后, 其实property和synthesize的职责没变,只是编译器会默认添加synthesize, 真实的情况还是 :
property = setter方法声明 + getter方法声明
默认添加的synthesize = ivar + setter实现 + getter实现
---->看起来变成了 property = ivar + setter(声明+实现) + getter(声明+实现)
自动合成机制(Auto property synthesis) :如果我们既没有写synthesize也没有写dynamic,那编译器默认会为我们添加:@synthesize property = _property;
如果不存在_property,则会创建一个_property成员变量
如果存在,则不会添加成员变量
因此在类内部我们可以使用 _property 来进行赋值、取值操作。
@synthesize到底对属性干了什么, 使用场景总结
但,自动合成机制有时候会失效
现在,synthesize的作用是:
@dynamic告诉编译器: 属性的setter,getter方法由用户自己实现, 不自动生成
使用@dynamic age;
就不会自动生成age的setter/getter方法的实现,也不会自动生成成员变量(ivar)。
需要注意的是,age的setter/getter方法的声明是不受影响的。