c# - 如何在 MonoTouch 中代理 UIKit 委托(delegate)?

标签 c# ios xamarin.ios uikit xamarin

我需要链接到 UIScrollView 的委托(delegate)(它不在我的代码中,我无法控制它)并处理它的一些方法,同时将所有事件传递给前一个委托(delegate)。

我天真的实现是这个代理类:

public class ScrollViewProxyDelegate : UIScrollViewDelegate
{
    private UIScrollViewDelegate _realDelegate;

    public ScrollViewProxyDelegate (UIScrollViewDelegate realDelegate)
    {
        _realDelegate = realDelegate;
    }

    public override void DecelerationStarted (UIScrollView scrollView)
    {
        _realDelegate.DecelerationStarted (scrollView);
    }

    public override void DecelerationEnded (UIScrollView scrollView)
    {
        _realDelegate.DecelerationEnded (scrollView);
    }

    // ...
 }

这没有成功,因为 scrollView.Delegate 我传递给 ScrollViewProxyDelegate 构造函数结果是 null 因为这个特定的委托(delegate)在一个不同的类树。我所追求的属性是 WeakDelegate,但它是一个 NSObject

我读了this我仍然很困惑。我想我可以在每个方法中调用此 NSObject 上的 Objective C 选择器,但是否有更简洁的方法?

更新 1

我刚刚尝试代理 PerformSelectorRespondsToSelector 但它导致无法识别的选择器崩溃。

更新2

好吧,显然 NSProxy is what people use for this .正在调查。

更新3

哎呀,MonoTouch 中没有 NSProxy

更新4

我最终使用 Key Value Observing 来观察我的 View 的 contentOffset。我早该考虑的!尽管如此,我还是很好奇如何在需要时实现代理。

挂接到 View 委托(delegate)的最简单方法是什么?

最佳答案

如果您尝试代理的代理为空,我不能完全理解您对代理的需求,或者您的意思是您需要代理的代理是 ScrollView 的 WeakDelegate?

WeakDelegate 本质上是任何 NSObject,您需要实现的任何方法都必须“导出”以便委托(delegate)的所有者能够调用它们。

[Export("scrollViewDidEndDecelerating:")]
public void MyDecelerationEndedMethod(UIScrollView scrollView)
{
  ...
}

您可以将这样的方法添加到任何 NSObject,例如 View Controller 。如果您需要使用 Wea​​kDelegate 作为代理的主题,您必须查询它以查看它是否响应选择器然后执行选择器 - 我认为这就是您的意思。

但是,我认为您无法编写可以处理任何委托(delegate)的通用代理,因为尽管代理调用了 RespondsToSelector,但它没有调用 PerformSelector - 选择器直接发送到代理,并且不是通过 PerformSelector。您必须编写一个代理来实现与您要代理的委托(delegate)完全相同的方法。

我能想出的最好的办法是如下所示,您必须在其中实现委托(delegate)实现的每个方法。

public class TestProxy : NSObject
{
    private NSObject realDelegate;

    public TestProxy(NSObject realDelegate)
    {
        this.realDelegate = realDelegate;
    }

    public override bool RespondsToSelector(MonoTouch.ObjCRuntime.Selector sel)
    {
        Console.WriteLine("Query : " + sel.Name);
        return this.realDelegate.RespondsToSelector(sel);
    }

    [Export("tableView:didSelectRowAtIndexPath:")]
    public void RowSelected(UITableView tableView, NSIndexPath indexPath)
    {
        // invoke method on realDelegate either by casting to the correct type or by using
        // reflection to find the method that matches the export and pass this method's arguments.
        // which way you implement depends on your needs and what you know about the delegate being
        // proxied - casting would be much faster than reflection.
    }
}

因为您要实现委托(delegate)实现的所有方法,所以 RespondsToSelector 是多余的,不是必需的。

关于c# - 如何在 MonoTouch 中代理 UIKit 委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14791230/

相关文章:

c# - 在 RichTextBox 上绘图

ios - 由于 'private' 级保护 - swift,无法访问“restoreProgress”

testing - 如何运行 mtouch 命令以在模拟器上启动 Xamarin.iOS 应用程序以进行自动化测试?

ios - 从 AppCenter/HockeyApp 分发 Xamarin iOS 应用程序

windows-phone-7 - MvvmCross - 共享多个 View 的 View 模型

c# - 自托管 WCF 服务器和 SSL

C# HttpClient 上传速度慢

c# - 如何在不使用 runat ="hidden"的情况下在 asp .net page_load 中设置 <input type ="server"> 的值

ios - 如何在 RestKit 中映射 JSON 数组

ios - 获取UITableView的最小高度