调用PerformSelector时...
var tableView = view.GetAncestors().OfType2<UITableView>().First2();
var indexPath = tableView.IndexPathForCell(view.To<UITableViewCell>());
tableView.SelectRow(indexPath, true, UITableViewScrollPosition.None);
tableView
.PerformSelector(new Selector("delegate"))
.If(_ => _.RespondsToSelector(new Selector("tableView:didSelectRowAtIndexPath:")))
.SafeNav(_ => _.PerformSelector(new Selector("tableView:didSelectRowAtIndexPath:"), tableView, indexPath));
我在ObjCRuntime中得到了这个未知的异常...
Warning (13816) / MonoTouchClient: critical: Stacktrace:
Warning (13816) / MonoTouchClient: critical: at <unknown> <0xffffffff>
Warning (13816) / MonoTouchClient: critical: at (wrapper managed-to-native) ObjCRuntime.Messaging.IntPtr_objc_msgSend (intptr,intptr) <0x00057>
Warning (13816) / MonoTouchClient: critical: at ObjCRuntime.Class.GetClassForObject (intptr) [0x00000] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/ObjCRuntime/Class.cs:134
Warning (13816) / MonoTouchClient: critical: at ObjCRuntime.Runtime.GetNSObject (intptr,ObjCRuntime.Runtime/MissingCtorResolution,bool) [0x00022] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/ObjCRuntime/Runtime.cs:1017
Warning (13816) / MonoTouchClient: critical: at ObjCRuntime.Runtime.GetNSObject (intptr) [0x00000] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/ObjCRuntime/Runtime.cs:1005
Warning (13816) / MonoTouchClient: critical: at Foundation.NSObject.PerformSelector (ObjCRuntime.Selector,Foundation.NSObject,Foundation.NSObject) [0x0006f] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/src/build/ios/native/Foundation/NSObject.g.cs:439
Warning (13816) / MonoTouchClient: critical:
Warning (13816) / MonoTouchClient: critical:
Warning (13816) / MonoTouchClient: critical: 0 MonoTouchClient 0x00083f11 mono_handle_native_sigsegv + 240
Warning (13816) / MonoTouchClient: critical: 1 MonoTouchClient 0x0008ba15 mono_sigsegv_signal_handler + 222
Warning (13816) / MonoTouchClient: critical: 2 libsystem_platform.dylib 0x2203a077 _sigtramp + 42
Warning (13816) / MonoTouchClient: critical: 3 MonoTouchClient 0x007c19d8 wrapper_managed_to_native_ObjCRuntime_Messaging_IntPtr_objc_msgSend_intptr_intptr + 100
Warning (13816) / MonoTouchClient: critical: 4 MonoTouchClient 0x0074c9e0 ObjCRuntime_Class_GetClassForObject_intptr + 44
Warning (13816) / MonoTouchClient: critical: 5 MonoTouchClient 0x0074a89c ObjCRuntime_Runtime_GetNSObject_intptr_ObjCRuntime_Runtime_MissingCtorResolution_bool + 116
Warning (13816) / MonoTouchClient: critical: 6 MonoTouchClient 0x0074a81c ObjCRuntime_Runtime_GetNSObject_intptr + 36
Warning (13816) / MonoTouchClient: critical: 7 MonoTouchClient 0x00770bd0 Foundation_NSObject_PerformSelector_ObjCRuntime_Selector_Foundation_NSObject_Foundation_NSObject + 440
值得注意的是,这只能在具有iOS 9.3.5的iPad 2上重现,而不能在具有iOS 10.1.1的iPad Pro上重现
我没有改变似乎有所作为。有没有人遇到这个或有任何调试技巧?
答案 0 :(得分:1)
Xamarin的PerformSelector
重载需要两个参数,期望选择器返回一个值。
即。
在Xamarin.iOS.Foundation.NSObject
:
public virtual NSObject PerformSelector(Selector aSelector, NSObject object1, NSObject object2);
然后将其发送到尝试编组返回的本机方法。
在问题代码中,表的委托的tableView:didSelectRowAtIndexPath
方法返回void
。因此,本机代码试图编组nil,这导致了错误。
解决方案是为PerformSelector(Selector aSelector, NSObject object1, NSObject object2)
创建自己的重载并自己调用本机方法:
首先,定义原生方法......
public static class MonoTouchNative
{
[DllImport("/usr/lib/libobjc.dylib")]
public static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2, IntPtr arg3);
}
然后,从名为PerformVoidSelector
...
public static void PerformVoidSelector(this NSObject nsObject, Selector aSelector, NSObject object1, NSObject object2)
{
MonoTouchNative.objc_msgSend(
nsObject.Handle,
Selector.GetHandle("performSelector:withObject:withObject:"),
aSelector.Handle,
(object1 != null) ? object1.Handle : IntPtr.Zero,
(object2 != null) ? object2.Handle : IntPtr.Zero);
}
最后,我从应用代码中调用了我的新扩展方法...
tableView
.PerformSelector(new Selector("delegate"))
.If(_ => _.RespondsToSelector(new Selector("tableView:didSelectRowAtIndexPath:")))
.SafeDo(_ => _.PerformVoidSelector(new Selector("tableView:didSelectRowAtIndexPath:"), tableView, indexPath));