iOS所有变量(static/extren/const等)

眼看就要过年了,这两天却着着实实被全局变量坑了一把,APP开发者和我们SDK使用了相同的全局变量导致嵌码冲突。还好只是公司内部APP嵌码发现的问题,没有交付给大客户。否则,恐怕要被客户和经理批的狗血临头,学艺不精也怨不了谁。今天就结合第三方以及自身的理解详细分析一下iOS的包含的所有变量,上图:


变量.png

下面我命就详细分析各个变量的使用:

一、static静态变量

静态变量优点:

1、节省内存。静态变量只存储一处,但供所有对象使用。
2、它的值是可以更新的。
3、可提高时间效率。只要某个对象对静态变量更新一次,所有的对象都能访问更新后的值。

静态变量static的使用

1、修饰局部变量
让局部变量只初始化一次,局部变量在程序中只有一份内存,但是并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,这个局部变量才会销毁)。

2、修饰全局变量
全局变量的作用域仅限于当前文件

3、static作用于函数:e.g.: static void func(void);
  使用static用于函数定义时,对函数的连接方式产生影响,使得函数只在本文件内部有效,对其他文件是不可见的。这样的函数又叫作静态函数。使用静态函数的好处是,不用担心与其他文件的同名函数产生干扰,另外也是对函数本身的一种保护机制。
  如果想要其他文件可以引用本地函数,则要在函数定义时使用关键字extern,表示该函数是外部函数,可供其他文件调用。另外在要引用别的文件中定义的外部函数的文件中,使用extern声明要用的外部函数即可。

  • 重点:也就是说,static定义的方法和或者变量最多也不会超出所在文件,也就是所在类。如果要其他类引用次静态方法,那么就必须要extern声明引用。
static int age = 20;//全局变量
static NSString *name = @"zhang";
- (void)staticTest{
    // static修饰局部变量,将全局变量变成局部变量,但是在其他地方全局变量还是不变的
    static int age = 0;
    age++;
    //所以此处输入的是局部变量的值,在其他部分调用全局age还是20.
    NSLog(@"局部变量的age:%d",age);
}
常见的使用场景:
1)最常见的就是Cell复用的CellIdentifier设置都是定义为静态的字符串。(就是为了节省内存和提高时间效率)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        return cell;
}
2)单例创建
+ (AccountManager *)sharedManager
{
    static AccountManager *sharedAccountManagerInstance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        sharedAccountManagerInstance = [[self alloc] init];
    });
    return sharedAccountManagerInstance;
}
extern修饰全局变量
  • extern作用域为整个源程序,在Reachability.h中,extern配合const设置了一个的全局且不可变的变量,如下:
#ifndef NS_ENUM
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#endif
//设置全局且不可变变量kReachabilityChangedNotification,在Reachability.m中赋值
extern NSString *const kReachabilityChangedNotification;

extern配合const设置要特别注意一点,那就是变量的命名一定要有特殊性,在多人开发过程中防止定义相同导致的冲突,如下图:


重复的标识.png

所以,使用全局变量要慎重,而且代码要规范,避免不必要的坑。

  • extern与const联合使用:
    static与const组合:在每个文件都需要定义一份静态全局变量。
    extern与const组合:只需要定义一份全局变量,多个文件共享。

  • extern作用:
    只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量
    extern工作原理:
    先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。

- (void)externAndConst{
    /*
     一般会先新建.h文件专门存放常量的引用,在iOS的网络判断Reachbility中就有。
     注意一定要在.h文件中定义,否则会报错。
     */
//    extern NSString *const kReachabilityChangedNotification;
//    extern const int num;
    
    
    //逼格更高的一种写法,模仿系统UIKIT_EXTERN来替代extern
//    UIKIT_EXTERN NSString *const kReachabilityChangedNotification;
//    UIKIT_EXTERN const int num;
    
    /*
     在.m file中进行赋值专门存放static const修饰的变量,需要用的时候导入头文件就可以了。
     定义整个程序都能访问的常量
     */
   
    const int num = 666;
    NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification";

}

在AFNetWorking中也有使用extern,这里作为一个扩展,截图如下:

定义全局变量.png

extern的使用.png

三、局部变量

此处的i就是局部变量,仅仅作用在这个for循环方法内部。

 for (int i = 0; i < array.count; i ++) {
        NewsTableViewController *pulicVc = [[NewsTableViewController alloc]init];
        pulicVc.title = array[i];
        [self addChildViewController:pulicVc];
    }

四、实例变量

下面为实例变量,作用域为整个类。

@property (nonatomic,copy) NSString *number;      //数量,被操作对象的某个序号指标,如:文章字数
@property (nonatomic,copy) NSString *objectName;  //对象短名称,如:文章标题
@property (nonatomic,copy) NSString *objectIDs;   //对象IDs  统计列表中多个文章的ID时传值

五、const变量值不可变

我们设置不可变参数noChange,然后两次赋值,如下图所示,我们在赋值一次之后,第二次想要改变noChange的值的时候报错:


代码效果1.png

代码效果2.png
1、使用static const修饰变量和宏定义的比较
  • 相同点:
    a:都不能再被修改
    b:一处修改,其他地方都改不了
  • 不同点:
    a:static const 修饰变量只有一份内存
    b:宏定义只是简单的替换,每次使用都需要创建一份内存。
2、结论:

使用static const修饰更加高效,在同一个文件内可以使用static const取代#define
static const声明一个静态的全局只读常量

3、使用场景:

在一个文件中经常使用的字符串常量,可以使用static与const组合,可用于替换#define

const和宏的区别:

const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。

  • 编译时刻:宏是预编译(编译之前处理),const是编译阶段。
  • 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
  • 宏的好处:宏能定义一些函数,方法。 const不能。
  • 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
/*
 二、const 使用
 */
- (void)constTest{
    /*
     1、没有const修饰的指针。指针p和*p都能够被修改。
     */
    // 定义一个指针变量
    int *p = NULL;
    
    // 定义2个int类型的变量
    int a = 10;
    int b = 30;
    
    // p指向a
    p = &a;
    *p = 20;
    
    // p指向b
    p = &b;
    *p = 40;
    
    NSLog(@"%d %d", a, b);
    
    /*
     2、const修饰的*m,只能被赋值一次,若再次被赋值,编译器会报错。
     const int *m = NULL;
     *m = 20;
     */
  
    
    /*
      3、const修饰的m,被const修饰的n只能存一次地址,以后再也不能存其它地址了,否则编译器报错
    const修饰的指针变量n
     int * const n = NULL;
     int c = 20;
     n = &c; // 编译器报错,不能修改指针变量n
     */
    
    
    /*
     4、const声明字符串的用法,只能赋值一次,再次赋值会出错。
     */
    NSString *const name = @"sam";
    
    
    
}

//三、static&Const联合使用
- (void)staticAndConst{
    
    /*
     1、static将一个全局变量变成局部变量
     2、const将一个局部变量变成局部常量
     */
    // 定义了一个局部常量,只能被赋值一次,无法再次改变。
    static const CGFloat ZMJRed = 0.4;
    static const CGFloat ZMJGreen = 0.6;
    static const CGFloat ZMJBlue = 0.7;
    
    NSLog(@"---------ZMJRed:%f------ZMJGreen:%f------ZMJBlue:%f",ZMJRed,ZMJGreen,ZMJBlue);
}

//四、static const 与#define 比较
- (void)staticConstAndDefine{
    /*
     1、使用static const修饰变量和宏定义的比较
     相同点:
     a:都不能再被修改
     b:一处修改,其他地方都改不了
     不同点:
     a:static const 修饰变量只有一份内存
     b:宏定义只是简单的替换,每次使用都需要创建一份内存。
     
     2、结论:
     使用static const修饰更加高效,在同一个文件内可以使用static const取代#define
     static const声明一个静态的全局只读常量
     3、使用场景:
     在一个文件中经常使用的字符串常量,可以使用static与const组合,可用于替换#define
     */
    
    /*
     const和宏的区别:
    const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量。
    
    编译时刻:宏是预编译(编译之前处理),const是编译阶段。
    编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
    宏的好处:宏能定义一些函数,方法。 const不能。
    宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
    */
    
    
    //1、static const 修饰变量只有一份内存
    static const CGFloat ZMJBlue = 0.4;
    //2、只是用0.4替换ZMJRed  define每次使用都会创建一份内存,所以效率不如static const
    #define ZMJRed @"zhangsanlisi"
   
    NSString *str = ZMJRed;
    NSString *str1 = ZMJRed;
    NSLog(@"---str:%p-------str1:%p",str,str1);
#warning 但是引用的define的时候并没有创建内存啊,莫名其妙
    
    // 3、开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。
    static  NSString * const key = @"name";
    
    // 4、如果 const修饰 *key1,表示*key1只读,key1还是能改变。
    
    static  NSString const *key1 = @"name";
    NSLog(@"修改前:%@",key);

    key1 = @"zhangsanfang";
    NSLog(@"相亲们,修改后没毛病:%@",key1);
    
//    2018-02-09 14:36:06.617239+0800 OCVariableDemo[4842:891035] --------static1:0x107083970-------static2:0x107083970
//    2018-02-09 14:36:06.617341+0800 OCVariableDemo[4842:891035] --------define:0x608000052000-------define:0x608000052000
}

六、volatile变量值随时可变

volatile参数可以随时改变,目前没有找到使用的地方,以后遇到的话会补充上来哒。

参考知识点:http://blog.csdn.net/hdfqq188816190/article/details/51435268,感谢作者“峥吖”的分享,本人在此基础上做了些补充并写了Demo供大家查阅,如有不足之处还望指出。
Demo链接:https://github.com/caiqingchong/BianLiang

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 基弗?Nonono,就爱“舞女控”印象大师埃德加·德加 文章作者:艺厘米 安塞姆·基弗 【成长于第三帝国废墟中的跨...
    艺厘米artcm阅读 344评论 0 0
  • 每次打开对话框,趁着有什么高兴的事想跟你分享下或者趁着节假日问候你下,也有时只是突然太想念,想跟你聊聊。 但每次盯...
    f220a6e26e90阅读 247评论 0 0
  • 成功的基础是态度,态度决定了状态,状态决定了效率,效率决定了成败! 核心就是没有不可能,只是自己给自己设限!凡事找...
    力拓阅读 748评论 0 1