Apple Tutorial Bug

Hey Guys,
I'm very new at coding and Swift so I googled for a Swift Tutorial and I found the "old" Apple Tutorial and I made it. But at the End of the lesson "Work with View" controllers I always get an Error at

guard let selectedImage = info[UIImagePickerControllerOriginalImage] as ? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: (info)").

It says Cannot subscript a value of type '[String : Any]' with an index of type 'UIImagePickerController.InfoKey'
Do anybody knows how to solve the issue? I will type in the whole code and the link to the tutorial.

https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/WorkWithViewControllers.html#//apple_ref/doc/uid/TP40015214-CH6-SW1

I don't know why the first lines are not included to the code.

//
// ViewController.swift
// FoodTracker
//
// Created by Okke Warner on 22.07.19.
// Copyright © 2019 Okke Warner. All rights reserved.
//

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 delegate callbacks.
    nameTextField.delegate = self
}

//MARK: UITextFieldDelegate

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    // Hide the keyboard.
    textField.resignFirstResponder()
    return true
}

func textFieldDidEndEditing(_ textField: UITextField) {
    mealNameLabel.text = textField.text
}

//MARK: UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    // Dismiss the picker if the user canceled.
    dismiss(animated: true, completion: nil)
}
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

    // 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)")
    }
    
    // Set photoImageView to display the selected image.
    photoImageView.image = selectedImage
    
    // Dismiss the picker.
    dismiss(animated: 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 an image.
    imagePickerController.delegate = self
    present(imagePickerController, animated: true, completion: nil)
}

@IBAction func setDefaultLabelText(_ sender: UIButton) {
    mealNameLabel.text = "Default Text"
}

}

The SDK now imports those string constants as a structure, to improve type safety. The error message is trying to tell you to use the UIImagePickerController.InfoKey type as the dictionary key.

The change is very simple: replace UIImagePickerControllerOriginalImage with .originalImage.

First, thanks for your answer. But if change it I get issues too.
If I only change UIImagePickerControllerOriginalImage to UIImagePickerController.originalImage
the Error says Type 'UIImagePickerController' has no member 'originalImage' and if I totally replace it to .originalImage it says 'UIImage?' is not convertible to 'UIImage'. Did I understand anything wrong? Or should I change one more thing?

Oh, the delegate method also needs updating. I think because you inadvertently declared it as private, it is confusing the error message system too.

Replace the line:

private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

with:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

This is the modern API definition which declares the info dictionary with a structured key, rather than simply strings. It is unfortunate that the Apple tutorial was written before this change came in, and clearly hasn't been updated.

(Note, your key can either be .originalImage or written explicitly as UIImagePickerController.InfoKey.originalImage. The key does not exist as a member of the top-level UIImagePickerController type, which is what your first error message was describing).

1 Like

Thanks! It works!