会报编译器警告的Xcode 6.3新特性:Nullability Annotations
最近在用Xcode 6.3写代码,一些涉及到对象的代码会报如下编译器警告:
1
|
Pointer is missing a nullability type specifier (__nonnull or __nullable) |
于是google了一下,发现这是Xcode 6.3的一个新特性,即nullability annotations。
Nullability Annotations
我们都知道在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!。而在Objective-C中则没有这一区分,view即可表示这个对象是optional,也可表示是non-optioanl。这样就会造成一个问题:在Swift与Objective-C混编时,Swift编译器并不知道一个Objective-C对象到底是optional还是non-optional,因此这种情况下编译器会隐式地将Objective-C的对象当成是non-optional。
为了解决这个问题,苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释:__nullable和__nonnull。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。
我们来看看以下的实例,
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@interface TestNullabilityClass () @property (nonatomic, copy) NSArray * items; - (id)itemWithName:(NSString * __nonnull)name; @end @implementation TestNullabilityClass ... - (void)testNullability { [self itemWithName:nil]; // 编译器警告:Null passed to a callee that requires a non-null argument } - (id)itemWithName:(NSString * __nonnull)name { return nil; } @end |
不过这只是一个警告,程序还是能编译通过并运行。
事实上,在任何可以使用const关键字的地方都可以使用__nullable和__nonnull,不过这两个关键字仅限于使用在指针类型上。而在方法的声明中,我们还可以使用不带下划线的nullable和nonnull,如下所示:
1
|
- (nullable id)itemWithName:(NSString * nonnull)name |
在属性声明中,也增加了两个相应的特性,因此上例中的items属性可以如下声明:
1
|
@property (nonatomic, copy, nonnull) NSArray * items; |
当然也可以用以下这种方式:
1
|
@property (nonatomic, copy) NSArray * __nonnull items; |
推荐使用nonnull这种方式,这样可以让属性声明看起来更清晰。
Nonnull区域设置(Audited Regions)
如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。在这两个宏之间的代码,所有简单指针对象都被假定为nonnull,因此我们只需要去指定那些nullable的指针。如下代码所示:
1
2
3
4
5
6
|
NS_ASSUME_NONNULL_BEGIN @interface TestNullabilityClass () @property (nonatomic, copy) NSArray * items; - (id)itemWithName:(nullable NSString *)name; @end NS_ASSUME_NONNULL_END |
在上面的代码中,items属性默认是nonnull的,itemWithName:方法的返回值也是nonnull,而参数是指定为nullable的。
不过,为了安全起见,苹果还制定了几条规则:
typedef定义的类型的nullability特性通常依赖于上下文,即使是在Audited Regions中,也不能假定它为nonnull。
复杂的指针类型(如id *)必须显示去指定是nonnull还是nullable。例如,指定一个指向nullable对象的nonnull指针,可以使用”__nullable id * __nonnull”。
我们经常使用的NSError **通常是被假定为一个指向nullable NSError对象的nullable指针。
兼容性
因为Nullability Annotations是Xcode 6.3新加入的,所以我们需要考虑之前的老代码。实际上,苹果已以帮我们处理好了这种兼容问题,我们可以安全地使用它们:
老代码仍然能正常工作, 即使对nonnull对象使用了nil也没有问题。
老代码在需要和swift混编时,在新的swift编译器下会给出一个警告。
nonnull不会影响性能。事实上,我们仍然可以在运行时去判断我们的对象是否为nil。
事实上,我们可以将nonnull/nullable与我们的断言和异常一起看待,其需要处理的问题都是同一个:违反约定是一个程序员的错误。特别是,返回值是我们可控的东西,如果返回值是nonnull的,则我们不应该返回nil,除非是为了向后兼容。
参考
会报编译器警告的Xcode 6.3新特性:Nullability Annotations
会报编译器警告的Xcode 6.3新特性:Nullability Annotations的更多相关文章
- Xcode And iOS9新特性
Xcode And iOS9 1. Xcode7 新特性 > 可直接在真机上运行自己的应用,只需要有苹果账号,无需购买苹果开发者账号. > 可设置在出现 EXC_BAD_ACCESS 错误 ...
- Xcode 8.0 新特性 & Swift 3.0 增加的变动
从 Xcode 8.0 开始,目前所有的插件都无法工作! NSLog 无法输出 -- 此bug等待正式版本... Xcode 提供了文档注释快捷键option + cmd + / 但是要把系统升级到1 ...
- iOS 9界面适配利器:详解Xcode 7的新特性UIStackView
升级Xcode7后老项目storyBoard出现问题了,一看时新特性搞的鬼.具体 详见:http://www.csdn.net/article/2015-08-04/2825372
- WWDC2016 Session笔记 - Xcode 8 Auto Layout新特性
目录 1.Incrementally Adopting Auto Layout 2.Design and Runtime Constraints 3.NSGridView 4.Layout Feedb ...
- WWDC2016 Session笔记 – Xcode 8 Auto Layout新特性
目录 1.Incrementally Adopting Auto Layout 2.Design and Runtime Constraints 3.NSGridView 4.Layout Feedb ...
- Xcode 8 的 Debug 新特性
Contents OverView Static Analyzer Localizability Instance Cleanup Nullablility Runtime Issue View De ...
- Xcode 8 的 Debug 新特性 —- WWDC 2016 Session 410 & 412 学习笔记
Contents OverView Static Analyzer Localizability Instance Cleanup Nullablility Runtime Issue View De ...
- Xcode 6 的新增特性
本文转载至 http://www.cocoachina.com/ios/20140823/9441.html (via:苹果开发者中心) Xcode 6 引入了设计和构建软件的崭新方式.Swift ...
- 编译器警告:CGContextSaveGState: invalid context 0x0
一.问题描述 下载图片,然后用Quartz2D绘制缩放的图片,运行无法显示图片并且编译器警告: Aug 18 21:41:50 02_计算UITableViewCell的行高[16777] < ...
随机推荐
- Office 365 - SharePoint 2013 Online 之母版页和页面布局
1.打开https://login.microsoftonline.com,登陆,点击SharePoint,如下图: 2.打开网站集,可以查看.添加.删除等管理操作: 3.打开一个站点,如下图: 4. ...
- thinkPHP学习笔记(2)
1.调试模式 设置调试模式部分代码如下: <?php define('APP_DEBUG',TRUE); // 开启调试模式 常量定义代码 require '/ThinkPHP框架所在目录/Th ...
- 关于Activity销毁,而绘制UI的子线程未销毁出现的问题
项目总结 ----------------------------------------------------------------------------------------------- ...
- IOS 简单动画 首尾式动画
首尾式动画 首尾式动画即通过实现控件由初始状态到结束状态的过程.(主要表现在控件的Frame 透明度 ) // // ViewController.m // CX 简单动画 // // Created ...
- java网络---查找Internet
连接到Internet的设备称为节点,计算机节点称为host. 为了区别每一台连接互联网的计算机,就有了Internet Protocol地址的概念. IPV4 & IPV6 我们以前默认的是 ...
- 如何使用GOOGLE高级搜索技巧
如何使用GOOGLE高级搜索技巧 一,GOOGLE简介 Google(www.google.com)是一个搜索引擎,由两个斯坦福大学博士生Larry Page与Sergey Brin于1998年9月发 ...
- Requirejs2.0笔记
API http://requirejs.org/ RequireJS 插件 http://requirejs.org/docs/api.html#plugins ①require.js脚本的异步加载 ...
- 【体系结构】Oracle参数介绍
[体系结构]Oracle参数介绍 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩ ...
- Java NIO入门(二):缓冲区内部细节
Java NIO 入门(二)缓冲区内部细节 概述 本文将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor). 状态变量是前一文中提到的"内部统计机制"的 ...
- powerdesigner设置表主键列为自动增长
powerdesigner 版本12.5 创建表就不说了.下面开始介绍设置自动增长列. 1 在表视图的列上创建.双击表视图,打开table properties ———>columens ,双击 ...