Swift 1.2 中 UIImage 的 If Let vs Guard Let

Posted

技术标签:

【中文标题】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 属性并尝试,必须工作,让我知道

以上是关于Swift 1.2 中 UIImage 的 If Let vs Guard Let的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何从 UIImage 数组中提取图像文件名

如何在 Swift 中识别 UIImage 数组中的 Tapped UIImage

将UIImage转换为NSData并在Swift中转换回UIImage?

在 Swift 中旋转 UIImage

如何使用 Swift 获取 UIImage 中像素的颜色?

如何在 swift 3 中使用 UIImage 数组为零?