苹果在 Xcode 6.3 以后,为了解决 Swift 与 OC 混编时的问题,引入了一个 Objective-C 的新特性:nullability annotations。

这一新特性的核心是两个新的类型注释:__nullable 和 __nonnull。从字面上我们可以猜到,__nullable 表示对象可以是 NULL 或 nil,而 __nonnull 表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告(编译器警告:Null passed to a callee that requires a non-null argument)。

引入 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。

我们来看看以下的实例:

 @interface StudentClass ()

 @property (nonatomic, copy) NSArray *studentArray;

 - (id)studentWithName:(NSString *__nonnull)name;

 @end

 @implementation StudentClass

 - (void)testNullability {
[self studentWithName:nil];
// 编译器警告:Null passed to a callee that requires a non-null argument
} - (id)studentWithName:(NSString *__nonnull)name {
return nil;
} @end
不过这只是一个警告,程序还是能编译通过并运行。
事实上,在任何可以使用 const 关键字的地方都可以使用 __nullable 和 __nonnull,不过这两个关键字仅限于使用在指针类型上。
而在方法的声明中,我们还可以使用不带下划线的 nullable 和 nonnull,如下所示:
- (nullable id)studentWithName:(NSString *nonnull)name;

在属性声明中,也增加了两个相应的特性,因此上例中的 studentArray 属性可以如下声明:

@property (nonatomic, copy, nonnull) NSArray *studentArray;

当然也可以用以下这种方式:

@property (nonatomic, copy) NSArray *__nonnull studentArray;

推荐使用 nonnull 这种方式,这样可以让属性声明看起来更清晰。

不过,为了安全起见,苹果还制定了几条规则:

  1. typedef 定义的类型的 nullability 特性通常依赖于上下文,即使是在 Audited Regions 中,也不能指定它为 nonnull。

  2. 复杂的指针类型(如id *)必须显示去指定是 nonnull 还是 nullable。例如,指定一个指向 nullable 对象的 nonnull 指针,可以使用 "__nullable id *__nonnull"。

  3. 我们经常使用的 NSError ** 通常是被假定为一个指向 nullable NSError 对象的 nullable 指针。

因为 Nullability Annotations 是 Xcode 6.3 新加入的,所以我们需要考虑之前的老代码。实际上,苹果已以帮我们处理好了这种兼容问题,我们可以安全地使用它们:

  1. 老代码仍然能正常工作,即使对 nonnull 对象使用了 nil 也没有问题。

  2. 老代码在需要和 Swift 混编时,在新的 Swift 编译器下会给出一个警告。

  3. nonnull 不会影响性能,事实上,我们仍然可以在运行时去判断我们的对象是否为 nil。

事实上,我们可以将 nonnull/nullable 与我们的断点和异常一起看待,其需要处理的问题都是同一个:违反约定是一个程序员的错误;特别是,返回值是我们可控的东西,如果返回值是 nonnull 的,则我们不应该返回 nil,除非是为了向后兼容。

__nonnull 和 __nullable (Swift 和 Objective-C混编)的更多相关文章

  1. Swift _ OC _ 混编

    Swift _ OC _ 混编 在OC环境下使用Swift. GitHub源码

  2. 详解Swift和OC的混编

    前言: 我们在一些情况下,仅仅使用swift 是无法完成一个项目的,在swift项目中必要用到 OC 实现一些功能,比如,项目要使用一些第三方的框架,但这个第三方的框架却是用 OC 实现的,或者你的项 ...

  3. iOS开发--Swift 如何完成工程中Swift和OC的混编桥接(Cocoapods同样适用)

    由于SDK现在大部分都是OC版本, 所以假如你是一名主要以Swift语言进行开发的开发者, 就要面临如何让OC和Swift兼容在一个工程中, 如果你没有进行过这样的操作, 会感觉异常的茫然, 不用担心 ...

  4. swift和oc的混编

    一.Swift工程中加入oc代码 1.在将oc代码加入到Swift工程的时候Xcode会自动创建一个桥接文件“yourProgectName-Bridging-Header.h”,如果没有创建或者删除 ...

  5. 开发 Swift 和 Objective-C 混编的 Framework

    来源:黄文臣 blog.csdn.net/hello_hwc/article/details/58320433 前言 为什么要写这样一篇文章,因为昨天和一个朋友讨论到Swift和Objective C ...

  6. obeject-c 与 swift 混编

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } p.p2 ...

  7. swift实现与OC的混编

    swift与OC的混编 现在写swift,很多的类库还不是很全,很多的第三方还是只有OC版的,这个时候swift想用,通常都是采用的swift和OC混编的方式.这里给大家演示一下混编是如何做的. sw ...

  8. 详解 swift2.2 和 OC 的混编

    前言: 我们在一些情况下,仅仅使用swift 是无法完成一个项目的,在swift项目中必要用到 OC 实现一些功能,比如,项目要使用一些第三方的框架,但这个第三方的框架却是用 OC 实现的,或者你的项 ...

  9. iOS开发——技术精华Swift篇&Swift 2.0和Objective-C2.0混编之第三方框架的使用

    swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引 ...

随机推荐

  1. ios 对象的集合类(collection classes)

    当你着手为你的应用编写代码的时候,你会发现有许多可供使用的Objective-C的框架类,其中尤其重要的就是基础框架类,它为平台所有的应用提供基础服务.基础框架类中包括了表示字符串和数字等基本数据类型 ...

  2. kvo原理概述

    kvo概述 kvo,全称Key-Value Observing,它提供了一种方法,当对象某个属性发生改变时,允许监听该属性值变化的对象可以接受到通知,然后通过kvo的方法响应一些操作. kvo实现原理 ...

  3. Struts2 + Spring + Hibernate 通用 Service 和 DAO

    我在 Struts2 + Spring + Hibernate  项目开发中总结出了一个Service 和 DAO ,可以用于处理任何的pojo(bean).使用这两个Service 和 DAO 可以 ...

  4. 微软.NET各子技术领域的应用前景

    从2002年微软发布.NET 1.0,其间历经了8年的发展,再到.NET 4.0,其已经成为一个庞大而复杂的软件开发与运行平台,架构日益复杂,应用领域也在不断地扩展,包容了“一堆”的子技术领域. 在. ...

  5. 软件测试之WEB测试经典总结

    在Web工程过程中,基于Web系统的测试.确认和验收是一项重要而富有挑战性的工作.基于Web的系统测试与传统的软件测试不同,它不但需要检查和验证是否按照设计的要求运行,而且还要测试系统在不同用户的浏览 ...

  6. JNI-数据类型

    转载:http://blog.csdn.net/conowen/article/details/7523145 在Java中有两类数据类型:primitive types,如,int, float, ...

  7. 注入限制绕过<转>

    突然想我们是否可以用什么方法绕过SQL注入的限制呢?到网上考察了一下,提到的方法大多都是针对AND与“'”号和“=”号过滤的突破,虽然有点进步的地方,但还是有一些关键字没有绕过,由于我不常入侵网站所以 ...

  8. MVC4网站发布到windows server 2003服务器

    在windows server 2003上部署MVC4的网站,需要进行以下工作 用VS2013新建项目 在创建项目的时候选择的矿建为.NET Framework4,然后选择[ASP.NET MVC4 ...

  9. C#-获取datatable指定列的数据

    DataTable dt = new DataTable();            da.Fill(dt);                                    this.text ...

  10. Windows下记事本编辑的Shell脚本放到Linux下执行出错,格式问题(/bin/bash^M: bad interpreter: 没有那个文件或目录)

    错误: /bin/bash^M: bad interpreter: 没有那个文件或目录 解决方案: 运行脚本时出现了这样一个错误,打开之后并没有找到所谓的^M,查了之后才知道原来是文件格式的问题,也就 ...