Nullable properties and methods Nullable 特性的属性和方法
给属性和方法添加空特性修饰符的方法有很多种,在实际操作中,最常用的修饰符是 nullable 和 nonnull。只要你给任意一个属性加上了这两者中的一个,Xcode 就会询问你是不是要把所有的属性都标记成这个修饰符。这里你要有一点心理准备,工作量会稍微有些大。
我们还是用 Person 类来做例子,这个类里面有 name 属性和 fetchGreetingForTime 方法。
现在这样来写 Person.h 文件:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
- (instancetype)initWithName:(NSString*)name;
- (NSString*)fetchGreetingForTime:(NSString*)time;
@end
Person.m 文件就这样写:
#import "Person.h"
@implementation Person
- (instancetype)initWithName:(NSString*)name {
if (self = [super init]) {
self.name = name;
}
return self;
}
- (NSString*)fetchGreetingForTime:(NSString*)time {
return [NSString stringWithFormat:@"Good %@, %@!", time, self.name];
}
@end
我们还需要更新 main.m 文件,这样代码才能跑起来:
Person *person = [[Person alloc] initWithName:@"Taylor"];
NSString *greeting = [person fetchGreetingForTime:@"morning"];
NSLog(@"%@", greeting);
在代码中我简化了 Person 类的功能,这样就可以更专注于空特性修饰符的用法。在这里我们创建了一个 person 对象,并且初始化了它的名字,接着调用了 fetchGreetingForTime 方法来欢迎它。这里我们用到了演示所需的所有元素:属性、方法、方法的参数以及返回值。
在我们正式接触空特性修饰符之前,我们先来看一看在 Swift 的里面是怎么实现上面这个功能的。我们选中 Person.h 文件,然后用 Alt+Cmd+Return 快捷键打开帮助编辑器(Assistant Editor),你也可以点击 View 菜单栏,然后选择 Assistant Editor > View Assistant Editor。最后在编辑器里选择 Counterparts > Person.h (Interface)。
我们就可以看到,这段代码用 Swift 来写就是这个样子:
import Foundation
public class Person : NSObject {
public var name: String!
public init!(name: String!)
public func fetchGreetingForTime(time: String!) -> String!
}
是!不!是!惊!呆!了!
真的……全是惊叹号……我都惊呆了……
可以发现,我们的所有元素,不管是初始化器和它的参数,还是 fetchGreetingForTime 方法的参数和返回值,都被强制解包了。
现在我们来调整代码,这段代码里没有可以返回 nil,或者可以把 nil 作为参数的地方,所以我们要用到 nonnull 修饰符。现在我们只有几行代码,修改就很简单啦,所以把 name 属性改成这样子:
@property (nonnull) NSString *name;
这样写就代表了读取 name 的结果绝对是不会为空的。然而修改之后,Xcode 马上就提示你,是否要把所有的属性都标记为 nonnull。
但是处理这个提示之前,我们可以用 Cmd+B 快捷键来看看 Swift 代码的更新,你会发现现在 name 属性变成了这样:
public var name: String
总算搞定咯,但是呢,这个代码还是不能被编译,因为我们还要再给两个返回值和两个参数加上修饰符,就像这个样子:
@property (nonnull) NSString *name;
- (nonnull instancetype)initWithName:(nonnull NSString*)name;
- (nonnull NSString*)fetchGreetingForTime:(nonnull NSString*)time;
做完这些之后,我们的 Swift 代码看起来就很棒了:
public class Person : NSObject {
public var name: String
public init(name: String)
public func fetchGreetingForTime(time: String) -> String
}
小提示:所有修改都在 Person.h 文件里,不要动实现文件。