【问题标题】:Binding issues: extending a class leads method calling itself?绑定问题:扩展类导致方法调用自身?
【发布时间】:2013-04-01 19:14:55
【问题描述】:

我还有一个与绑定有关的问题 (Issues with Bindings: Calling base method on binding class calls override method. Leads to infinite recursion),而且它已经变得很长,所以我想我会从一个包含我目前所知道的最佳信息的新问题开始。

我正在尝试在 MonoTouch 中进行的项目中使用 Cordova。我一直在为 Cordova 制作绑定。

这是我对 Cordova 2.4.0 类的绑定(可在此处获得 https://github.com/apache/cordova-ios/tree/2.4.0/CordovaLib/Classes):(请注意,这不是一个完整的绑定,只是我目前需要的部分

interface CDVScreenOrientationDelegate {
    [Export ("supportedInterfaceOrientations")]
    uint SupportedInterfaceOrientations ();

    [Export ("shouldAutorotateToInterfaceOrientation:")]
    bool ShouldAutoRotateToInterfaceOrientation (UIInterfaceOrientation interfaceOrientation);

    [Export ("shouldAutorotate")]
    bool ShouldAutoRotate ();
}

[BaseType (typeof (UIViewController))]
interface CDVViewController : CDVScreenOrientationDelegate {
    [Export ("webView")]
    UIWebView WebView { get; set; }

    [Export ("pluginObjects")]
    NSMutableDictionary PluginObjects { get; }

    [Export ("pluginsMap")]
    NSDictionary PluginsMap { get; }

    [Export ("settings")]
    NSDictionary Settings { get; }

    [Export ("whitelist")]
    CDVWhitelist Whitelist { get; }

    [Export ("loadFromString")]
    bool LoadFromString { get; }

    [Export ("useSplashScreen")]
    bool UseSplashScreen { get; set; }

    [Export ("activityView")]
    UIActivityIndicatorView ActivityView { get; }

    [Export ("imageView")]
    UIImageView ImageView { get; }

    [Export ("wwwFolderName")]
    string WwwFolderName { get; set; }

    [Export ("startPage")]
    string StartPage { get; set; }

    [Export ("commandQueue")]
    NSObject CommandQueue { get; set; }

    [Export ("commandDelegate")]
    NSObject CommandDelegate { get; set; }

    [Export ("userAgent")]
    string UserAgent { get; }

    [Export ("printMultitaskingInfo")]
    void PrintMultitaskingInfo ();

    [Export ("createGapView")]
    void CreateGapView ();

    [Export ("newCordovaViewWithFrame:")]
    UIWebView NewCordovaView(RectangleF bounds);

    [Export ("javascriptAlert:")]
    void JavascriptAlert (string text);

    [Export ("appURLScheme")]
    string AppUrlScheme ();

    [Export ("parseInterfaceOrientations:")]
    NSArray ParseInterfaceOrientations (NSArray orientations);

    [Export ("supportsOrientation:")]
    bool SupportsOrientation (UIInterfaceOrientation orientation);

    [Export ("getCommandInstance:")]
    NSObject GetCommandInstance (string pluginName);

    [Export ("registerPlugin:withClassName:")]
    void RegisterPluginWithClassName (CDVPlugin plugin, string className);

    [Export ("URLisAllowed:")]
    bool UrlIsAllowed (NSUrl url);

    [Static] [Export ("getBundlePlist:")]
    NSDictionary GetBundlePlist (string plistName);

    [Static] [Export ("applicationDocumentsDirectory")]
    string ApplicationDocumentsDirectory ();

    // The following methods and properties come from UIWebViewDelegate, but we can't do multiple inheritance
    //[Export ("webView:shouldStartLoadWithRequest:navigationType:")]
    //bool ShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType);
}

[BaseType (typeof(NSObject))]
interface CDVWhitelist {
    [Export ("whitelist")]
    NSArray Whitelist { get; }

    [Export ("expandedWhitelist")]
    NSArray ExpandedWhitelist { get; }

    [Export ("allowAll")]
    bool AllowAll { get; }

    [Export ("initWithArray:")]
    IntPtr Constructor (NSArray array);

    [Export ("URLIsAllowed:")]
    bool UrlIsAllowed (NSUrl url);

    [Export ("schemeIsAllowed:")]
    bool SchemeIsAllowed (string scheme);

    [Export ("errorStringForURL:")]
    string ErrorStringForUrl (NSUrl url);
}

[BaseType (typeof(NSObject))]
interface CDVPlugin {
    [Export ("webView")]
    UIWebView WebView { get; set; }

    [Export ("viewController")]
    UIViewController ViewController { get; set; }

    [Export ("commandDelegate")]
    NSObject CommandDelegate { get; set; }

    [Export ("hasPendingOperation")]
    bool HasPendingOperation { get; }

    [Export ("initWithWebView:")]
    CDVPlugin InitWithWebView (UIWebView theWebView);

    [Export ("handleOpenURL:")]
    void HandleOpenUrl (NSNotification notification);

    [Export ("onAppTerminate")]
    void OnAppTerminate ();

    [Export ("onMemoryWarning")]
    void OnMemoryWarning ();

    [Export ("onReset")]
    void OnReset ();

    [Export ("appDelegate")]
    NSObject AppDelegate ();
}

这是使用来自Monotouch Binding Syntax For Protocols 的 miguel.de.icaza 协议。这没有 CDVViewController 也采用的 UIWebViewDelegate

@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{
    @protected
    CDVCommandDelegateImpl* _commandDelegate;
    @protected
    CDVCommandQueue* _commandQueue; 
    NSString* _userAgent;
}

另外,我发现 Rolf Bjarne Kvinge 在 http://monotouch.2284126.n4.nabble.com/Objective-C-protocol-binding-method-not-invoked-td4105828.html 推荐采用 Adopts 语法。不幸的是,我无法让它工作,因为当我尝试构建我的绑定时,它会抱怨无法使System.Type 符合String。但这是一个不同的问题。

当我尝试继承 CDVViewController 时,我遇到了其他问题。具体调用ViewDidLoad后,系统调用我的子类的ShouldAutoRotateToInterfaceOrientation

为了确认这一点,我做了以下操作:

public class WebViewController : CDVViewController
{
    public override bool ShouldAutoRotateToInterfaceOrientation (MonoTouch.UIKit.UIInterfaceOrientation interfaceOrientation)
    {
        Console.WriteLine ("Enter ShouldAutoRotateToInterfaceOrientation");
        var output = base.ShouldAutoRotateToInterfaceOrientation;
        Console.WriteLine ("Leave ShouldAutoRotateToInterfaceOrientation");
        return output;
    }
}

我在ShouldAutoRotateToInterfaceOrientation 中放置了一个断点,当我逐步执行该方法时,当我到达base.ShouldAutoRotateToInterfaceOrientation 时,它只是跳回到此方法的开头,我的调用堆栈现在添加了@987654337 @,但是查看此方法的源代码(可用here),它从不尝试调用自身或子类实现。相反,它在内部调用supportsOrientation:,它会检查一个数组以查看是否支持此方向。

知道supportsOrientation: 无论如何最终都会被调用,我也尝试从ShouldAutoRotateToInterfaceOrientation 调用它,但后来我只是在该方法中得到了奇怪的回调行为。

如果我直接实例化CDVViewController,那么一切似乎都按预期工作,但我需要为我的项目重写一些方法。当我扩展CDVViewController时, 然后这种行为开始发生。

我对此感到很困惑,我无法弄清楚我做错了什么,所以任何帮助将不胜感激。

更新 #1 根据 Rolf 的要求,这里是生成的类。我希望这就是你要找的。由于篇幅原因,我在这里将其添加为 Gist https://gist.github.com/innopal/5288047

【问题讨论】:

  • 你能找到生成的绑定代码并查看/发布它的样子吗?如果您右键单击解决方案并选择查看所有文件,则生成的文件位于某个子目录中(不记得确切的名称,但应该不会花很长时间才能找到它)。
  • 感谢罗尔夫的回复。我在我生成的 DLL 中找到了这些。我希望对 gist.github.com/innopal/5288047 有所帮助
  • 您是使用绑定项目还是手动使用btouch?
  • 我正在手动使用 btouch,使用以下命令 /Developer/MonoTouch/usr/bin/btouch -e Cordova.cs -s Enums.cs AssemblyInfo.cs --out:Cordova.dll --link-with=libcordova.a,libCordova.a。你会推荐一个绑定项目吗?我以github.com/sblom/monotouch-bindings/tree/master/Cordova/Binding 为起点来弄清楚如何绑定东西。
  • 尝试删除“-e”参数。

标签: xamarin.ios xamarin


【解决方案1】:

正如 Rolf 所指出的,这个问题的解决方案是我在我的论点中包含了 -e 标志。

btouch 的帮助中所述,

-e  Generates smaller classes that cannot be subclassed (previously called 'external mode').

所以这里的问题是我在不知不觉中使用了一个专门使类不可子类化的标志,然后尝试对它们进行子类化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2011-05-28
    • 2011-03-01
    • 2020-01-02
    • 1970-01-01
    相关资源
    最近更新 更多