Xcode - 如何修复'NSUnknownKeyException'错误,原因:"...此类不符合键值编码的要求,无法为键X进行编码"?

1317
我正在尝试将一个在我的类中创建的UILabel与一个IBOutlet连接起来。
我的应用程序崩溃并显示以下错误:
*** 
Terminating app due to uncaught exception
'NSUnknownKeyException', reason: 
'[<UIViewController 0x6e36ae0> setValue:forUndefinedKey:]: 
this class is not key value coding-compliant for the key XXX.'

这是什么意思,我该如何修复?

15
Pedrotorres是正确的。 是的,这是正确的。如果您正在进行UITableViewCell,记住在IB中将File's Owner设置为NSObject,并将UITableViewCell的Class设置为您定义的.h类。 - gdm
4
当你遇到这样的问题,而冒犯的键是一个“动作”而不是一个“插座”,那么很可能你有一个“插座”错误地引用了你的“动作”函数名,而不是你的“插座”变量名。 - Alex Yursha
2
你应该注意到错误信息中键的名称(OP 称其为“XXXX”)是你在 nib 文件中命名的某个东西的名称。这应该有助于缩小你的搜索范围。 - kris
我提交了rdar://22105925,要求苹果在构建时更明显地显示这些错误。 :) - jtbandes
1
如何立即解决问题!https://dev59.com/0eo6XIcBkEYKwwoYOR0q#13812660 绝佳的技巧。 - Fattie
显示剩余6条评论
81个回答

1662

您的xib文件可能存在连接问题。

我经常遇到这个错误。虽然TechZen的回答在这种情况下是完全正确的,但另一个常见原因是当您在.h/.m中更改了已连接到nib文件中的“File's Owner”的IBOutlet属性的名称时。

从您的nib文件开始:

  1. 选择IB中的对象并转到“Connections Inspector”。
  2. 在“Referencing Outlets”下,确保您的对象没有仍然连接到旧属性名称......如果是这样,请点击小“x”以删除引用,然后重新编译。

    enter image description here

如果您正在使用Storyboard,则另一个常见原因是您的UIButton可能有多个分配(解决方案与nib几乎相同):

  1. 打开故事板并右键单击UIButton
  2. 您将看到此按钮有多个分配/引用。 使用小“x”删除一个“Main...”灰色窗口:

    example 2


2
谢谢!在我的情况下,我有两个出口指向同一个视图,摆脱旧的并将视图连接到新的结束了异常。 - Mark Patterson
我的东西被复制了两次。我开始从专业版(从轻量版)拖放每一个连接,以为它会保留在其他项目中的连接。当我发现重复的连接时,需要点击三次才能断开连接,我真心希望早在三天前就这样做了。哦,这就是开发人员的生活。 - aremvee
我遇到了UIButton被分配多次的问题。这解决了我的问题。 - mythicalcoder
我曾经遇到过类似的错误,其中我将一个按钮输出口连接到了错误的 ViewController Swift 文件上,而该页面使用 GUI 尚未创建。 - brw59
一遍又一遍地出现相同的错误,以不同的方式,即使我尽可能小心!我认为这是Xcode上的一个bug,不可能每次都搞砸。 - Daniel Beltrami
显示剩余4条评论

1062

你的视图控制器在xib中可能使用了错误的类。

我下载了你的项目。

你遇到的错误是

'NSUnknownKeyException',原因:'[<UIViewController 0x3927310> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key string.'

这是由于在MainWindow.xib中的Second视图控制器使用了UIViewController而不是正确的SecondView类所引起的。更改为正确的类即可解决问题。

顺便说一下,在Objective-C中使用类似 "string" 的名称是不好的做法。这会导致运行时命名冲突。即使是练手的应用程序也要避免这样做。命名冲突很难跟踪,并且你不想浪费时间。

这个错误的另一个可能原因:从一个控制器复制和粘贴元素到另一个控制器时,Xcode 会在编辑和重新链接该元素到新控制器后仍然保留与原始控制器的链接。

这个错误的另一个可能原因:

错误的输出口。

你已经在.h文件中删除重命名了一个输出口名称。

.xib.storyboard文件的连接检查器中删除它。

还有一个可能的原因

(在我的情况下)对UIView进行可绑定属性扩展并为这些可绑定属性设置值(例如阴影、角半径等),然后从UIView扩展中删除这些属性(由于某种原因),但以下<userDefinedRuntimeAttributes>仍留在xml中(foo.storyboard):

<userDefinedRuntimeAttributes>
  <userDefinedRuntimeAttribute type="color" keyPath="shadowColor">
      <color key="value" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
  </userDefinedRuntimeAttribute>
  <userDefinedRuntimeAttribute type="number" keyPath="shadowOpacity">
      <real key="value" value="50"/>
  </userDefinedRuntimeAttribute>
  <userDefinedRuntimeAttribute type="point" keyPath="shadowOffset">
      <point key="value" x="5" y="5"/>
  </userDefinedRuntimeAttribute>
  <userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
      <real key="value" value="16"/>
  </userDefinedRuntimeAttribute>
  <userDefinedRuntimeAttribute type="number" keyPath="borderWidthValue">
      <real key="value" value="0.0"/>
  </userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>

解决方案: 右键点击 foo.storyboard > 以源代码方式打开 > 搜索关键路径(例如,shadowRadius) > 删除导致问题的 </userDefinedRuntimeAttributes>


10
不要忘记将nib文件中的“view”出口与继承自UIViewController的自定义类的文件所有者视图出口相连接。这可以通过从“占位符”下的“文件所有者”控制拖动到“对象”下的“视图”,并选择视图出口来完成。 - Nirma
1
我甚至没有使用Interface Builder,但仍然出现这个错误。有任何想法是怎么回事吗? - sudo
14
没关系。这是由于两个原因造成的:Xcode仍在访问我的Main storyboard,尽管它已从项目中删除,并且模拟器缓存了它。我强烈不建议使用storyboards或NIBs - 它们会引起很多问题。 - sudo
7
@Josh 哈哈。每次我想要在Xcode中创建本地应用程序时,都会花一整天时间试图了解如何做任何事情。我是一名C#开发者,所以最近一直在研究Xamarin和Telerik(nativescript)的解决方案。 - The Muffin Man
1
另一个可能导致这个错误的原因是:当从一个控制器复制和粘贴元素到另一个控制器时,Xcode 会在编辑和重新链接该元素到新控制器后仍然保留与原始控制器的链接。<= 这就是我的全部翻译。 - moolsbytheway
显示剩余10条评论

155

有时候这与你的"继承自目标"有关。该值必须设置。对于单个目标应用程序,您只需选择"从目标继承"。如果您有多个目标,请选择所需的目标。

输入图像描述


这个答案对我解决了一个具体的问题。我需要继续处理一个旧的 Obj-C 项目,其中有多个目标。我在 Swift 中创建了一个自定义的 UITableViewCell,但是遇到了相同的错误。通过启用“从目标继承”,问题得以解决。谢谢! - magohamote
该模块并不总是正确设置的;例如,如果在实际创建类之前填写类名。 - Johan
我在填写类名时没有按下“Enter”键,因此IDE没有自动检查此标志。浪费了1个小时在这上面。谢谢。 - MatPag
不确定 @Sergio,也许需要更多的赞。与您的朋友分享! - mrabins
原问题中指出的错误是关于容器的叶控件的,这是早期出现的错误的次要错误。容器没有从目标继承,并出现了如下错误:在 Interface Builder 文件中未知的 CustomUserClass 类。 - JustinC
显示剩余3条评论

129
我在尝试为一个表格实现自定义的ViewCell时遇到了这个错误。当我高亮XIB中的View控制器并将其连接到CellView中的元素时,就会出现“此类不符合键值编码的要求”错误。一旦我删除这些连接,错误就消失了。
请删除下面图像中的连接。 当高亮File Owner时,请在检查器中删除连接 只需确保您仅拥有与表格视图单元格相关的连接。要检查,请单击表格视图单元格,在检查器中查找您的连接。 在高亮表格视图单元格时,连接应该在这里

5
这对我有用,非常感谢。当左列中选择了“文件所有者”时,我取消了连接,然后选择了我的自定义单元格并重新连接它们。成功! - Rogare
即使使用Xcode7,这也可以工作,只需使用右侧面板“连接检查器”。从tableviewcell和标签中删除outlet,然后重新添加它,一切都应该正常工作。 - lifeisfoo
8
这个方法可行,但需要确保 FileOwner 没有被设置过!文件所有者应该保持为 NSObject。 - devjme
相同的答案救了我两次! - wm.p1us
1
请问有人能告诉我将类名称设置为 File's Owner 和直接设置为 UIView 之间的区别是什么? - lee

124

我必须从模拟器/ iPhone 中删除该应用程序以解决此错误。


2
这个解决方法对我很有效。我正在清理一些使用IB的代码。当我从代码中删除了一个按钮时,即使在nib文件中根本没有引用这个按钮(至少我没有看到),错误仍然不断地出现。 - SundayMonday
2
如果你需要调试两个恰好同名的应用程序,我认为这是必要的。 - Anton
是的,似乎XIB中的某些内容被缓存在模拟器上,这对于测试升级而言非常麻烦,因为你实际上并不想删除旧应用。 - Carlos P
我曾经遇到过删除XIB文件的问题,但现在已经解决了。 - balboa
5
如果删除应用程序无效,尝试删除XCode的DerivedData文件夹,这可能会缓存不正确的xib文件。打开XCode -> 首选项 -> 路径 -> 打开DerivedData文件夹并将其拖到回收站中。 - Philip Fung

68

如果这是一个仅适用于iPhone的应用程序而不是通用应用程序,请确保以下字段为空:

Targets > Summary > iPhone/iPod Deployment Info > Main Interface

如果您在那里指定了xib文件,它会导致崩溃。


2
没错,对我来说就是这样。在试图添加一个新的启动视图控制器时,我将其设置为了新的类/接口文件。在连接视图输出后,我遇到了这个错误。清除该字段后问题得到解决。 - terriblememory
这对我有用。请注意,为了使其工作,我还必须从设备/模拟器中删除旧版本。 - jimt
谢谢 - 这正是我的问题。我已经重命名了我的iPad故事板文件,但没有在项目的首选项中更新。 - RobertJoseph
2
谢谢!这对我解决了问题。(在将主界面字段更改为空后,我不得不从模拟器中删除应用程序。仅更改该字段并不能强制模拟器清除缓存。) - snipe
我记得我将应用程序从通用应用更改为仅限 iPhone 应用程序,这解决了错误! - Justin
这是我的解决方案。 - Teofilo Israel Vizcaino Rodrig

64

这个错误表示已连接的Interface Builder对象在其拥有者的源代码(文件所有者)中被删除/重命名。

如果在Interface Builder中看到感叹号,请在“文件所有者”上进行控制-单击以修复该问题。

如下图所示,“aRemovedView”的右侧有一个感叹号,因为我在已将其连接到IB时删除了IBOutlet视图对象。

enter image description here

这会导致以下错误:Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key aRemovedView.'。


谢谢!这个解决了我的问题。我一直遇到这个问题很长时间了,除了从头开始重新做之外,不知道该怎么解决。原来是因为在视图控制器中删除了IBOutlets,但不知道它们仍然被引用/链接到所有者(在这种情况下是界面构建器中的“View Controller” - Xcode 6)。 - Ira Herman

45

我曾遇到同样的问题,虽然TechZen的回答确实很棒,但我发现很难适用于我的情况。

最终,我通过将标签通过“对象”下的控制器(如下图所示)链接而不是通过“文件拥有者”解决了该问题。

希望这能帮到你。

输入图像描述


41

就我而言,这是故事板源代码中的一个错误,请按照以下步骤操作:

  1. 首先将您的故事板打开为源代码。
  2. 搜索<connections>
  3. 删除不需要的连接。

例如:

<connections>
    <outlet property="mapPostsView" destination="4EV-NK-Bhn" id="ubM-Z6-mwl"/>
    <outlet property="mapView" destination="kx6-TV-oQg" id="4wY-jv-Ih6"/>
    <outlet property="sidebarButton" destination="6UH-BZ-60q" id="8Yz-5G-HpY"/>
</connections>

正如你所看到的,这些是你的代码变量名称和故事板布局 XML 标签之间的连接关系 😉


36

enter image description here enter image description here

我的解决方法与Gerard Grundy的类似。在使用XIB创建自定义UITableViewCell时,我错误地将Custom Class名称应用于File's Owner而不是UITableViewCell。在画布上将类应用于UITableViewCell,并将我的IBOutlet属性连接到它即可解决此问题。


Ayyy dag nab it... 真不敢相信我犯这个错误的频率有多高。谢谢笑。 - Benjamin
这对我也起作用了,但是我看过的所有教程都说要将文件的所有者设置为类而不是根视图。我很困惑为什么在某些情况下可以工作,而在其他情况下则不行? - Kevin DiTraglia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接