我正在使用Xamarin开发Apple Watch应用程序。我添加了一个表(WKInterfaceTable)并用代码隐藏填充它。但是当我点击一行时,应用程序会立即崩溃。
为了实现这一目标,我实际上手动编辑了故事板XML文件,因为只需在故事板上拖放表就无法工作。这是XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="6221" systemVersion="14A389" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="AgC-eL-Hgc">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6213"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="3734"/>
</dependencies>
<scenes>
<!--Interface Controller-->
<scene sceneID="aou-V4-d1y">
<objects>
<controller id="AgC-eL-Hgc" title="Favorites" customClass="InterfaceController" customModuleProvider="">
<items>
<table alignment="left" id="nXC-Mh-TYy">
<items>
<tableRow identifier="default" id="zJA-dk-zIT" customClass="FavoriteRowController">
<group key="rootItem" width="1" height="40" alignment="left" spacing="6" id="ASs-9x-fCK">
<items>
<imageView width="35" height="35" alignment="left" verticalAlignment="center" image="Door" id="rac-gq-1kM"/>
<label alignment="left" verticalAlignment="center" text="Location" id="jkO-KQ-vGr"/>
</items>
<color key="backgroundColor" red="0.93625843524932861" green="0.94465947151184082" blue="0.98500943183898926" alpha="0.14000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
<edgeInsets key="margins" left="2" right="2" top="2" bottom="2"/>
</group>
<connections>
<outlet property="RowLabel" destination="jkO-KQ-vGr" id="Hcb-P2-F5Q"/>
</connections>
</tableRow>
</items>
</table>
</items>
<connections>
<outlet property="InterfaceTable" destination="nXC-Mh-TYy" id="4YS-uT-eWw"/>
</connections>
</controller>
</objects>
<point key="canvasLocation" x="0.0" y="0.0"/>
</scene>
</scenes>
我在XML中出了什么问题吗?
InterfaceController
的代码:
public partial class InterfaceController : WKInterfaceController
{
protected InterfaceController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void Awake(NSObject context)
{
base.Awake(context);
this.LoadTableData();
// Configure interface objects here.
Console.WriteLine("{0} awake with context", this);
}
public override void WillActivate()
{
// This method is called when the watch view controller is about to be visible to the user.
Console.WriteLine("{0} will activate", this);
}
public override void DidDeactivate()
{
// This method is called when the watch view controller is no longer visible to the user.
Console.WriteLine("{0} did deactivate", this);
}
private void LoadTableData()
{
var cityNames = new[] { "r1", "r2", "r3", "r4", "r5" };
InterfaceTable.SetNumberOfRows(cityNames.Length, "default");
for (var i = 0; i < cityNames.Length; i++)
{
var row = (FavoriteRowController)InterfaceTable.GetRowController(i);
row.RowLabel.SetText(cityNames[i]);
}
}
}
InterfaceController.designer.cs
的代码:
[Register("InterfaceController")]
partial class InterfaceController
{
[Outlet]
public WKInterfaceTable InterfaceTable { get; set; }
void ReleaseDesignerOutlets()
{
if (InterfaceTable != null)
{
InterfaceTable.Dispose();
InterfaceTable = null;
}
}
}
FavoriteRowController
的代码:
public partial class FavoriteRowController : WKInterfaceController
{
protected FavoriteRowController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void Awake(NSObject context)
{
base.Awake(context);
// Configure interface objects here.
Console.WriteLine("{0} awake with context", this);
}
public override void WillActivate()
{
// This method is called when the watch view controller is about to be visible to the user.
Console.WriteLine("{0} will activate", this);
}
public override void DidDeactivate()
{
// This method is called when the watch view controller is no longer visible to the user.
Console.WriteLine("{0} did deactivate", this);
}
}
FavoriteRowController.designer.cs
的代码:
[Register("FavoriteRowController")]
partial class FavoriteRowController
{
[Outlet]
public WKInterfaceLabel RowLabel { get; set; }
void ReleaseDesignerOutlets()
{
}
}
应用程序输出中崩溃的例外:
2016-11-03 10:10:58.780 MyAppWatchExtension[16255:474000] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<FavoriteRowController 0x799ec7e0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key InterfaceTable.'
*** First throw call stack:
(
0 CoreFoundation 0x00383a22 __exceptionPreprocess + 194
1 libobjc.A.dylib 0x059a0e76 objc_exception_throw + 52
2 CoreFoundation 0x00383951 -[NSException raise] + 17
3 Foundation 0x013c5732 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 238
4 Foundation 0x012eac53 _NSGetUsingKeyValueGetter + 146
5 Foundation 0x012eab3b -[NSObject(NSKeyValueCoding) valueForKey:] + 282
6 WatchKit 0x04b06c16 __58-[SPRemoteInterface handlePlistDictionary:fromIdentifier:]_block_invoke.882 + 39
7 libdispatch.dylib 0x06252c4f _dispatch_call_block_and_release + 15
8 libdispatch.dylib 0x0627550f _dispatch_client_callout + 14
9 libdispatch.dylib 0x0625be31 _dispatch_main_queue_callback_4CF + 1031
10 CoreFoundation 0x00343e7e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
11 CoreFoundation 0x00306dcf __CFRunLoopRun + 2319
12 CoreFoundation 0x0030624b CFRunLoopRunSpecific + 395
13 CoreFoundation 0x003060ab CFRunLoopRunInMode + 123
14 Foundation 0x012c5192 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 308
15 Foundation 0x012c504f -[NSRunLoop(NSRunLoop) run] + 69
16 libxpc.dylib 0x0656d8a5 _xpc_objc_main + 476
17 libxpc.dylib 0x06570175 xpc_main + 215
18 Foundation 0x01323880 +[NSXPCListener serviceListener] + 0
19 PlugInKit 0x111556b6 -[PKService run] + 954
20 WatchKit 0x04b43108 main + 148
21 libxamarin-debug.dylib 0x0584fb33 xamarin_main + 3475
22 TycoMobilePassUIiOSWatchExtension 0x001055bc xamarin_watchextension_main + 124
23 libdyld.dylib 0x062ae85d start + 1
24 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
答案 0 :(得分:1)
如果在选择项目时发生崩溃而不是在显示表格时发生,那么我会假设它与行选择代码有关,并且会从那里开始。
这里有两个选项,取决于您尝试做什么:
<强> DidSelectRow 强>
在选择行并且您想要操作某些数据或移动到另一个视图时使用。
public override async void DidSelectRow(WKInterfaceTable table, nint rowIndex)
{
var contextForNextInterfaceController = rows[(int)rowIndex]; // this depends how you have set up the table.
Console.WriteLine($"Row selected: {rowData}");
PushController("TheNextInterFaceController", contextForNextInterfaceController);
}
<强> GetContextForSegue 强>
在iOS Designer或Xcode中设置segue时使用,以便为正在使用的下一个接口控制器设置上下文。
public override NSObject GetContextForSegue(string segueIdentifier, WKInterfaceTable table, nint rowIndex)
{
// Can check segueIdentifier if using more segues
return new ContextForNextInterfaceController() // This needs to sub class NSObject
{
model = modelForNextInterfaceController,
};
}
在设置上下文后移动到另一个视图时,您将neext来转换上下文对象并检查它是否是您要查找的类型:
public override void Awake(NSObject context)
{
base.Awake(context);
Console.WriteLine("{0} awake with context", this);
var currentContext = context as ContextForNextInterfaceController;
if (currentContext != null)
{
// Do stuff with context
}
}
如果您可以发布您的Interface Controller代码或行选择代码,那么我可以提供更多帮助。此外,如果您在应用程序输出中收到任何可能有用的错误。
=============================================== ============================ 的更新强>
从你的错误输出中我可以说它FavoriteRowController
错过了故事板中设置的插座或错误的类。
此类与密钥InterfaceTable不符合密钥值编码。'
当您丢失插座或删除插座但未删除故事板中的链接时,是常见错误。
RowControllers不需要是InterfaceControllers所以我会这样设置:
FavoriteRowController
的代码:
using Foundation;
namespace WatchConnectivity.OnWatchExtension
{
public partial class FavoriteRowController : NSObject
{
protected FavoriteRowController()
{
}
}
}
FavoriteRowController.designer.cs
的代码:
using Foundation;
using System.CodeDom.Compiler;
namespace WatchConnectivity.OnWatchExtension
{
[Register ("FavoriteRowController")]
partial class FavoriteRowController
{
[Outlet]
public WatchKit.WKInterfaceLabel RowLabel { get; set; }
void ReleaseDesignerOutlets ()
{
if (RowLabel != null) {
RowLabel.Dispose ();
RowLabel = null;
}
}
}
}
选中此sample
答案 1 :(得分:1)
我修复了它,因为我的RowController类应该来自NSObject
,而不是WKInterfaceController