このエラーが引き続き発生します:Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<FoodTracker.MealViewController 0x7faa9ed189d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key cancel.'
Apple iOSアプリの使用を開始するための開発者ガイド。私のコードとストーリーボードは、サンプルファイルのコードとストーリーボードとまったく同じように見えます。私ではない何かを見ることができますか?
import UIKit
import os.log
class MealViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
//MARK: Properties
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var ratingControl: RatingControl!
@IBOutlet weak var saveButton: UIBarButtonItem!
/*
This value is either passed by 'MealTableViewController' in
'prepare(for:sender) or constructed as part of adding a new meal.
*/
var meal: Meal?
override func viewDidLoad() {
super.viewDidLoad()
// Handle the text field's user input through delegate callbacks
nameTextField.delegate = self
// Enable save button only if text field has valid Meal name
updateSaveButtonState()
}
//MARK: UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
updateSaveButtonState()
navigationItem.title = textField.text
}
func textFieldDidBeginEditing(_ textField: UITextField) {
// Disable save button while editing
saveButton.isEnabled = false
}
//MARK: UIImagePickerControllerDelegate
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
// Dismiss the picker if the user canceled
dismiss(animated: 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.
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: Navigation
@IBAction func cancel(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
// Configure view controller before it's presented
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
// Configure destination view controller only when save button pressed
guard let button = sender as? UIBarButtonItem, button === saveButton else {
os_log("The save button was not pressed, cancelling", log: OSLog.default, type: .debug)
return
}
let name = nameTextField.text ?? ""
let photo = photoImageView.image
let rating = ratingControl.rating
// Set meal to be passed to MealTableViewController after unwind segue
meal = Meal(name: name, photo: photo, rating: rating)
}
//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)
}
//MARK: Private Methods
private func updateSaveButtonState() {
// Disable the save button if the text field is empty
let text = nameTextField.text ?? ""
saveButton.isEnabled = !text.isEmpty
}
}
他にもいくつかのファイルがありますが、私はSwift/XCodeが初めてで、何を提供するかしないかわからないので、必要なものを教えてください。
つまり、ストーリーボード上にcancel
という名前のIBOutletに接続されているものがありますが、クラスにはこのIBOutletがありません。そのため、コンパイラはクラスでKey cancel
(プロパティを意味します)を見つけることができません。ストーリーボードでそのボタン(名前のせいでUIButtonだと思う)を見つけ、マウスの右ボタンをクリックし、「x」をクリックしてその接続を削除します。または、このボタンをまったく削除することもできます。または、このIBOutletをクラスに追加することもできます。
「もう存在しない接続を探して削除する」などの実用的なソリューションであるアレックスシュビンの答えに同意します。私は同じ問題を抱えていて、彼の提案はそのバグを修正しました。プログラミングが初めてで、私のようなXcodeをお使いの場合は、ストーリーボードでxボタンを見つける方法についてもう少し情報が役立つかもしれません。
ストーリーボードのView Controllerの上部にある黄色の丸をクリックします。
次に、ユーティリティバーの右上に接続インスペクターを表示します。接続インスペクターは、右端のメニュー、右向き矢印の付いた円です。それをクリックすると、そのView Controllerのすべての接続が表示されます。
アプリにどのように見えるかのスクリーンショットを含めています。
「Identity Inspector」でモジュール名を確認します。モジュール名を選択するか、「ターゲットからモジュールを継承」をチェックする必要があります。複数のモジュールがある場合は、適切なモジュールを選択します。