MonoTouch绑定ObjectiveC库不起作用

4

头文件 .h:

#import <Foundation/Foundation.h>

typedef enum _XLBadgeManagedType {
    XLInboxManagedMethod = 0,
    XLDeveloperManagedMethod = 1
} XLBadgeManagedType ;


@interface XLXtifyOptions :NSObject
{
    NSString *xoAppKey;
    BOOL    xoLocationRequired ;
    BOOL    xoBackgroundLocationRequired ;
    BOOL    xoLogging ;
    BOOL    xoMultipleMarkets;
    XLBadgeManagedType xoManageBadge;
}
+ (XLXtifyOptions *)getXtifyOptions;
- (NSString *)getAppKey ;
- (BOOL) isLocationRequired;
- (BOOL) isBackgroundLocationRequired ;
- (BOOL) isLogging ;
- (BOOL) isMultipleMarkets;
- (XLBadgeManagedType)  getManageBadgeType;
- (void)xtLogMessage:(NSString *)header content:(NSString *)message, ...;
@end

.m文件:

#import "XLXtifyOptions.h"
#import "XtifyGlobal.h"

static  XLXtifyOptions *xXtifyOptions=nil;

@implementation XLXtifyOptions

+ (XLXtifyOptions *)getXtifyOptions
{
    if (xXtifyOptions==nil) {
        xXtifyOptions=[[XLXtifyOptions alloc]init];
    }
    return xXtifyOptions;
}

-(id)init
{
    if (self = [super init]) {        
        xoAppKey=xAppKey;
        xoLocationRequired=xLocationRequired;
        xoBackgroundLocationRequired=xRunAlsoInBackground ;
        xoLogging =xLogging ;
        xoMultipleMarkets=xMultipleMarkets;
        xoManageBadge=xBadgeManagerMethod;

    }
    return self;
}

- (NSString *)getAppKey
{
    return xoAppKey;
}
- (BOOL) isLocationRequired
{
    return xoLocationRequired;
}
- (BOOL) isBackgroundLocationRequired 
{
    return xoBackgroundLocationRequired;
}
- (BOOL) isLogging 
{
    return xoLogging;
}
- (BOOL) isMultipleMarkets
{
    return xoMultipleMarkets;
}
- (XLBadgeManagedType)  getManageBadgeType
{
    return xoManageBadge;
}
- (void)xtLogMessage:(NSString *)header content:(NSString *)format, ... {
    va_list args;
    va_start(args, format);
    if (xoLogging) {
        NSString *prettyFmt=[NSString stringWithFormat:@"%@ %@", header,format];
        NSLogv(prettyFmt, args);
    }
    va_end(args);
}
@end

Global.h:

#define xAppKey @"abc123"

#define xLocationRequired NO

#define xRunAlsoInBackground FALSE    

#define xBadgeManagerMethod XLInboxManagedMethod 

#define xLogging TRUE

#define xMultipleMarkets FALSE

我的绑定定义:

[BaseType (typeof (NSObject))]
public interface XLXtifyOptions {

    [Static]
    [Export ("xtifyOptions")]
    XLXtifyOptions Options { get;}

    [Export ("getAppKey")]
    string GetAppKey ();

    [Export ("isLocationRequired")]
    bool IsLocationRequired ();

    [Export ("isBackgroundLocationRequired")]
    bool IsBackgroundLocationRequired ();

    [Export ("isLogging")]
    bool IsLogging ();

    [Export ("isMultipleMarkets")]
    bool IsMultipleMarkets ();

    [Export ("getManageBadgeType")]
    XLBadgeManagedType GetManageBadgeType ();

    //      [Export ("xtLogMessage:content:...")]
    //      void XtLogMessagecontent... (string header, string message,, );
    //      
}

以下返回 null:

XLXtifyOptions.Options;
new XLXtifyOptions().GetAppKey();

厂商的入门指南:

要开始使用,请按照以下步骤操作:

  XLXtifyOptions *anXtifyOptions=[Options getVendorOptions];
  [[TheirClass get ]initilizeXoptions:anVendorOptions];

我匆忙地尝试重命名一些东西,因为我不确定可以粘贴供应商代码的程度,所以希望没有混淆问题。
这与以下相关:Binding #define used as constant 更多信息:
如果我在设备上运行而不是模拟器上运行这个程序,我会得到以下错误:
Unhandled managed exception: Wrapper type 'XtifyPush.XLXtifyOptions' is missing its native ObjectiveC class 'XLXtifyOptions'. 

编辑

关于@Stephane的问题:我更新了代码,不再隐藏供应商。我绑定的是:http://developer.xtify.com/display/sdk/Getting+Started+with+Apple+Push+Notification+Service,顺便说一下。我已经按照您的建议更新了getXtifyOptions的引用,但结果仍然相同。我已经尝试使用您提到的github库,但我会继续探索。

我正在处理的绑定可以在此处找到:https://github.com/lordscarlet/monotouch-bindings/tree/master/Xtify

4个回答

3
简而言之,Options类没有被编译。我查看了您的项目和要绑定的功能。它看起来有两个部分:已预编译的嵌入式框架以及一些其他东西(主要是Options类),包括设置AppKey的.h文件,您需要在应用程序中进行编译。除非您创建一个最小的xcode项目并公开AppKey的setter,否则无法使绑定工作。另一种选择是放弃该部分并完全在C#中实现XLXtifyOptions,然后您需要自己设置AppKey。更新:编译后的嵌入式框架的某些api调用将Options作为参数,因此如果您仅在C#中定义Options,请确保为Options.h文件中定义的每个函数或属性添加Export属性。希望这可以帮助您理解我的意思。

如果我实现自己的XLXtifyOptions,那么我的绑定是否足够支持其余功能? - Doug Moore
我不确定我理解你的更新——[Export]部分是否会与我创建的类有所关联? - Doug Moore
制作最小化的Xcode应用可能是目前为止最简单的方法,至少根据我的理解是这样的。在这种情况下,我需要为Options.h文件中的每个内容都设置一个setter,对吗? - Doug Moore
如果我能够导出XtifyGlobal.h,那么这会完全解决我的问题吗? - Doug Moore
但你不能导出它。如果是我,我会使用C#创建选项,我非常有信心那样会最好。让我添加第三个答案。 - Stephane Delcroix

3
< p > getVendorOptions 的正确绑定应该是这样的:

[Static]
[Export ("vendorOptions")]
Options Options { get;}

“get”部分和大写是按照惯例完成的。查看生成的代码。只要将GetAppKey绑定为方法而不是属性,就可以使用它了。请注意,它不应返回null,而应抛出异常。

关于

MyNamespace.Current;

我没有看到任何定义,因此我不知道出了什么问题。

在这个阶段,我对您如何构建本地库并将其包含在托管库中(有关设备上的异常)有一些担忧。确保您正在正确地进行操作,查看https://github.com/mono/monotouch-bindings中的大量示例。


那看起来也没有解决它。我将努力将所有内容放到GitHub上,以便有人愿意查看绑定的全部范围,并尝试确定问题是否明显。非常感谢你迄今为止的帮助! - Doug Moore
确实很有帮助,拥有你的东西可用。 - Stephane Delcroix
https://github.com/lordscarlet/monotouch-bindings/tree/master/Xtify 应该可以让您像我一样进行绑定和构建。谢谢! - Doug Moore
我将着手组建一个项目,但我只是在AppDelegate中进行这个操作:public AppDelegate () { var xOptions = XLXtifyOptions.Options; var yOptions = new XLXtifyOptions (); XLappMgr.Current.InitializeXoptions (xOptions); } - Doug Moore
在创建示例代码时,我遇到了“无法加载文件或程序集'XtifyPush.dll'或其某个依赖项。系统找不到指定的文件。” 我已经包含了dll文件,所以我不知道是否有什么问题与dll有关,但这可能是一个迹象。我相信所有本地内容都应该编译到dll中,对吗? - Doug Moore
"无法加载: 确保您的 Xamarin.iOS 已更新。我知道最近更改了 monotouch.dll 的签名。" - Stephane Delcroix

3

如果您需要构建自己的托管选项类,则可以按照以下方式进行操作(在Extra.cs文件中)。

public class XLXtifyOptions : NSObject {
    static XLXtifyOptions options;
    [Export ("getXtifyOptions")] //not sure that one will be ever called by obj-C code
    public static XLXtifyOptions XtifyOptions () {
        return options ?? (options = new XLXtifyOptions () {
            appKey = "yourappkey",
        });
    }

    string appKey;

    [Export ("getAppKey")]
    public string GetAppKey () {
        return appKey;
    }

    //same for all the getters

    [Export ("getManageBadgeType")
    public XLBadgeManageType GetManageBadgeType () {
        return manageBadge;
    }

    //Have to check if this is the right way to bind method with variable lengths argument, but that's the idea
    [Export ("xtLogMessage:content:")]
    public void LogMessage (string header, params string[] message)
    {
        //print the message
    }
}

public enum XLBadgeManageType {
    Inbox,
    Developer
}

这应该能给你一个想法...

到目前为止看起来很不错,我的唯一问题是另一个被绑定的类调用了XLXtifyOptions。我已经在Xamarin中设置了这个绑定项目,但它无法编译,因为它看不到extra.cs中的我的类。[Export("initilizeXoptions:")] void InitializeXoptions(XLXtifyOptions xOptions);编辑:如果我使用btouch也会遇到同样的问题:XtifyLib.cs(99,42): error CS0246: 无法找到类型或命名空间名称“XLXtifyOptions”。您是否缺少using指令或程序集引用? - Doug Moore
我认为你的回答非常有帮助,但我可能存在一些更大的问题。在设备上,我对var x = new XLappMgr();得到了一个非常类似的错误:“未处理的托管异常:包装器类型'XtifyPush.XLappMgr'缺少其本机ObjectiveC类'XLappMgr'。” - Doug Moore
基于你之前的回答,我认为XLappMgr和XLXtifyOptions有同样的问题。它是一个.h文件,因此不会被编译进代码中。这是否意味着我需要像处理选项一样,在C#中自己编写它? - Doug Moore
好的,那么我仍然需要找出为什么会出现“Wrapper type missing”错误。非常感谢您的所有帮助。 - Doug Moore
取消Option的绑定,使用我们刚刚讨论过的托管版本,异常就会消失。 - Stephane Delcroix
显示剩余5条评论

2
首先,这个API的设计很糟糕,它依赖于#define预处理指令进行初始配置,例如ApiKey,在头文件中有大量空格等问题。
您可以在这里找到一个绑定项目,请测试它并告诉我是否解决了您的问题。

https://dl.dropbox.com/u/2058130/random%20stuff/XtifyLib.zip


您的绑定上未设置API密钥。
在SDK头文件中,您会找到XLXtifyOptions.hXLXtifyOptions.m。这意味着XLXtifyOptions类不存储在静态XtifyPush中,因此我取出了这两个文件,稍作修改,创建了另一个静态fat(ARMv7、ARMv7s和i386)库,称为libXtifyLibHelper.a
此库包含两个帮助器Objective-C消息getXtifyOptionsWithAppKey:locationRequired:backgroundLocationRequired:logging:multipleMarkets:manageBadge:getXtifyOptionsWithAppKey:,这将帮助您正确设置API密钥。
请使用上述帮助程序之一来设置API密钥,它们已被绑定为XLXtifyOptions类内的静态方法。
另外,您不必担心libXtifyLibHelper.a,当您构建提供的项目时,它会自动地(TM)包含在您的DLL中。
希望这有所帮助。
Alex

我改变了我的答案,因为它解决了我的实际问题。Stephane在上面给了我很大的帮助,并帮助我解决了一些问题,但这似乎已经完全解决了我遇到的所有问题。 - Doug Moore
惊人的消息!!很高兴我能帮忙。 - dalexsoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接