如何理解 if let 与guard
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何理解 if let 与guard相关的知识,希望对你有一定的参考价值。
参考技术A if let 和 guard 只是语法糖,没有也可以,但有了可以使得代码更简洁方便。要理解 if let 和 guard,不妨设想假如没有这两者,代码会怎么写。------------------------------------if let
func doSomething(str: String?)
let v: String! = str
if v != nil
// use v to do something
Swift 中因为有optional, 经常需要判断是否为空。假如没有if let,大致写成上面的样子,有了if let, 可以改写成
func doSomething(str: String?)
if let v = str
// use v to do something
上面两段代码的控制流是一样的。对照着,可以看出if let的写法更加简洁方便。
------------------------------------
guard
假如if中出现的代码很长,我们写代码时可以将错误情况先返回。比如:
func doSomething(str: String?)
let v: String! = str
if v == nil
return
// use v to do something
这样做可以避免过多的嵌套。上面代码实在太常见了,swift也提供一个guard这个语法糖,用guard可以改写成:
func doSomething(str: String?)
guard let v = str else return
// use v to do something
上面两段代码的控制流是一样的。也可以看出guard的写法更加简洁方便。
------------------------------------
至于if let 和 guard 语法中出现的where,只是附加一些条件。相当于逻辑运算 && 和 ||。SQL中的条件语法也是用where这个关键字。
假如还不理解,动手将一段代码,不用if let 和 guard 进行改写。试多几次,就会发觉很自然了。
Swift 1.2 中 UIImage 的 If Let vs Guard Let
【中文标题】Swift 1.2 中 UIImage 的 If Let vs Guard Let【英文标题】:If Let vs Guard Let for UIImage in Swift 1.2 【发布时间】:2017-06-04 19:35:32 【问题描述】:我正在学习 iOS Apple 开发人员教程,但我遇到了一些问题,因为我的计算机的 Swift 版本是 1.2,Xcode 是 6.4 而不是 Swift 3.0。我已经能够根据需要同时降级代码,但是在下面的 Swift 2.0 中引入的“guard let”中遇到了错误:
// The info dictionary may contain multiple representations of the image.
// You want to use the original.
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
我将其转换为以下内容:
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
return selectedImage
else
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
//Set photoImageView to display the image.
photoImageView.image = selectedImage
但我收到以下错误:“使用未解决的已识别 'selectedImage'”
任何帮助将不胜感激!
编辑:下面是完整代码
import UIKit
class ViewController: UIViewController, UITextFieldDelegate,
UIImagePickerControllerDelegate, UINavigationControllerDelegate
//MARK: Properties
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var mealNameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
override func viewDidLoad()
super.viewDidLoad()
//Handle the text field's user input through the delegate callbacks
nameTextField.delegate = self
//MARK: UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool
//Hide the keyboard
textField.resignFirstResponder()
return true
func textFieldDidEndEditing(textField: UITextField)
//Set the lablel name as what the used typed
mealNameLabel.text = textField.text
//MARK: UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(picker: UIImagePickerController)
//Dismiss the picker if the user canceled
dismissViewControllerAnimated(true, completion:nil)
func imagePickerController(picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any])
//The info dictionary may contain multiple representations of the image. You want to use the original.
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
//Set photoImageView to display the image
photoImageView.image = selectedImage
else
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
//Set photoImageView to display the image
//photoImageView.image = selectedImage
//Dismiss the picker
dismissViewControllerAnimated(true, completion: nil)
//MARK: Actions
@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer)
//Hide the keyboard
nameTextField.resignFirstResponder()
//UIImagePickerController is a view controller that lets a user pick media from their photo library.
let imagePickerController = UIImagePickerController()
//Only allow photos to be picked, not taken.
imagePickerController.sourceType = .PhotoLibrary
//Make sure ViewController is notified when the user picks and image.
imagePickerController.delegate = self
presentViewController(imagePickerController, animated: true, completion: nil)
@IBAction func setDefaultLabelText(_: UIButton)
mealNameLabel.text = "Default Text"
【问题讨论】:
你的错误在这一行photoImageView.image = selectedImage
?,这是因为你的变量 selectedImage 只在你的 if let
范围内定义,顺便说一句,你返回你的 selectedImage
之后你是将其分配给 .image?
正确,错误就在那一行。如果我在 if let 中添加return selectedImage
,会解决它吗?更新:刚试过这个。现在return selectedImage
返回错误:'UIImage' is not convertible to '()'
检查我的答案
【参考方案1】:
if let
可选绑定语句创建一个新变量,该变量仅存在于后面的大括号内:
if let foo = optionalFoo
//foo is only defined here
//foo has gone out of scope.
guard let 创建一个新变量,该变量在当前作用域结束后的代码中存在:
func bar(optionalFoo: FooThing)
guard let foo = optionalFoo else return
//foo exists from here until the end of the
//current scope (the end of the func)
由于 Swift 1 没有保护语句,您需要将 guard let
之后的代码移动到 if let
的大括号内:
看起来@ReinierMelian 用他的回答打败了我。在 Swift 1.x 中查看他的正确代码形式的答案。
请注意,Swift 1.0 已经过时了,使用它对你自己不利。您应该升级到 Xcode 8.3 和 Swift 3.1。从 Swift 1 到 Swift 2 的变化是显着的,而从 Swift 2 到 Swift 3 的变化是大。 Swift 1 代码无法在 Xcode 8 中编译,您可能无法通过自动转换运行它。 (Xcode 8 将提供通过自动转换为 Swift 3 来运行 Swift 2.x,但我不确定它是否会将 Swift 1 转换为 Swift 3。
【讨论】:
现在 Swift 1.x 已经过时了 4 个主要版本,所以你绝对应该继续前进。 (我们使用的是 Swift 5.2)【参考方案2】:发生这种情况是因为您的变量 selectedImage
仅在您的 if let
范围内定义
您必须改用此代码
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
//Set photoImageView to display the image.
photoImageView.image = selectedImage
return selectedImage
else
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
希望对你有帮助
【讨论】:
嗨 Reinier,感谢您的帮助。代码现在可以编译,但是当我在模拟器中单击并选择一个图像时,它会加载到应用程序中。这可能是因为它包含在if let
范围内吗?
@user282041 你是想说不要在应用程序中加载?还是不要在模拟器中加载?不要在你的 photoImageView UIImageView 中加载?
它不会在模拟器中加载。我单击图像,从库中选择一张照片,但一旦我选择它,照片就不会加载。
@user282041 你能分享你的完整代码看看有什么问题吗?
@user282041 我认为你的问题又是范围,你在一个方法中定义你的UIImagePickerController
,将你的选择器视图作为 viewController 属性并尝试,必须工作,让我知道以上是关于如何理解 if let 与guard的主要内容,如果未能解决你的问题,请参考以下文章
Swift 基本语法03-"if let"和"guard let"
Swift 1.2 中 UIImage 的 If Let vs Guard Let