在Swift中测试null objective-C字符串的正确方法?

时间:2016-04-05 18:07:18

标签: swift

我有一个Objective-C框架,它导出以下类:

@interface NIDIdentifiedNumberItem : NSObject
@property (strong, nonatomic) NSString          *name;
@property (strong, nonatomic) NSString          *address;
@property (strong, nonatomic) NSString          *number;
...

我读到Objective-C指针会自动转换为swift选项,但这不是我所观察到的:

enter image description here

并且以下代码不会产生预期结果:

if item.address != nil
{
   // code will execute

如何在Swift中检查Objective-C空指针?

因此在框架中填充对象:

- (NSArray*) identifiedNumbers {
    NSMutableArray* numbers = [[NSMutableArray alloc] init];
     NIDIdentifiedNumberItem* item = [[NIDIdentifiedNumberItem alloc] init];
     item.name = "Something";
     item.address = nil;
     etc.
    [numbers addObject:item];
    return numbers;

在Swift中获得:

   var identifiedNumbers = []
   ...
   identifiedNumbers =  NIDModel.singleton().identifiedNumbers()
   ...
   let item = identifiedNumbers[indexPath.row]

我还观察到以下内容:

    let a = item.address
    if a != nil {
    }
    if let b = item.address
    {
    }

这两个if语句都将执行。赋值后,a的类型为String !!而b是String!类型。为什么它们不同,为什么if语句评估为true?

2 个答案:

答案 0 :(得分:2)

问题在于这一行:

var identifiedNumbers = []

您尚未声明这是 的数组。因此, faute de mieux ,它被输入为NSArray。但是NSArray没有已知的元素类型。因此,当你说

let item = identifiedNumbers[indexPath.row]

你得到一个AnyObject。因此,当您说item.address时,您不是提取地址;你问这个未知的东西是否 address属性。这就是为什么它被输入为String!! - 第一个!是因为如果这个东西确实有一个address它将是一个可选的包裹一个字符串,而第二个是因为整个拥有address属性的概念将该结果包装在另一个Optional中。

事实证明,这个未知事物确实具有address属性,因此item.address不是nil。但是如果你打开那个现在你有一个可选字符串,所以现在你可以看到它是否实际上是nil。它是:

if item.address != nil {
    if item.address! != nil {
        // it is nil, this won't execute
    }
}

如果您正确地键入了identifiedNumbers [NIDIdentifiedNumberItem],那么您将永远不会遇到这些疯狂和不必要的困难。您可以使用Objective-C的轻量级泛型来帮助实现自动化。

答案 1 :(得分:0)

如果您还没有使用NS_ASSUME_NONNULL_BEGIN/END,那么转换为可选项。所以你可以:

if let address = item.address
{
    print("Address is \(address)")
}

如果你告诉编译器假设非null,那么暴露给Swift的类型似乎不是可选的。因此,就Swift而言,它永远不会是nil