Swift Nullability and Objective

通过Bridging-Header文件,Swift可以与Objective-C无缝调用,但是Swift与Objective-C有一个很大的不同点:Swift支持Optional类型。比如NSView和NSView?,在Objective-C里对此只有一种表示,即NSView *,既可以用来表示该View为nil、也能表示为非nil,此时Swift编译器是无法确定这个NSView是不是Optional类型的,这种情况下Swift编译器会把它当作NSView!处理,隐式拆包。

在早期发布的Xcode版本中,苹果的一些框架针对Swift的Optional类型进行了一些专门审查,,使他们的API能够适配Optional,而Xcode 6.3的发布,给我们带来了Objetive-C的一个新特性:nullability注解,利用该特性我们也能对自己的代码进行类似的处理。

核心:__nullable 和 __nonnull

这个功能给我们带来了两个新的类型注解:__nullable和__nonnull,就像你看到的,__nullable可以表示一个NULL或者nil值,而__nonnull则刚好相反。如果你违反了这个规则,你将会收到编译器的警告:

– (AAPLListItem * __nullable)itemWithName:(NSString * __nonnull)name;@property (copy, readonly) NSArray * __nonnull allItems;[self.list itemWithName:nil]; // warning!

你能在任何地方使用__nullable和__nonnull关键字,比如和标准C的const一起使用,也能直接应用到指针上。但是在大多数情况下,你会以优雅的方式写下这些注解:在方法定义或声明里,只要类型是一个简单的对象或者Block指针,你就能以不带下划线的方式(nullable或nonnull)直接写在左括号后面:

– (nullable AAPLListItem *)itemWithName:(nonnull NSString *)name;- (NSInteger)indexOfItem:(nonnull AAPLListItem *)item;

对于@property,你也能以同样的方式写在它的属性列表里:

@property (copy, nullable) NSString *name;@property (copy, readonly, nonnull) NSArray *allItems;

不带下划线的形式比带下划线的形式看起来更简洁,但你仍然需要将它们应用到头文件的每一个类型里。如果你觉得麻烦同时想让头文件变得更加简洁,你就会使用到审查区域。

审查区域(Audited Regions)

如果想更加轻松的添加这些注解,那么你可以把Objective-C头文件的某个区域标记为需要审查(for nullability),在这个区域内,所有简单的指针类型都会被当作nonnull,我们之前的例子会变成这样:

NS_ASSUME_NONNULL_BEGIN- (nullable AAPLListItem *)itemWithName:(NSString *)name;- (NSInteger)indexOfItem:(AAPLListItem *)item;@property (copy, nullable) NSString *name;@property (copy, readonly) NSArray *allItems;//—@endNS_ASSUME_NONNULL_END= nil; // okayAAPLListItem *matchingItem = [self.list itemWithName:nil]; // warning!

Xcode 6.3(iOS 8.3 SDK)引入了NS_ASSUME_NONNULL_BEGIN / END宏

为了安全起见,这个规则也有一些例外情况:

你可以通过Error Handling Programming Guide了解更多详细内容。

兼容性

你的Objective-C框架现有的代码写对了吗?是否能安全的改变它们的类型? Yes, it is.

大多数情况下,应该接受nullable和nonnull,你当前使用的断言或者异常太粗暴了:违反约定是程序员经常犯的错误(而nullable和nonnull能在编译时就解决问题)。特别的,返回值是你能控制的东西,永远不应该对一个non-nullable的返回类型返回一个nil,除非这是为了向后兼容。

回到Swift

现在我们给我们的Objective-C头文件添加了nullability注解,我们在Swift中使用它: 在Objective-C中添加注解之前:

func itemWithName(name: String!) -> AAPLListItem!func indexOfItem(item: AAPLListItem!) -> Int@NSCopying var name: String! { get set }@NSCopying var allItems: [AnyObject]! { get }//—}

添加注解之后:

func itemWithName(name: String) -> AAPLListItem?func indexOfItem(item: AAPLListItem) -> Int@NSCopying var name: String? { get set }@NSCopying var allItems: [AnyObject] { get }//—}

这些Swift代码非常清晰。这是一个微妙的变化,但是它让你的框架使用起来更爽。

来说是非者,便是是非人。

Swift Nullability and Objective

相关文章:

你感兴趣的文章:

标签云: