最近在使用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. MySQL数据库的数据备份和恢复(导入和导出)命令操作语法【转】

    不管是Oracle数据库还是SQL Server数据库,每个数据库都有自己的一套数据备份和恢复的方法,MySQL数据库也不例外.MySQL数据库备份和恢复用到了两个命令,分别是“mysqldump”和 ...

  2. Jquery实现双击表单元格可编辑

    <script type="text/javascript"> function doTableTdEditClick(param){ doTdEditable(par ...

  3. dotnet的移除-->安装 升级

    之所以要升级dotnet 是因为项目中报了如下错误 意思就是版本低了 为了升级 我先要把之前的移除掉(用脚本移除) #!/usr/bin/env bash # # Copyright (c) .NET ...

  4. C#变量修饰符

    访问修饰符 关键字包括:internal,public,protected和private,用于设置变量的访问级别.  public  变量可以做为它所属的类型的一个字段,可以在任何地方访问它.  i ...

  5. 路由页面缓存开启 以及 keep-alive 给你埋下的坑

    为什么要用keep-alive呢, 因为这个会缓存dom模板, 下次再回到这个页面, 就可以利用这个已经渲染好的dom结构了, 如果数据不一样, 也会启用 virtualDoM 进行diff更新, 这 ...

  6. python操作---RabbitMQ

    RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(MQ)是一种应用程序 ...

  7. HP Autonomy KeyView入门使用&Maven打包流程

    正文:使用自带的KeyView.jar可能报各种各样的错误,比如no manifest,找不到main方法等等,这里需要自己把需要用到的Filter类和KeyView.jar一起打包,并修改manif ...

  8. Tomcat下log4j设置文件路径和temp目录

    转自:http://www.cnblogs.com/dkblog/archive/2007/07/27/1980873.html 在Web应用中的如何设置日志文件的路径呢?最笨的方法是写绝对路径,但很 ...

  9. System.InvalidOperationException nested transactions are not supported

    如下bll方法,在执行时会报事务嵌套异常.bll方法里开启了分布式事务,dal方法里又启动了数据库事务.通过查看异常堆栈,发现异常是在执行BillsDal.Add(bill);方法里的var tran ...

  10. BOS物流管理系统-第八天

    BOS物流管理系统-第八天-权限系统设计-Shiro 回顾: 两大块业务:基础设置模块,业务派单模块. 两天:权限控制. 拦截器大的范围的.纯登录级别(认证级别)大颗粒的权限控制的一种技术. Shir ...