可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I tried adding an interface controller to a storyboard, setting its Custom Class to a WKInterfaceController subclass, launched the app in the simulator and navigated to the specified interface controller.
When I do so, I get the following error:
WatchKit error - unable to find interface controller class 'TestController' to instantiate
If I try to interact with the controller (e.g. try launching its button's action), I get the following error:
- *********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
- *********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:7120004 not found
I tried setting the module name as recommended on this answer, but that still gives me the following errors:
- WatchKit error - unable to find interface controller class '_TtC29myWatchApp_WatchKit_App19TestController' to instantiate
- *********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
- *********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:6E20004 not found
回答1:
I got this error after renaming the WatchKit target, but finally realized: if you rename your WatchKit targets, you'll have to go through the interfaces in Interface Builder and make sure the module names for each of them is renamed as well.
You can do this by selecting an interface controller, clicking the Identity Inspector (or command-option-3), delete the module name, then tab away. It will automatically be filled in with the new target name. That did it for me!
回答2:
This error came up for me because I was not properly handling the didDeactivate
message. My deactivated controller was still receiving messages via MMWormhole
. Once I severed that connection, the error went away. It turns out that in the simulator all the deactivated interface controllers hang around in memory, so you have to carefully make sure they don't get any more messages of any kind. I don't know if this happens on the Watch itself, but of course we should assume so.
回答3:
I spent way too much time with this issue, but finally figured what it was.
The Apple Watch has basically two navigation patterns:
Hierarchical:
[self pushControllerWithName:@"controllerName" context:nil];
Page-based:
[[self class] reloadRootControllersWithNames:@[@"controller1",@"controller2"] contexts:nil];
According to apple:
You cannot combine hierarchical and page-based interface styles. At design time, you must choose the style that best suits your app’s content and design for that style.
So, the issue is that I was mixing both and that leads to undefined behavior like:
*********** ERROR -[SPRemoteInterface _interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:(null) not found
Hope this helps other developers
EDIT:
Just a suggestion that worked for me as a workaround, when using Page-based navigation you can still present modal controllers (just saying):
[self presentControllerWithName:@"controllerName" context:nil];
回答4:
This bug seems to be closely related to this one: Unable to see custom classes in Interface Builder drop down.
When I originally tried solving this, I had to manually type in the module name since the drop down was empty for both the custom classes and the module names.
Examining the storyboard's source code reveals one workaround.
Interface controllers that work look like this:
<controller id="AgC-eL-Hgc" customClass="InterfaceController"
customModule="myWatchApp_WatchKit_App" customModuleProvider="target">
Interface controllers that don't work lack the customModule
and/or the customModuleProvider
attribute(s).
Therefore, a workaround is to manually add those missing attributes to the storyboard file by right-clicking it and choosing Open As > Source Code.
A longer-term solution may be to fix the storyboard so that custom classes appear in the drop downs (see linked question for some potential fixes).
Update:
Other interface controllers that also work use customModule="myWatchApp_WatchKit_Extension"
(notice the _Extension
vs. _App
difference) and don't need the customModuleProvider
attribute.
回答5:
For me, this appears to be a false negative. I tried all suggested solutions, but then proved it's an Apple error by creating a brand new Apple Kit project, making one change to the Glance (adding an image) and getting the error. I've logged the following error with Apple in their Bug Reporter.
Title
Receive clientIdentifier for interfaceControllerID not found when
navigating to Glance
Description
I receive the following error which appears to be a false negative
when navigating to a Glance in a watchOS 2.0 project. I reproduced
this by creating a brand new Apple Kit project, making one change to
the Glance (adding an image) and getting the error.
Steps to reproduce
- Clear all data in both watch and iOS simulators.
- In XCode, create a new WatchKit application including complication and glance.
- Run and see no issues.
- Add a png to your image assets.
- Add a UIImageView to the Glance in Interface Builder.
- Run the extension in the watch simulator.
- Enable the Glance in the iOS Watch companion app.
- Navigate to the Glance in the watch simulator.
- Note the follow error in your log.
2015-07-16 08:35:10.663 restaurant-reports WatchKit App
Extension[78301:2211560] *********** ERROR -[SPRemoteInterface
_interfaceControllerClientIDForControllerID:] clientIdentifier for interfaceControllerID:3118001E not found
Expected result
No false negatives should appear in log
Actual result
False negative appears in log
Watch OS version (build)
2.0 (13S5293f)
They gave me bug id 21853566.
回答6:
I think you forgot to use the storyboardID to your class. That's what i get from your error.
回答7:
I had this problem when I renamed the WatchKit target. When I renamed it back the error went away.
回答8:
The better way to do a push/pop controller is running that piece of code into the main thread so:
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 documentation says about the three methods:
Always call this method from your WatchKit extension’s main thread.
回答9:
You need to verify the view controller is in your compile source here: Select Project > Select Watchkit Extension Target > Build Phases > Compile Sources
回答10:
It's not anything you're doing wrong. This is already a known issue. See my answer here. Please dupe the following radar on Apple's Bug Reporting System to help raise the priority to get this fixed.
回答11:
I was having same issues after the recent 8.2 release. I had to go to each one of my InterfaceControllers and adjust its custom class module to whatever was shown as an option or "none".
回答12:
I had this problem when I mistakenly set root interface controller's identifier. When I remove the identifier, this warning disappeared.
回答13:
The controller’s Module name should be the same name as your Project’s root name (top left blue Xcode document icon name).
Your dynamic interface’s module name should be that same name and your destination controller’s module name (i.e. the one you're pushing to) should also be the same name.
Btw, in case you’re new or not sure I thought I’d throw this in because you might be thinking your class is wrong or something. Your Dynamic Interface Controller doesn’t have to point to the default Xcode NotificationController.swift class. Of course you can create a custom class i.e. FriendRequestNotificationController
To troubleshoot you can add this code into awakeWithContext method to see what controllers have what IDs.
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
if let vcID = self.valueForKey("_viewControllerID") as? NSString {
print("Controller: \(vcID)")
}
// Configure interface objects here.
}
回答14:
- If you are using page-based navigation (from where you are handling
push or presenting a new view controller) then please present
the new controller instead of pushing it.
- Since first screen which if page based (like page view controller)
screens, then it by default uses pushing of next page or previous
page on swiping left and right and it becomes root window view of
your WatchKit app. In this case if you push another controller on
click from inside controls then it will not recognise the push but
it will recognise present new controller. Hence please do follow
the rules if possible.