如何在 MonoTouch 中代理 UIKit 代表?

Posted

技术标签:

【中文标题】如何在 MonoTouch 中代理 UIKit 代表?【英文标题】:How to proxy UIKit delegates in MonoTouch? 【发布时间】:2013-01-25 07:41:21 【问题描述】:

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

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

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,因为这个特定的委托位于不同的类树中。我追求的属性是WeakDelegate,但它是NSObject

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

更新 1

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

更新 2

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

更新 3

哎呀,在 MonoTouch 中没有 NSProxy

更新 4

我最终使用 Key Value Observing 来观看我的视图 contentOffset。我早该想到的!不过,如果我需要代理,我很好奇如何实现它。

挂钩到视图委托的最简单方法是什么?

【问题讨论】:

【参考方案1】:

如果您尝试代理的委托为空,我无法完全满足您对代理的需求,或者您的意思是您需要代理的委托是滚动视图的 WeakDelegate?

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

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

  ...

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

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

我能想到的最好的方法是如下所示,您必须实现委托实现的每个方法。

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.
    

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

【讨论】:

以上是关于如何在 MonoTouch 中代理 UIKit 代表?的主要内容,如果未能解决你的问题,请参考以下文章

Swift:尝试导入 UIKit 时出错

如何在 MonoTouch 中使用 System.IO.Packaging

如何在 MonoTouch / MonoDevelop / UIBuilder 中插入插座?

如何在 DialogViewController (Monotouch.Dialog) 上设置背景颜色

如何在 MonoTouch 中注册 UIApplicationWillEnterForegroundNotification

如何使用 Monotouch 在 iPad 故事板应用程序中以编程方式管理视图