Objective-C关键字__Nullable和__Nonnull
2015-12-10 15:53
671 查看
Xcode 6.3中有一项新特性,`nullability`标记,这为 OC 提供了类似 Swift 中的 Optional 的类型
为了让更多开发者从 OC 向 Swift 过渡,OC 和 Swift 混编已经变得尤为重要,就像是OC通向Swift的一座桥梁,
通过引入泛型使得 OC 和 Swift 之间更加安全清楚的理解和共享包含特定元素的集合
大概意思就是,我们又添加了两种类型,
事实上你可以在任何可以使用C语言关键字
当然
。即在方法申明的时候可以使用
在属性中,同样可以使用
为了更加高效的工作和代码的简洁,我们需要用到一种苹果称之为
什么是
为了方便采用新的方式,你可以在
任何简单指针类型都将被标注为
安全起见,这种方式会有一些异常
1.
2.很多复杂的指针,譬如
3.特定类型
现有的编译代码会在你的框架上继续跑,即
当你使用新的
这个功能最早被发布在
在
回到
现在我们已经
在没有添加标注前的
添加之后是这样的
这样一来,
为了让更多开发者从 OC 向 Swift 过渡,OC 和 Swift 混编已经变得尤为重要,就像是OC通向Swift的一座桥梁,
通过引入泛型使得 OC 和 Swift 之间更加安全清楚的理解和共享包含特定元素的集合
The Core: _Nullable and _Nonnull
关于 _Nullable 和 _Nonnull ,官方文档有这么一句话At the core of this feature we have two new type annotations: _Nullable and _Nonnull. As you might expect, a _Nullable pointer may have a NULL or nil value, while a _Nonnull one should not. The compiler will tell you if you try to break the rules.
大概意思就是,我们又添加了两种类型,
_Nullable可以为
NULL或者
nil,反之
_Nonnull绝对不能为空,否则编译器就会出现警告
@interface AAPLList : NSObject <NSCoding, NSCopying> // ... - (AAPLListItem * _Nullable)itemWithName:(NSString * _Nonnull)name; @property (copy, readonly) NSArray * _Nonnull allItems; // ... @end // -------------- [self.list itemWithName:nil]; // warning!
事实上你可以在任何可以使用C语言关键字
const的地方使用
_Nullable和
_Nonnull
当然
_Nullable和
_Nonnull一般用于指针类型,在一般情况下,有一个更好的方法去实现这种标记的功能
。即在方法申明的时候可以使用
non-underscored形式,
nullable和
nonnull,直接写在类型前面(类型必须是一个对象或者block指针)。
- (nullable AAPLListItem *)itemWithName:(nonnull NSString *)name; - (NSInteger)indexOfItem:(nonnull AAPLListItem *)item;
在属性中,同样可以使用
non-underscored形式将这样的关键字放到属性列表中
@property (copy, nullable) NSString *name; @property (copy, readonly, nonnull) NSArray *allItems;
non-underscored方式比
underscored方式有很明显的优势,但是即便如此,你仍然需要将它们写在每一种类型中去
为了更加高效的工作和代码的简洁,我们需要用到一种苹果称之为
audited regions的方法
什么是 Audited Regions
为了方便采用新的方式,你可以在Objective-C头文件标记一块区域作为
audited for nullability,在这块区域内,
任何简单指针类型都将被标注为
nonnull类型,这样一来,如果有一大段代码需要加注
nonnull,就比前面那种繁琐的方式简单多了。
NS_ASSUME_NONNULL_BEGIN @interface AAPLList : NSObject <NSCoding, NSCopying> // ... - (nullable AAPLListItem *)itemWithName:(NSString *)name; - (NSInteger)indexOfItem:(AAPLListItem *)item; @property (copy, nullable) NSString *name; @property (copy, readonly) NSArray *allItems; // ... @end NS_ASSUME_NONNULL_END // -------------- self.list.name = nil; // okay AAPLListItem *matchingItem = [self.list itemWithName:nil]; // warning!
安全起见,这种方式会有一些异常
1.
typedef类型不会被当做
nonnull处理,即使在
audited regions内
2.很多复杂的指针,譬如
id *必须明确标注,例如要制定一个非空的指针可以被空对象引用,要这样写
_Nullable id * _Nonnull
3.特定类型
NSError **经常通过方法的参数返回错误以致它总是被假定为一个可以被空指针引用的空指针
兼容性
如果已经存在的Objective-C代码被重写会怎样?单单以这种方式改变类型安全么?没错,是安全的。
现有的编译代码会在你的框架上继续跑,即
ABI不会变,就是说现有的代码在运行时出现
nil不会报错
当你使用新的
Swift编译器,使用不安全的方式在编译时现有的源代码在你的框架可能会有额外的警告
nonnull不影响优化,尤其是在运行时你仍然能检查标注为
nonnull的参数是否是nil,向后兼容是很重要的。
这个功能最早被发布在
Xcode 6.3上,关键字是
__nullable和
__nonnull,由于一些三方库潜在的冲突,
在
Xcode 7上将关键字改为这里提到的
_Nullable和
_Nonnull,为了兼容
Xcode 6.3,苹果定义了
__nullable和
__nonnull
回到Swift
现在我们已经nullability标注添加到我们的
Objective-C头文件中,来看看怎么在
Swift中使用它
在没有添加标注前的
Objective-C转换成
Swift应该是这样的
class AAPLList : NSObject, NSCoding, NSCopying { // ... func itemWithName(name: String!) -> AAPLListItem! func indexOfItem(item: AAPLListItem!) -> Int @NSCopying var name: String! { get set } @NSCopying var allItems: [AnyObject]! { get } // ... }
添加之后是这样的
class AAPLList : NSObject, NSCoding, NSCopying { // ... func itemWithName(name: String) -> AAPLListItem? func indexOfItem(item: AAPLListItem) -> Int @NSCopying var name: String? { get set } @NSCopying var allItems: [AnyObject] { get } // ... }
这样一来,
Swift代码看起来就简洁多了,虽然是一个微妙的变化,但这会让你的框架更完美
相关文章推荐
- 谷歌 Project Zero 团队宣布新政策,漏洞披露前将有完整的 90 天缓冲期
- 开发人员、程序员与计算机科学家三者之间的区别
- JAVA泛型—— 3fe8 转
- JAVA泛型详解——转
- 春节长假安全手册
- 地震避险自救常识
- 路由器安全有关的目录
- 打造个性_安全的电脑系统图文教程2第1/2页
- 路由器内的安全认证
- 加强php的安全之一
- http www安全必备知识
- SQLServer 2008中的代码安全(一) 存储过程加密与安全上下文
- 编写高质量代码改善C#程序――使用泛型集合代替非泛型集合(建议20)
- C#通过反射创建自定义泛型
- C#泛型用法实例分析
- C语言泛型编程实例教程
- C语言安全编码之数值中的sizeof操作符