WatchKit:无法找到接口控制器类

时间:2015-03-16 03:23:41

标签: ios storyboard watchkit

我尝试将一个接口控制器添加到故事板,将其Custom Class设置为WKInterfaceController子类,在模拟器中启动应用程序并导航到指定的接口控制器。

当我这样做时,我收到以下错误:

  

WatchKit错误 - 无法找到接口控制器类'TestController'来实例化

如果我尝试与控制器交互(例如尝试启动其按钮的操作),则会出现以下错误:

  
      
  • *********** ERROR - [SPRemoteInterface _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier :( null)not found
  •   
  • *********** ERROR - [SPRemoteInterface _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier:找不到7120004
  •   

我尝试了setting the module name as recommended on this answer,但这仍然给我以下错误:

  
      
  • WatchKit错误 - 无法找到接口控制器类'_TtC29myWatchApp_WatchKit_App19TestController'来实例化
  •   
  • *********** ERROR - [SPRemoteInterface _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier :( null)not found
  •   
  • *********** ERROR - [SPRemoteInterface _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier:找不到6E20004
  •   

15 个答案:

答案 0 :(得分:34)

重命名WatchKit目标后出现此错误,但最终意识到:如果重命名WatchKit目标,则必须通过Interface Builder中的接口并确保每个接口的模块名称都重命名

您可以通过选择接口控制器,单击Identity Inspector(或命令选项-3),删除模块名称,然后选项卡来完成此操作。它将自动填入新的目标名称。这样做对我来说!

答案 1 :(得分:16)

我遇到了这个错误,因为我没有正确处理didDeactivate消息。我的已停用控制器仍在通过MMWormhole接收消息。一旦我切断了那个连接,错误就消失了。事实证明,在模拟器中,所有已停用的接口控制器都会在内存中闲置,因此您必须仔细确保它们不会再收到任何类型的消息。我不知道手表本身是否会发生这种情况,但我们当然应该这样认为。

答案 2 :(得分:10)

我花了太多时间处理这个问题,但终于想出了它是什么。 Apple Watch基本上有两种导航模式:

分层:

[self pushControllerWithName:@"controllerName" context:nil];

基于页面的:

[[self class] reloadRootControllersWithNames:@[@"controller1",@"controller2"] contexts:nil];

根据苹果:

  

您无法组合分层和基于页面的界面样式。在设计时,您必须选择最适合您应用的内容和风格设计的样式。

所以,问题在于我混合了两者,这导致了未定义的行为,如:

  

*********** ERROR - [SPRemoteInterface _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier :( null)未找到

希望这有助于其他开发者

修改

只是一个对我有用的建议作为解决方法,当使用基于页面的导航时,你仍然可以呈现模态控制器(只是说):

[self presentControllerWithName:@"controllerName" context:nil];

答案 3 :(得分:6)

这个错误似乎与这个错误密切相关:Unable to see custom classes in Interface Builder drop down

当我最初尝试解决此问题时,我不得不手动输入模块名称,因为自定义类和模块名称的下拉列表都是空的。

检查故事板的源代码揭示了一种解决方法。

工作的接口控制器如下所示:

<controller id="AgC-eL-Hgc" customClass="InterfaceController" 
  customModule="myWatchApp_WatchKit_App" customModuleProvider="target">

不起作用的接口控制器缺少customModule和/或customModuleProvider属性。

因此,解决方法是通过右键单击并选择打开为&gt;手动将这些缺少的属性添加到情节提要文件中。源代码

更长期的解决方案可能是修复故事板,以便自定义类出现在下拉列表中(有关可能的修复,请参阅linked question)。

<强>更新

其他可以使用customModule="myWatchApp_WatchKit_Extension"的接口控制器(注意_Extension_App的区别)并且不需要customModuleProvider属性。

答案 4 :(得分:3)

对我而言,这似乎是假阴性。我尝试了所有建议的解决方案,但随后通过创建一个全新的Apple Kit项目证明了它是一个Apple错误,对Glance进行了一次更改(添加图像)并获得错误。我在他们的Bug Reporter中记录了以下与Apple的错误。

标题

  

接收未找到interfaceControllerID的clientIdentifier   导航到Glance

描述

  

我收到以下错误,似乎是误报   在watchOS 2.0项目中导航到一览。我转载   通过创建一个全新的Apple Kit项目,进行一次更改   浏览(添加图像)并获取错误。

重现的步骤

  
      
  1. 清除手表和iOS模拟器中的所有数据。
  2.   
  3. 在XCode中,创建一个新的WatchKit应用程序,包括复杂性和一瞥。
  4.   
  5. 运行,看不出任何问题。
  6.   
  7. 将png添加到图片资源。
  8.   
  9. 在Interface Builder中添加UIImageView。
  10.   
  11. 在手表模拟器中运行扩展程序。
  12.   
  13. 在iOS Watch配套应用中启用Glance。
  14.   
  15. 导航到手表模拟器中的Glance。
  16.   
  17. 请注意日志中的跟随错误。
  18.         

    2015-07-16 08:35:10.663 restaurant-reports WatchKit App   Extension [78301:2211560] *********** ERROR - [SPRemoteInterface   _interfaceControllerClientIDForControllerID:] interfaceControllerID的clientIdentifier:3118001E未找到

预期结果

  

日志

中不应出现任何误报

实际结果

  

日志中出现假阴性

观看操作系统版本(构建)

  

2.0(13S5293f)

他们给了我错误ID 21853566。

答案 5 :(得分:2)

我想你忘了在课堂上使用storyboardID了。这是我从你的错误中获得的。

enter image description here

答案 6 :(得分:2)

当我重命名WatchKit目标时,我遇到了这个问题。当我重新命名它时,错误就消失了。

答案 7 :(得分:2)

执行push / pop控制器的更好方法是将这段代码运行到主线程中,这样:

dispatch_async(dispatch_get_main_queue(), ^{
     [self pushControllerWithName:@"controllerIdentifier" context:data];
});

dispatch_async(dispatch_get_main_queue(), ^{
     [self popToRootController];
});

dispatch_async(dispatch_get_main_queue(), ^{
     [self popController];
});

Apple文档说明了这三种方法:

  

始终从WatchKit扩展程序的主线程中调用此方法。

答案 8 :(得分:1)

您需要在此处验证视图控制器是否在您的编译源中:选择项目&gt;选择Watchkit Extension Target&gt;构建阶段&gt;编译来源

答案 9 :(得分:1)

我能够通过从我的didSet中删除IBOutlet个观察者来解决此问题。 tymac的故障排除代码很有帮助。似乎接口元素尚不可用,因为didSetawake(withContext:)之前被调用。

答案 10 :(得分:0)

这不是你做错了什么。这已经是一个已知问题。请参阅我的回答here。请在Apple的radar上填写以下Bug Reporting System,以帮助提高优先级以解决问题。

答案 11 :(得分:0)

在最近的8.2发布之后,我遇到了同样的问题。我必须转到我的每个InterfaceControllers并将其自定义类模块调整为显示为选项或&#34;无&#34;的任何内容。

答案 12 :(得分:0)

当我错误地设置根接口控制器的标识符时,我遇到了这个问题。当我删除标识符时,此警告消失。

enter image description here

答案 13 :(得分:0)

控制器的模块名称应与项目的根名称相同(左上角的蓝色Xcode文档图标名称)。

enter image description here

您的动态界面的模块名称应该是相同的名称,目标控制器的模块名称(即您要推送的名称)也应该是相同的名称。

顺便说一句,如果你是新手或者不确定我以为我会把它扔进去,因为你可能认为你的班级错了什么的。您的动态接口控制器不必指向默认的Xcode NotificationController.swift类。当然,您可以创建一个自定义类,即FriendRequestNotificationController

要进行故障排除,您可以将此代码添加到awakeWithContext方法中,以查看哪些控制器具有哪些ID。

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)
    if let vcID = self.valueForKey("_viewControllerID") as? NSString {
        print("Controller: \(vcID)")
    }

    // Configure interface objects here.
}

答案 14 :(得分:0)

  • 如果您使用的是基于页面的导航(从您处理的位置) 推送或展示新的视图控制器)然后请出现 新控制器而不是推送它。
  • 从第一个屏幕开始,如果基于页面(如页面视图控制器) 屏幕,然后它默认使用下一页或上一页的推送 左右滑动的页面,它成为根窗口视图 你的WatchKit应用程序。在这种情况下,如果你推送另一个控制器 从内部控件中单击然后它将无法识别push 但是 它将识别当前的新控制器。因此,请遵循 如果可能的规则。