ios 此类不符合键取消的键值编码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45902651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:24:14  来源:igfitidea点击:

This class is not key value coding-compliant for the key cancel

iosswiftxcodesigabrt

提问by Ethan

I keep getting this error: 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.'

我不断收到此错误: 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.'

I'm trying to complete the Apple developer guide to getting started with iOS apps. My code and storyboard looks exactly like theirs does in the example file. I'm hoping that a fresh eye might be able to see something I am not?

我正在尝试完成 iOS 应用程序入门的 Apple 开发人员指南。我的代码和故事板看起来与示例文件中的完全一样。我希望新的眼睛能够看到我没有看到的东西?

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

There are a few other files, but please just let me know what you need because I am very new to Swift/XCode and not sure what to provide/not provide.

还有一些其他文件,但请告诉我您需要什么,因为我对 Swift/XCode 非常陌生,不确定要提供/不提供什么。

回答by Alex Shubin

This means that you have something on your storyboard connected to the IBOutlet called cancelbut you don't have this IBOutlet in your class. So compiler can't find Key cancel(it means property) in your class. You should find that button(i think it's a UIButton because of the name) in storyboard, click right mouse button on it and click "x" to delete that connection. Or you might want to delete this button at all. Or you might want to add this IBOutlet to your class.

这意味着你的故事板上有一些东西连接到被调用的 IBOutlet,cancel但你的班级中没有这个 IBOutlet。所以编译器cancel在你的类中找不到 Key (它意味着属性)。你应该在故事板中找到那个按钮(我认为它是一个 UIButton,因为它的名字),在它上面单击鼠标右键,然后单击“x”删除该连接。或者您可能想完全删除此按钮。或者您可能希望将此 IBOutlet 添加到您的类中。

回答by llamacorn

I agree with what Alex Shubin mentioned in his answer, an actionable solution like “look for any connections that don't exist anymore and delete them”. I was having the same issue and his suggestion fixed that bug. For those who are new to programming, and Xcode like me, a little more information on how to locate the x button in storyboard might be helpful.

我同意 Alex Shubin 在他的回答中提到的,一个可操作的解决方案,比如“查找任何不再存在的连接并删除它们”。我遇到了同样的问题,他的建议修复了该错误。对于那些不熟悉编程的人,以及像我这样的 Xcode,有关如何在故事板中定位 x 按钮的更多信息可能会有所帮助。

Click on the yellow circle at the top of the view controller in storyboard.

单击故事板中视图控制器顶部的黄色圆圈。

enter image description here

在此处输入图片说明

Then show the connections inspector in the upper right of the utilities bar. The connections inspector is the menu on the far right, a circle with a right pointing arrow. Click that, and you should see all the connections for that view controller.

然后在实用工具栏的右上角显示连接检查器。连接检查器是最右侧的菜单,一个带有向右箭头的圆圈。单击它,您应该会看到该视图控制器的所有连接。

I'm including a screen shot of what that looks like in my app.

我在我的应用程序中包含了一个屏幕截图。

enter image description here

在此处输入图片说明

回答by Mathioli Ramalingam

Check for the module name under "Identity Inspector". Either module name has to be selected or "Inherit Module from Target" has to be checked. If there are multiple modules, select the appropriate one.

检查“身份检查器”下的模块名称。必须选择模块名称或必须选中“从目标继承模块”。如果有多个模块,选择合适的一个。