最近在使用Swift的过程中,感觉到苹果公司为了迎合Swift,在Objective-C中添加了许多关键字。这些关键字一般用来用来修饰属性,或者方法的参数以及方法的返回值等等。而在以前的Objective-C开发中我们可能并不会去关注这样的一些关键字。尽管iOS10就要出了,但出于更深入了解两种语言的目的,我总结了一些Objective-C的新关键字。

  新关键字的出现总是有其意义的,而iOS9的这些关键字可以很清晰的看出苹果公司推出的意义:

  1.迎合Swift

    因为Objective-C是一个弱类型的语言,程序在运行时才会去确认每个对象的类型与声明的类型是否一致。而Swift是强类型的语言,需要我们在编译时确定每一个对象的类型。这样两种语言在处理同一个方法或属性的时候可能会出现矛盾。为了迎合Swift,苹果公司添加了许多语言来兼容两种语言。

  2.提高我们开发人员的开发规范,减少程序员之间的交流

    我们以前可能没有规定全面一个属性的所有方面的需求,这样在遇到实际的需求的时候两个程序员对同一个接口的参数可能有歧义,不清楚是否可以为空等等。规定全面了这些问题后,我们在敏捷开发中就可以省去这部分不必要的交流,更多的时间与精力放在编程中。

  一.nullable

  这个关键字由两部分组成,与接下来的很多关键字是相同的。null:空的;able:可以。也就是说,nullable修饰的属性是可以为空的。

  nullable有三种不同的书写规范,分别放在不同的位置,但表达的意思是相同的。

 // 方式一:
@property (nonatomic, strong, nullable) NSString *nullableName; // 方式二:放在*号之后
@property (nonatomic, strong) NSString * _Nullable _NullableName; // 方式三:beta版本的关键字,手写的时候已经没有提示了
@property (nonatomic, strong) NSString * __nullable __nullableName;

  简单来说,1.不带下划线的全小写nullable,放在括号内;2.带一个下划线的首字母大写_Nullable,放在星号*后;3.带两个下划线的全小写__nullable,放在星号*后。

  之后的许多关键字都有这三种写法。不再一一赘述。

  我们在调用的时候,系统会从最基本的提示变更为带有_Nullable可以为空提示的字样:

  这样,我们是可以给这个属性设置为空的:

 [self setName:nil];

  既然一开始我们就提到了这些关键字是为了迎合Swift,那这个关键字体现在Swift中是什么呢?那就是 "?" 这个标识符了。这个标识符在Swift中代表这个常量/变量是可能为空的,对应到Objective-C中,自然就是nullable。

  

  二.nonnull

  non:非,不;null:空的。nonnull:非空的。也就是说,nonnull修饰的属性与上面nullable不同,是不能为空的。

  nonnull同样有三种不同的书写格式:

  方式一:

 @property (nonatomic, strong, nonnull) NSString *nonnullIcon;

  方式二:放在*号之后

 @property (nonatomic, strong) NSString * _Nonnull _NonnullIcon;

  方式三:beta版本的关键字,已经没有提示

 @property (nonatomic, strong) NSString * __nonnull __nonnullIcon;

  与上面类似,不再赘述。

  使用时,也与nullable有相似的效果:

  我们在给标识为nonnull的属性设置为空时,系统会提示我们出错:

  Warning:Null passed to a callee that requires a non-null argument. // callee:传话者,被召者,这里指代属性; argument:参数。

  警告:我们将一个空值传给了一个要求非空参数的属性。

  同样的,nonnull对应在Swift中,就是 "!" 标识符了,代表非空的。

  

  三.注意:iOS9.0新出的关键字只能修饰对象,不能修饰基本数据类型

  我们刚才试验的对象,都是字符串对象,NSString类型。那么我们可不可以用上述关键字修饰基本数据类型呢?我们可以试一下。

  提示报错。

  Alert:Nullability specifier 'nonnull' cannot be applied to non-pointer type 'int'. // specifier:分类符; applied:应用的,实用的

  警告:表示非空的标识符"nonnull"不能适用于非指针类型'int'。

  也就是说,新推出的关键字,只能修饰对象,不能修饰基本数据类型。

  四.方法中,关键字书写规范

  我们刚才都是在属性中使用关键字。而文章一开头就说明了,这些关键字除了用来修饰属性之外,还可以修饰方法的参数与返回值。那么这样是如何使用呢?

  使用方式有两种,并不像之前的三种了:

 - (nullable NSString *)test:(nullable NSString *)str;
- (NSString *_Nullable)test1;

  而在调用过程中是这样的:

  这样,我们一眼就能看明白这个参数或返回值是可以为空或非空的,就不会给他传空等等造成沟通的麻烦,也就体现了我之前提到的,减少不必要的交流的问题。

    

  五.有关nullable和nonnull的深入思考

  我们学习了nullable和nonnull之后,会发现我们几乎碰到所有系统类的属性与方法中都带着这两个之一的关键字。那么苹果官方是怎么写的呢?难道一个属性一个属性的添加这样的关键字吗?我们点进去UIButton,发现很多属性都带有nullable,而几乎看不到nonnull关键字。难道这些关键字都可以为空吗?

  其实并不是这样。在许多类中,我们都会在开头和结尾看到这样两个宏的出现:

 #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") // assume:确认
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")

  在NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END两个宏之间,定义的所有对象属性和方法默认为nonnull。

  我们可以尝试一下:

 NS_ASSUME_NONNULL_BEGIN

 @property (nonatomic, strong) NSString *name;

 NS_ASSUME_NONNULL_END

  这样,在调用这个属性的时候我们会发现: 

 [self setName:<#(NSString * _Nonnull)#>];

  这个属性是默认非空的。

  也就是说,我们也可以在我们的类中的开头和结尾使用这两个宏,然后我们只需要给可能为空的属性添加nullable就可以了。

  六.null_resettable

  null:空的; resettable:可重调; null_resettable:可以重新设置为空的。

  这个关键字表示,这个属性getter方法不能返回为空;setter可以为空。如何会出现这种情况呢?也就是说,我们必须要重写这个属性的getter方法或setter方法来处理传值为空的情况,否则就会出现警告。

  Warning:Synthesized setter 'setNull_resettableName:' for null_resettable property 'null_resettableName' does not handle nil.

  警告:同步setter方法'setNull_resettableName:' 给可以设置为空的属性'null_resettableName'时没有经过处理。

  这种典型的,就是我们在调ViewController的view时,系统将view的getter方法给重写了。大致是这样的:

 @synthesize view = _view;

 - (UIView *)view {

     if (!_view) {

         [self loadView];
[self viewDidLoad];
} return _view;
}

  同样的,我们也可以用同样的方式对null_resettable的属性进行处理:

 @synthesize null_resettableName = _null_resettableName;
// 重写get
- (NSString *)null_resettableName { if (!_null_resettableName) { _null_resettableName = @"";
} return _null_resettableName;
} - (void)setNull_resettableName:(NSString *)null_resettableName { if (!null_resettableName) { _null_resettableName = @"";
} _null_resettableName = null_resettableName;
}

  因为我同时重写了setter与getter方法,所以编译器需要找到属性null_resettableName的变量形式是什么。实际编程中,我们重写这两个方法中的任意一个就可以了。

  

  七.null_unspecified

  null:空的; unspecified:未特别指出的;未具体说明的; 也就是说null_unspecified是我们未具体指出是否为空,也就是默认状态。或者说,这个关键字写不写都行。

  与之类似的,它有三种书写方式:

 @property (nonatomic, strong, null_unspecified) NSString *null_unspecifiedName;
@property (nonatomic, strong) NSString *_Null_unspecified _Null_unspecifiedName;
@property (nonatomic, strong) NSString * __null_unspecified __null_unspecifiedName;

  调用时,是这样的:

 [self setNull_unspecifiedName:<#(NSString * _Null_unspecified)#>];
[self set_Null_unspecifiedName:<#(NSString * _Null_unspecified)#>];
[self set__nullableName:<#(NSString * _Nullable)#>];

  

  希望大家有所收获。

iOS的一些关键字的更多相关文章

  1. iOS中__block 关键字的底层实现原理

    在 <iOS面试题集锦(附答案)> 中有这样一道题目: 在block内如何修改block外部变量?(38题)答案如下: 默认情况下,在block中访问的外部变量是复制过去的,即:写操作不对 ...

  2. iOS 声明属性关键字的总结

    atomic: 原子操作(原子性是指事务的一个完整操作,操作成功就提交,反之就回滚. 原子操作就是指具有原子性的操作)在objective-c 属性设置里面 默认的就是atomic ,意思就是 set ...

  3. IOS开发之关键字synchronized

    static Config * instance = nil; +(Config *) Instance { @synchronized(self)  { if(nil == instance)  { ...

  4. iOS 声明属性关键字讲解

    atomic: 原子操作(原子性是指事务的一个完整操作,操作成功就提交,反之就回滚. 原子操作就是指具有原子性的操作)在objective-c 属性设置里面 默认的就是atomic ,意思就是 set ...

  5. 【iOS】copy 关键字

    以前没注意过 iOS 的 copy, nonatomic, assign, weak, strong 等关键字. 偏偏今天遇到了一个问题,恰恰是关键字的问题,如图: 之前用的是 assign, 没有用 ...

  6. iOS 新特性关键字

    1.用来修饰属性,或者方法的参数,方法的返回值 /** nullable:表示可以传空 */ //@property (nonatomic, strong, nullable) NSString *n ...

  7. iOS Regex匹配关键字并修改颜色

    引入第三方框架RegexKitLite /** * 根据传入的文字返回一个符合规则的富文本 * * @param title 匹配的文字 * * @return 创建的富文本 */ -(NSAttri ...

  8. ios开发static关键字的理解

    :static关键字修饰局部变量::当static关键字修饰局部变量时,该局部变量只会初始化一次,在系统中只有一份内存 :static关键字不可以改变局部变量的作用域,但是可延长局部变量的生命周期,该 ...

  9. IOS开发 static关键字的作用

    (1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值: (2)在模块内的 static 全局变量可以被模块内所 ...

随机推荐

  1. [Q]自定义保存位置及文件名

    以“DWG To PDF.pc3”打印为例: 说明:<DrawingDirectory> 当前图纸所在目录<DrawingFolderName> 当前图纸文件所在文件夹名称&l ...

  2. 关于mac地址的一点感想

    因为怕mac地址冲突导致环路影响,所以修改了本地设备的mac地址.地址修改为 77:77:77:00:22:11, 结果导致 wlan0 下发不下来. 查看配置选项/etc/config/wirele ...

  3. NSDateComponents

    NSDateComponents将时间表示成适合人类阅读和使用的方式, 首先要遵循某种历法 NSCalendar * cal = [NSCalendar currentCalendar]; 有三种用法 ...

  4. php笔记(四)PHP类和对象之对象继承

    建立一个Truck类,扩展Car类,并覆盖speedUp方法,使速度累加50 <?php class Car { public $speed = 0; //汽车的起始速度是0 public fu ...

  5. linux ll命令参数的详解

    用法:ls [选项]... [文件]... 列出 FILE 的信息(默认为当前目录). 如果不指定-cftuvSUX 或--sort 选项,则根据字母大小排序. 长选项必须使用的参数对于短选项时也是必 ...

  6. Springmvc+Myabtis+Ajax实现异步分页emp+dept(全部查询及模糊查询)

    1.在项目中创建如下目录 2.创建实体类Dept package com.entity; import java.io.Serializable; /** * 部门表 * @author Admini ...

  7. zTree 勾选checkbox

    zTree 勾选checkbox var setting = {    check: {        enable: true//        chkboxType : { "Y&quo ...

  8. scala中java并发编程

    Runnable/Callable 线程(Thread) Executors/ExecutorService Future 线程安全问题 示例:搜索引擎 解决方案 Runnable/Callable ...

  9. C#中ref和out的区别浅析

    这篇文章主要介绍了C#中ref和out的区别浅析,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢,需要的朋友可以参考下   在C#中通过使用方法来获取返回值时,通 ...

  10. 以Jar形式为Web项目提供资源文件

    以Jar形式为Web项目提供资源文件 http://www.webjars.org/ Web前端使用了越来越多的JS或CSS如jQuery, Backbone.js 和Twitter Bootstra ...