0

I am working my way through the iOS Apple Developer Tutorial, but am having a bit of an issue since my computer's version of Swift is 1.2 and Xcode is 6.4 instead of Swift 3.0. I've been able to work along-side downgrading the code as need, but have hit an error in "guard let", which was introduced in Swift 2.0, below:

// 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)")
}

I converted it to the following:

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

but I got the following error: "Use of unresolved identified 'selectedImage'"

Any help would be greatly appreciated!

EDIT: FULL CODE BELOW

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"
}
}
user282041
  • 37
  • 8
  • your error is in this line `photoImageView.image = selectedImage` ?, this is because you have the variable selectedImage defined only inside your `if let` scope by the way, you return your `selectedImage` and after that you are assigning it to a .image? – Reinier Melian Jun 04 '17 at 19:44
  • Correct, the error is on that line. If I add in a `return selectedImage` to the if let, will that fix it? Update: just tried this. Now the `return selectedImage` is returning an error: `'UIImage' is not convertible to '()'` – user282041 Jun 04 '17 at 19:54
  • check my answer – Reinier Melian Jun 04 '17 at 20:00

2 Answers2

0

this happens because you have the variable selectedImage is defined only inside your if let scope

You must use this code instead

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)")
}

I hope this helps

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
  • Hey Reinier, thanks for the help. The code now compiles, but when I click and select an image in the simulator it load in the app. Could this be because it is contained inside the `if let` scope? – user282041 Jun 04 '17 at 20:53
  • @user282041 You are trying to say don't load in the app?, or don't load in the simulator?, don't load in your photoImageView UIImageView? – Reinier Melian Jun 04 '17 at 21:14
  • It does not load in the simulator. I click the image, select a photo from the library, but the photo does not load once I select it. – user282041 Jun 05 '17 at 01:28
  • @user282041 can you share your full code to see what is wrong? – Reinier Melian Jun 05 '17 at 12:04
  • @user282041 your problem is scope again I think, you are defining your `UIImagePickerController` inside one method, put your picker view as viewController property and try, must work, let me know about – Reinier Melian Jun 07 '17 at 01:10
0

An if let optional binding statement creates a new variable that only exists inside the braces that follow:

if let foo = optionalFoo {
  //foo is only defined here
}

//foo has gone out of scope.

guard let creates a new variable that exists from the code after through the end of the current scope:

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)
}

Since Swift 1 doesn't have a guard statement, you need to move the code that's after the guard let to inside the braces of the if let:

It looks like @ReinierMelian beat me to it with his answer. See his answer for the correct form of your code in Swift 1.x.

Note that Swift 1.0 is badly out of date, and you are doing yourself a disservice working with it. You should upgrade to Xcode 8.3 and Swift 3.1. The change from Swift 1 to Swift 2 was significant, and from Swift 2 to Swift 3 was big. Swift 1 code won't compile in Xcode 8, and you may not be able to run it through an automatic conversion. (Xcode 8 will offer to run Swift 2.x through an automatic conversion to Swift 3, but I'm not sure if it will convert Swift 1 to Swift 3.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • And now Swift 1.x is 4 major versions out of date, so you should definitely move on. (We're on Swift 5.2) – Duncan C Jan 16 '20 at 22:33