Objective-C 实用关键字详解1「面试、工作」看我就 ???? 了 ^_^.

时间:2022-09-01 10:51:30

在写项目 或 阅读别人的代码(一些优秀的源码)中,总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思
的。

相信很多开发者跟我当初一样,只是基本的常用关键字定义属性会使用,但在关键字概念上及具体的用法「应用场景、优化选择」上却依然有些模糊。
本文为「简书-白开水ln」作者原创;你关注的人,决定了你看到的世界 ^_^.

Objective-C 实用关键字详解1「面试、工作」看我就 ???? 了 ^_^.

目录:

  1. 关键字 const/static/extern 的「释义和用法」
    1、const
    2、static
    3、extern
    4、static与const联合使用
    5、extern与const联合使用
    6、const与宏的区别?「面试题」
  2. 期待 & 后续

关键字 const/static/extern 的「释义和用法」

1、const
  • const 简介:之前常用的字符串常量。
  • const 作用:
  • const 仅仅用来修饰右边的变量(基本数据变量p,指针变量*p)
  • const 修饰的(全局)变量是只读的,不能修改。
  • const 基本使用:
- (void)viewDidLoad {
    [super viewDidLoad];
    // 定义变量
    int a = 1;
    // 允许修改值
    a = 20;

    // const两种用法
    // const:修饰基本变量p
    // 这两种写法是一样的,const只修饰右边的基本变量b
    const int b = 20; // b:只读变量
    int const b = 20; // b:只读变量
    // 不允许修改值,错误
    b = 1;

    // const:修饰指针变量*p,带*的变量,就是指针变量.
    // 定义一个指向int类型的指针变量,指向a的地址
    int *p = &a;
    int c = 10;
    // 允许修改p指向的地址,
    p = &c;
    // 允许修改p访问内存空间的值
    *p = 20;

//--------------------------- 面试题 ------------------------------//

    // const修饰指针变量访问的内存空间,修饰的是右边*p1,
    // 两种方式一样
    const int *p1; // *p1:只读  p1:变量
    int const *p1; // *p1:只读  p1:变量

    // const修饰指针变量p1
    int * const p1; // *p1:变量 p1:只读

    // 第一个const修饰*p1 第二个const修饰 p1
    // 两种方式一样
    const int * const p1; // *p1:只读 p1:只读
    int const * const p1;  // *p1:只读 p1:只读
}
注意: 判断p 和 *p是只读还是变量,关键是看const在谁前面。
  • const 开发中应用场景
@implementation ViewController
// 定义只读全局常量 => 代替宏
NSString * const str  = @"123";

// 当一个方法的参数,只读.
- (void)test:(NSString * const)name
{
}

// 指针只读,不能通过指针修改值
- (void)test1:(int const *)a
{
}

// 基本数据类型只读
- (void)test2:(int const)a
{
}
@end
2、static
  • static 简介:可释义为“静态”的意思。
  • static 作用:
  • 修饰局部变量:
    • static修饰局部变量,延长生命周期,跟整个应用程序有关。
    • static修饰局部变量,只会分配一次内存。
    • static修饰局部变量什么分配内存?【程序一运行就会给static修饰变量分配内存】。
  • 修饰全局变量:
    • static修饰全局变量,会作修改用域(防止重复声明全局变量),只能在当前文件下使用。即当前文件内部才能访问该全局变量。
  • static 基本使用:
  • 保证局部变量永远只初始化一次,在程序的运行过程中永远只有一份内存, 生命周期类似全局变量了,但是作用域不变。这句话怎么理解呢?还是以代码例子来讲解吧。
// 被`static`修饰局部变量
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //声明一个局部变量i
    int i = 0; // 方式一
    static  int i = 0; // 方式二
    i ++;
    NSLog(@"i=%d",i);
}

打印输出:
方法一
2016-10-26 14:58:48.290 test[2760:170260] i=1
2016-10-26 14:58:49.044 test[2760:170260] i=1
2016-10-26 14:58:49.200 test[2760:170260] i=1
方式二
2016-10-26 15:07:34.276 test[2817:175155] i=1
2016-10-26 15:07:35.347 test[2817:175155] i=2
2016-10-26 15:07:35.761 test[2817:175155] i=3

注解
方式一:因为每次点击进入这个方法就会重新初始化一个全新的变量i = 0,加加了一次后值变为1,然后打印出结果为1,
出了这个方法后局部变量i就被释放回收。
方式二:它不是每次进去都被初始化赋值为0了么,怎么能累加呢。
这就是关键字static修饰的局部变量的作用,让局部变量永远只初始化一次,一份内存,生命周期已经跟全局变量类似了,只是作用域不变。

iOS 中在一个文件声明的全局变量,工程的其他文件也是能访问的,但是我又不想让其他文件访问,这时就可以用static修饰它了,比较典型的是使用GCD一次性函数创建的单例,全局变量基本上都会用static修饰。

// 被`static`修饰全局变量
@implementation LoginTool

// static修饰全局变量,让外界文件无法访问
static LoginTool *_sharedManager = nil;

+ (LoginTool *)sharedManager {
     static dispatch_once_t oncePredicate;
     dispatch_once(&oncePredicate, ^{
        _sharedManager = [[self alloc] init];
    });
    return _sharedManager;
}
3、extern
  • extern 简介:可释义为“外部”的意思。
  • extern 作用:只是用来声明外部全局变量,注意 extern 只能声明,不能用于定义。
  • extern 工作原理:先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
  • extern 基本使用
在 ViewController.m 文件中 定义个全局的常量
int i = 15;

在 AppDelegate.m 文件中声明
extern int i;

NSLog(@"%d",i); // 打印输出 15 
4、static与const联合使用
  • static与const作用:声明一个只读的静态变量
  • 需求:1、变量为只读,防止修改 2、只在当前文件下使用(非全局),可以使用static与const组合。
// iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.

// 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。static修饰后表示只能本文件访问。
static  NSString * const key = @"name";

// 如果 const修饰 *key1,表示*key1只读,key1还是能改变。
static  NSString const *key1 = @"name";
5、extern与const联合使用
  • 开发中使用场景:在 多个文件中 经常使用的同一个字符串常量,可以使用externconst组合。
  • 原因:
  • 使用externconst组合:在每个文件都需要定义一份静态全局变量(报重复定义错误)。
  • 使用externconst组合:只需要定义一份全局变量,多个文件共享。
  • 全局常量正规写法:全局变量不能定义在自己类中,开发中便于管理所有的全局变量,通常搞一个GlobeConst文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找。

在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,下面来看看高逼格的一种做法:

//  GlobeConst.m
#import "GlobeConst.h"

// 定义整个项目中全局变量
//--------------------------- 首页 ------------------------------//
//
NSString * const home_name = @"name";

//--------------------------- 发现 ------------------------------//
//
NSString * const discover_name = @"name";

//--------------------------- 圈子 ------------------------------//
//
NSString * const circle_name = @"name";

//--------------------------- 我的 ------------------------------//
//

//  GlobeConst.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

// 在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,下面来看看【高逼格】的一种做法:
#ifdef __cplusplus
#define LNKIT_EXTERN        extern "C" __attribute__((visibility ("default")))
#else
#define LNKIT_EXTERN            extern __attribute__((visibility ("default")))
#endif

// 声明整个项目中全局变量(把声明放到.h中)
//--------------------------- 首页 ------------------------------//
//
extern NSString * const home_name;

//--------------------------- 发现 ------------------------------//
// 系统
UIKIT_EXTERN NSString * const discover_name;

//--------------------------- 圈子 ------------------------------//
// 高逼格
LNKIT_EXTERN NSString * const circle_name;

//--------------------------- 我的 ------------------------------//
//

总结:这样,只要导入头文件,就可以全局的使用定义的变量或常量。

6、const与宏的区别?「面试题」

从四点回答:

  • 编译时刻:宏是预编译(编译之前处理);const 是编译阶段。

  • 编译检查:宏不做检查,不会报编译错误,只是替换;const 会编译检查,会报编译错误。

  • 宏的好处:宏能定义一些函数 或 方法。 const 不能。

  • 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。


  • 注意:很多Blog都说大量使用宏,会消耗大量内存,我这验证并不会生成很多内存,宏定义的是常量,常量都放在常量区,只会生成一份内存。

  • 提示:苹果不推荐我们抽成宏,推荐我们使用const常量,Swift已干掉了。

  • 代码示例:

// 常见的常量:抽成宏
#define LNAccount @"account"
#define LNUserDefault [NSUserDefaults standardUserDefaults]

// 字符串常量
static NSString * const account = @"account";
- (void)viewDidLoad {
    [super viewDidLoad];
    // 偏好设置存储
    // 使用宏
    [LNUserDefault setValue:@"123" forKey:LNAccount];
    // 使用const常量
    [[NSUserDefaults standardUserDefaults] setValue:@"123" forKey:account];
}

未完----------。待续
未完----------。待续
未完----------。待续

期待


  • 如果在阅读过程中遇到 error,希望你能 Issues 我,谢谢。

  • 如果你想为【本文相关】分享点什么,也希望你能 Issues 我,我非常想为这篇文章增加更多实用的内容,谢谢。

  • 「博客原文」对本文我会【不定时、持续更新、一些 学习心得与文章、实用才是硬道理】^_^.

About me


【我也是对所花费时间的一个总结】

我只是个【有思想的伐码猿

随机推荐

  1. asp&period;net &lt&semi;asp&colon;Content&gt&semi;控件

    <asp:Content ID="Content2" ContentPlaceHolderID="CPH_MainContent" runat=&quot ...

  2. 攻城狮在路上(叁)Linux(二十)--- Linux磁盘格式化

    磁盘完成分区之后,进行格式化,生成文件系统. 命令格式: mkfs [-t 文件系统格式] 设备文件名  <== 使用 mkfs [Tab][Tab] 可以查看linux支持的文件系统格式 示例 ...

  3. 蒟蒻修养之cf橙名计划2

    29 由于第一篇没写题意导致大部分神题题解已经完全不知道在说啥了...所以还是重开一篇保平安... [303A]题意:求三个长度为$n(n<=10^5)$的排列$a,b,c$使得$a_i+b_i ...

  4. vs2008 编译时候 自动关闭 问题解决方法

    最近又出现如此让人崩溃的问题.      vs2008在编译程序时候老是莫名其妙的自动退出.卸载重装以后问题仍然存在.      害我一度以为是vs2008的BUG,看网上说的更新BUG.      ...

  5. Xamarin for android&colon;为button设置click事件的几种方法

    原文:Xamarin for android:为button设置click事件的几种方法 在Xamarin中一个最基础的事情,就是为一个button指定click事件处理方法,可是即使是这么一件事也有 ...

  6. 【MySQL】20个经典面试题,全部答对月薪10k&plus;

    Part2:经典题目 1.MySQL的复制原理以及流程 基本原理流程,3个线程以及之间的关联: 2.MySQL中myisam与innodb的区别,至少5点 (1).问5点不同: (2).innodb引 ...

  7. 网络IP地址

    IP地址分类 A类网络的IP地址范围为1.0.0.1-127.255.255.254: B类网络的IP地址范围为:128.1.0.1-191.255.255.254: C类网络的IP地址范围为:192 ...

  8. angular 1&period;x 控制器之间互相传递参数

    我们要向前方看齐,基于js引用类型的对象就不记了,所以使用基于事件的方式: angular 中 $on,$emit,$boardcast来实现父控制器和子控制器互相通讯, 其中$on表示事件监听, $ ...

  9. Jquery为动态添加的未来元素绑定事件

    语法: $(selector).on(event,childSelector,data,function) event:必需.规定要从被选元素移除的一个或多个事件或命名空间.由空格分隔多个事件值,也可 ...

  10. 背包----Proud merchants

    一件物品p,q,v 分别表示物品的价格,钱少于q时就不能买,和物品的价值 n表示物品数量,m表示初始有的钱 问最多能买多少东西 01背包 注意点是,因为有一个q作为限制条件,所以n件物品不是随意选的了 ...