1、const(常量---readonly)
作用:
- 用于修饰 右边 的基本变量或指针变量;
- 被修饰的变量只读,不能被修改(readonly);
定义的意义:
(1.) 常用使用方式:
- 常用单独使用形式有三种:(但是一般会和其他关键字联合使用)
const NSString * name = @"jack";
NSString const * sax = @"boy";
NSString * const age = @"24";
这样定义的均为全局常量:不管你定义在那个文件夹(单独定义现在只能存在于.m文件中,见:用法举例->PS),在外部的任意文件中都可以访问到。
- 和其他关键字结合使用的形式一般有两种:
extern const NSString * name; // 仅做声明使用,一般存在与.h文件中
static const NSString * name = @"jack"; // 使全局常量变为局部变量,具体使用后面会介绍🙃
(2.)const究竟做了什么?
在介绍const时着重强调了“右边”二字,这是有原因的O(∩_∩)O~
在使用时我们发现const 修饰时 位置是不一样的,不同位置分别代表了什么含义呢?
const NSString * name = @"jack";
// *name 不能修改 name 可以修改 ---> *name 是指向指针的指针~
NSString const * sax = @"boy";
// 与上面一样(这就是为什么强调“右边”二字了)
NSString * const age = @"24";
// *name 能修改 name 不可以修改 --->所以我们想定义一个不想被修改的常量应该这样
我们可以用指针变量来验证一下:
用法举例:
访问的方式一般有两种:
(1.)在.m文件中定义,在其他文件中获取其声明,然后使用;
(2.)另一种使用时需要先在.h中声明,然后.m中赋值,当要使用该常量时需要导入定义该常量的头文件,然后直接使用即可。
PS:现在不能直接在.h文件中定义常量了,会发生循环引用问题。具体见http://www.jianshu.com/p/94ca52399ade该篇文章的第十五小标题,所以现在常用方法是单独创建一个专门存放常量的文件,使用第二种方法定义常量,然后在pch文件中导入该文件的头文件。
2、static (静态的)
作用:修饰不同的变量作用不尽相同。
(1.)修饰全局变量:
static NSString * name_boy = @"Bob";
// 下面是与const结合使用的情况
static const NSString * name = @"jack";
static NSString const * sax = @"boy";
static NSString * const age = @"24";
这又分为两种:
---》在.h中修饰全局变量:
现在直接在.h文件中定义全局变量或者const修饰的全局变量运行时会直接报_x86的错误,但是可以使用static 修饰,即可在.h文件中定义,然后在其他文件中可以直接使用!
---》在.m中修饰全局变量:
改变全局变量的作用域,使全局变量的作用域仅限于当前文件内部(.m内部),即当前文件内部才能访问该全局变量。同时这样能够避免重复定义全局变量!常见的使用情况:单例中。
若将上图(2-1-定义)中static const NSString * name = @"jack";
放到.m文件中则在AppDelegate.m中则访问不到name
.
(2.)修饰局部变量:
---》改变局部变量的生命周期(只到程序结束,这个局部变量才会销毁)不会改变局部变量的作用域;
---》让局部变量只初始化一次,局部变量在程序中只有一份内存
下面有一组对比来说明修饰局部变量后的变化:
可以看到,经过static修饰后,在for循环内部workDays只被初始化了一次。
与const结合使用:
一般是在.m文件中定义经常使用的字符串常量,或者数值常量时使用。static将一个全局变量变成局部变量,然后const将一个局部变量变成局部常量
e.g : MBProgressHUD.m中
3、extern(外部的,外部变量)
作用:
- 用来声明全局变量;
- 只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量;
用法:
- 在.h中修饰声明全局变量,然后在.m中定义该全局变量,则在其他文件中可以直接使用该变量!
- 获取全局变量的值(具体用法参考本篇文章中const篇幅中 -> 用法举例 中的(1.);
与const结合使用:
即,在.h中声明一个const修饰的全局变量,让后再在.m中实现其定义。(这样逼格看起来要高一些,其实就是定义了一个全局变量~)
在这里还有一些关键字UIKIT_EXTERN、OBJC_EXTERN、FOUNDATION_EXTERN、FOUNDATION_EXPORT、FOUNDATION_IMPORT,这些均为经过处理的extern.
- UIKIT_EXTERN:将函数/变量修饰为兼容以C编译方式的、具有extern属性的属性。
- OBJC_EXTERN:与UIKIT_EXTERN差不多,但是比其更加宽泛一些。
- FOUNDATION_EXTERN:看其定义是与OBJC_EXTERN一毛一样的······
- FOUNDATION_EXPORT/FOUNDATION_IMPORT:用来兼容win32应用程序,同时也是为了兼容C++语言的~~(不明觉厉😜)
若是使用以上字段是不是看起来逼格又高了一点~~,不过通常使用最多的也就是 UIKIT_EXTERN了。
4、typedef(定义类型)
作用:定义类型的别名。
(1.)定义枚举:
typedef NS_ENUM(NSInteger, UITableViewStyle) {
UITableViewStylePlain,
UITableViewStyleGrouped
};
typedef NS_OPTIONS(NSUInteger, UISwipeGestureRecognizerDirection) {
UISwipeGestureRecognizerDirectionRight = 1 << 0,
UISwipeGestureRecognizerDirectionLeft = 1 << 1,
UISwipeGestureRecognizerDirectionUp = 1 << 2,
UISwipeGestureRecognizerDirectionDown = 1 << 3
};
//凡是需要以按位或操作来组合的枚举都应使用NS_OPTIONS定义。若是枚举不需要互相组合,则应使用NS_ENUM来定义
(2.)定义block:
typedef void (^JRNetWorkSuccessBlock)(id responseObject, MBProgressHUD * hud);
(3.)添加别名:
typedef NSString Str;
// 这样再定义string类型时,也可以直接使 Str
// e.g @property (copy, nonatomic) Str * name;
5、typeof(变量名,类型)
作用:静态获取参数类型。
最常见就是自定义block中防止循环引用:
__weak typeof(self)weakSelf = self;
self.channelHeaderView.addAction = ^{
[[UIApplication sharedApplication].keyWindow addSubview:weakSelf.channelView];
};
6、define(定义)
作用:主要是用于定义宏
关于宏定义可以看一下我的这篇文章 《iOS预编译指令详解》。对于经常使用的一些常量最好使用const而不是定义成宏。