Swift:为什么我仍然需要可选值?

Swift: why do I need optionals anyways?

我已经阅读了几篇有关它的文章并理解了基本原理,并且同意它在某些情况下可能会有用。但是,大多数情况下,如果我 nil 到了我不应该去的地方,我会希望我的程序崩溃——这就是我怎么知道有问题的!

此外,我读到使用可选值可以缩短代码。这怎么可能??据我所见,它们背后的整个想法是它们可以有一个值或 nil 所以你必须做额外的检查,而以前这是没有必要的!

需要一直使用 "as" 是怎么回事?它只会让一切变得更加冗长和冗长。比如比较下面的代码在Objective-C和Swift

Objective-C:

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Home"];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = vc;
[UIView transitionWithView:appDelegate.window
                          duration:0.2
                          options:UIViewAnimationOptionTransitionCrossDissolve
                          animations:^{ appDelegate.window.rootViewController = vc; }
                          completion:nil];

Swift:

//have to check if self.storyboard != nil
let viewController:UIViewController = self.storyboard?.instantiateViewControllerWithIdentifier("Home") as UIViewController; //Isn't the view controller returned by instantiateViewControllerWithIdentifier() already of type UIViewController?
let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate; //Isn't the delegate returned by sharedApplication() already of type AppDelegate?
//have to check if appDelegate.window != nil
appDelegate.window!.rootViewController = viewController as UIViewController; //Why cast viewController as UIViewController if the type has already been explicitly set above?

UIView.transitionWithView(
    appDelegate.window!,
    duration: 0.2,
    options: UIViewAnimationOptions.TransitionCrossDissolve,
    animations:{appDelegate.window!.rootViewController = viewController as UIViewController},
    completion: nil
);

我做错了什么吗?或者这真的是它想要的样子吗?

可选

如果你确定一个变量应该 永远不会 为 nil,你可以使用 ! 强制解包一个可选的或使用 [=12= 声明为隐式解包].当它为 nil 时,这将导致崩溃,就像你想要的那样。

但是,对于某些变量,将它们设置为零是合理的。例如,User 模型的 age 变量未设置,因为用户未提供它。

明确将它们标记为可选并使用 if let 展开它们会迫使您考虑可空性。最后,这会创建更健壮的代码。

我不认为它会导致代码短路。在 Objective-C 中使用 if var != nil 的地方在 Swift 中使用 if let var = var。在 Obj-C 中向 nil 发送消息是一个 noop,您可以在 Swift 中使用 var?.method() 获得相同的行为。最后还是一样。

铸造(as)

你现在需要在 Swift 中强制转换的一个重要原因是因为一些 Objective-C 方法 return id,这在 Obj-C 中没有问题但会导致麻烦在 Swift。我希望随着 Swift 变得越来越流行并且框架得到调整,这种情况会减少。

更新代码

我快速查看了您的代码,看来您不需要一半的转换。这是我的想法:

if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("Home") as? UIViewController {
    if let window = UIApplication.sharedApplication().delegate?.window {
        window.rootViewController = viewController

        UIView.transitionWithView(window, duration: 0.2, options: .TransitionCrossDissolve, animations: {
            window.rootViewController = viewController
        }, completion: nil);
    }
}