outlet 或 action 找不到連線目標,造成 App 閃退

電影食神說折凳是七種武器之首,如果要選出新手剛開始學習 iOS App 開發,最容易遇到的問題,莫過於因為 outlet 或 action 找不到連線目標,造成 App 閃退。

開發 iOS App 時,我們一般會將程式和 App 畫面分開,然後利用 outlet 存取控制 storyboard 畫面上的元件,利用 action 設定事件發生時觸發的 function。(比方點選按鈕) 但是如果你不小心把 outlet 連結的變數或 action 連結的 function 刪除或改名,原本的連線還在,但 App 已找不到連結的目標時,將引發 App 閃退的悲劇。

接下來我們就以猜數字 App 的畫面為例說明吧。

例子1: 將 outlet 改名或刪除,this class is not key value coding-compliant for the key

outlet numberTextField 連結到畫面上輸入數字的 text field,我們將它注解。

class ViewController: UIViewController {
//@IBOutlet weak var numberTextField: UITextField!

執行

App 閃退,模擬器一片空白。

此時 Xcode 的畫面如下。當 Xcode 的畫面出現紅色一條,停在 AppDelegate.swift 的 class AppDelegate 時,即代表 App 已經閃退死掉了。

點選紅色長條後,Xcode 會告訴我們錯誤的原因。

[<Demo2.ViewController 0x155808890> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key numberTextField.

另外在右下角的 Console 也會顯示錯誤訊息。

以後當你看到錯誤訊息提到 this class is not key value coding-compliant for the key 時,十之八九都是因為 outlet 找不到連結的變數。而且它還會當抓耙子,告訴我們凶手是誰。比方剛剛的例子,它提到了 for the key numberTextField,表示曾經有個 outlet 連到 numberTextField,但是現在程式碼裡找不到 numberTextField,因此造成 App 閃退。

例子2: 將 action 改名或刪除,unrecognized selector。

action guess 連結到畫面上的 go 按鈕,我們將它改名為 guess2。

@IBAction func guess2(_ sender: Any) {

}

執行

App 一開始活得好好的,然而一旦我們點選 go 按鈕,App 將再次閃退。因為此時 action 找不到連結的 function。點選紅色長條或從右下角的 Console 可查詢 App 閃退的原因。

關鍵字在 unrecognized selector,表示它不認得 selector。selector 的意思就是 function,因此它找不到 function,而且它也會跟我們提到 function 的名字,比方剛剛例子裡的 guess:

以彼得潘自己的教學經驗,初學者如果發現 App 一啟動就閃退,或是顯示某個頁面,點選某個按鈕時閃退,大概有六成以上的機率是 outlet 或 action 找不到連線目標導致。如果你還發現 Console 的錯誤訊息出現剛剛提到的關鍵字, this class is not key value coding-compliant for the key 或 unrecognized selector,那大概就八九不離十了。

解決方法

解法一:

  • 從 Console 的錯誤訊息找出找不到的 outlet 或 action 名字。

比方當我們看到以下錯誤訊息時,找不到的名字是 guess。

-[Demo2.ViewController guess:]: unrecognized selector sent to instance 0x147d0b7c0
  • 切換到 Find navigator 頁面(快速鍵 cmd + shift + f)輸入找不到的名字。

我們在 Find navigator 輸入 guess 後,可從清單裡點選 Main.storyboard 下的 guess。

此時右邊的 Connection inspectors 頁面將顯示 guess ,而且標示出提醒我們有問題的黃色三角形驚嘆號。

滑鼠游標移到黃色三角形上,還會顯示貼心地告訴我們警告的原因,The action ‘guess:’ is not defined on ‘ViewController’。

看到黃色三角形,殺就對了,就是它害 App 閃退的。殺它十分容易,點選 X 即可刪除。

解法 2:

  • 在 storyboard 點選 outlet 或 action 應連到的元件。

大部分的時候此元件是 controller ,不過也有可能是某個 cell 或 view。

  • 從右鍵選單找尋是否有黃色警告的三角形。

如果有的話,即表示有找不到連線目標的 outlet 或 action。

除了右鍵選單,我們也可以點選 controller 後,從它的 Connections inspector 找到黃色三角形。

  • 點選 X 刪除黃色三角形標示的連線。

以上閃退的故事告訴我們,分手要分乾淨,不要藕斷絲連,不然會很可怕。因此千萬記得當你在程式碼裡將 outlet 連結的變數或 action 連結的 function 刪除時,還要回到 storyboard 刪除當初的連線。

若想修改 outlet 或 action 的名字,也是可以,只是不要自己手動改,請透過 Xcode 幫我們改,相關說明可參考以下連結。

解法 3:

若是找不到黃色驚嘆號,可能是你遇到了 Xcode 特別的 bug。此時可試試重新設定 controller 的 class。先將它的 Class 清空,然後重新選擇一次類別,可能問題就解決了。

詢問 AI

我們也可以貼上錯誤的文字或截圖詢問 AI,例如以下例子。

This error message indicates that in your iOS application, there’s an attempt to set a value for a key called `numberTextField` on an instance of `Demo2ViewController`, but `Demo2ViewController` does not have a property or accessor method for this key. This is a common error when using Key-Value Coding (KVC) and it suggests that either the key name is incorrect or the property does not exist.

Here’s how you can debug this:

1. **Check your Interface Builder (IB) connections**: If you are using a storyboard or xib file, make sure that there are no old connections to a `numberTextField` that you may have deleted or renamed. Look in the “Connections Inspector” for any outdated references and remove them.

2. **Verify your Code**: Ensure that the `numberTextField` is correctly declared in `Demo2ViewController`. If it’s supposed to be an IBOutlet, the declaration should look like this:

@IBOutlet weak var numberTextField: UITextField!

Make sure that the declaration in the code matches the IB connections exactly, including the case sensitivity.

3. **Initialization**: If you are setting this value programmatically, ensure that the property exists on the `Demo2ViewController` and is accessible for KVC.

self.setValue("someValue", forKey: "numberTextField")

If `numberTextField` is meant to be accessed through KVC, ensure you have the correct property or methods defined to handle it. If not, you should set the value directly on the property or through a method.

4. **Typo in Key Name**: Typos are a common source of KVC errors. Double-check the key name `numberTextField` for any typos in your code or storyboard.

5. **Refactor if necessary**: If you’ve recently refactored your code or renamed properties, search your entire project for `numberTextField` to ensure it has been updated everywhere.

To fix the error, you will need to align your storyboard/xib file with your code or vice versa. After making the necessary changes, clean your build folder in Xcode (`Product -> Clean Build Folder`) and compile again to see if the error is resolved.

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com