Xamarin中Objective-c绑定的问题

时间:2014-04-05 16:22:04

标签: c# ios binding xamarin.ios xamarin

我正努力让我的第一个Xamarin绑定工作。我正在尝试创建FlatUIKit库的绑定:https://github.com/Grouper/FlatUIKit

我设法创建了上述项目的胖静态库(通用.a)。 我使用Objective Sharpie为我生成ApiDefinition.cs。 我使用ApiDefinition.cs在Xamarin中创建了一个BindingProject(稍加修改以使项目编译)。 我拿了那个新的.dll并在一个新项目中尝试了它。 从.dll调用方法工作正常并编译。但是,我在运行时遇到问题。对FlatUI_UIColor执行的所有静态调用都返回null。这使得此API无法使用。

这是包含颜色的初始.h:

  

@interface UIColor(FlatUI)

     
      
  • (UIColor *)colorFromHexCode:(NSString *)hexString;
  •   
  • (UIColor *)turquoiseColor;
  •   
  • (UIColor *)greenSeaColor;
  •   
  • (UIColor *)emerlandColor;
  •   
  • (UIColor *)nephritisColor;
  •   
  • (UIColor *)peterRiverColor;
  •   
  • (UIColor *)belizeHoleColor;
  •   
  • (UIColor *)amethystColor;
  •   
  • (UIColor *)wisteriaColor;
  •   
  • (UIColor *)wetAsphaltColor;
  •   
  • (UIColor *)midnightBlueColor;
  •   
  • (UIColor *)sunflowerColor;
  •   
  • (UIColor *)tangerineColor;
  •   
  • (UIColor *)carrotColor;
  •   
  • (UIColor *)pumpkinColor;
  •   
  • (UIColor *)alizarinColor;
  •   
  • (UIColor *)pomegranateColor;
  •   
  • (UIColor *)cloudsColor;
  •   
  • (UIColor *)silverColor;
  •   
  • (UIColor *)concreteColor;
  •   
  • (UIColor *)asbestosColor;

  •   
  • (UIColor *)blendedColorWithForegroundColor:(UIColor *)foregroundColor                             backgroundColor:(UIColor *)backgroundColor                                percentBlend:(CGFloat)percentBlend;

  •   
     

@end

以下是Objective Sharpie生成的绑定:

[Category, BaseType (typeof (UIColor))]
public partial interface FlatUI_UIColor {

    [Static, Export ("colorFromHexCode:")]
    UIColor ColorFromHexCode (string hexString);

    [Static, Export ("turquoiseColor"), Verify ("ObjC method massaged into getter property", "/Users/jhondel/Projects/iOS Libraries/FlatUIKit/Classes/ios/UIColor+FlatUI.h", Line = 14)]
    UIColor TurquoiseColor { get; }

    [Static, Export ("greenSeaColor"), Verify ("ObjC method massaged into getter property", "/Users/jhondel/Projects/iOS Libraries/FlatUIKit/Classes/ios/UIColor+FlatUI.h", Line = 15)]
    UIColor GreenSeaColor { get; }

    /// ...

    [Static, Export ("blendedColorWithForegroundColor:backgroundColor:percentBlend:")]
    UIColor BlendedColorWithForegroundColor (UIColor foregroundColor, UIColor backgroundColor, float percentBlend);
}

在ApiDefintion.cs中,我摆脱了验证。

如果有帮助,这是初始库的.m:

@implementation UIColor (FlatUI)

// Thanks to http://stackoverflow.com/questions/3805177/how-to-convert-hex-rgb-color-codes-to-uicolor
+ (UIColor *) colorFromHexCode:(NSString *)hexString {
    NSString *cleanString = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""];
    if ([cleanString length] == 3) {
        cleanString = [NSString stringWithFormat:@"%@%@%@%@%@%@",
                       [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)],
                       [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)],
                       [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]];
    }
    if([cleanString length] == 6) {
        cleanString = [cleanString stringByAppendingString:@"ff"];
    }

    unsigned int baseValue;
    [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue];

    float red = ((baseValue >> 24) & 0xFF)/255.0f;
    float green = ((baseValue >> 16) & 0xFF)/255.0f;
    float blue = ((baseValue >> 8) & 0xFF)/255.0f;
    float alpha = ((baseValue >> 0) & 0xFF)/255.0f;

    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

+ (UIColor *) turquoiseColor {
    static UIColor *turquoise = nil;
    static dispatch_once_t dispatchToken;

    dispatch_once(&dispatchToken, ^{
        turquoise = [UIColor colorFromHexCode:@"1ABC9C"];
    });

    return turquoise;
}

为什么FlatUI_UIColor.GreenSeaColor(和其他人)返回null的任何想法?

感谢您的帮助。

@jstedfast评论后更新:

感谢您的回复。

我使用makefile构建了fat库 https://github.com/xamarin/monotouch-samples/blob/master/BindingSample/src/binding/Makefile。

它构建了一个通用库(收集armv7和i386) 当我在Xamarin的绑定项目中导入.a时,它会自动生成LinkWith。就我而言:

[assembly: LinkWith ("libXMBindingLibrarySampleUniversal.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true)]  

图书馆仅使用" UIKit"和"基金会"根据文档,不需要在LinkWith中指定。

生成的.dll似乎很好。我可以访问我的示例项目中的方法。我设法创建一个带标题的FlatUIButton,并在运行模拟器时查看标题。但是按钮无法单击并且是黑色的,因为所有FlatUI_UIColor.X都返回null。我真的不知道发生了什么。

2 个答案:

答案 0 :(得分:1)

如果/当它们不能P / Invoke到本机库时,绑定方法通常会返回null。所以问题可能是你要么没有在你的构建中连接本机库(或者你在Simulator上运行,例如,本机库在FAT二进制文件中没有i386支持),或者你有错误的链接器标志。

有两种方法可以为Xamarin.iOS指定本机库的链接器标志,但我会引导您完成我认为最简单的方法:

如果您正在使用Xamarin Studio并且使用Objective-C Binding Project模板创建了一个项目,则只需添加本机库(扩展名为.a),Xamarin Studio将创建一个新的源文件使用与本机库相同的基本名称,但扩展名为“.linkwith.cs”。

您需要做的是编辑该文件并进行所需的任何调整。

最初的LinkWith属性应该看起来像这样(这是来自内存,所以它可能不是100%准确):

[assembly: LinkWith ("libLibraryName.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, ForceLoad = true)]

如果库是c ++,则需要添加:

IsCxx = true

您还可以指定它所依赖的框架:

Frameworks = "UIKit"

如果本机库需要与其他本机库链接,您可以使用LinkerFlags属性(字符串)指定它们。

(您只需要指定应用程序尚未与之链接的框架 - 因此您通常可以跳过Foundation和UIKit,但它也不会受到伤害)

还有其他可以设置的属性,但我不记得这些属性,所以您可能需要检查docs以获取更多可用属性(Google可能会增加其他属性)资源)。

答案 1 :(得分:0)

我遇到了同样的问题,解决方案非常简单:

  • .h标题中的接口称为“iZettle”
  • 目标Sharpie将其翻译成'IZettle'

我有权访问静态属性,但它们都是null。经过几天尝试不同的事情,最后我们将界面名称更改为'iZettle'(注意开头的小'i'),因此它将匹配头文件中的接口,并猜猜是什么,静态不再是null !

另外,正如@Rolf Bjarne Kvinge所指出的那样,当我们为模拟器构建时,没有错误,但是当它为设备构建时,它报告了一个错误,即“iZettle”框架丢失了。

所以也许您应该尝试将public partial interface名称更改为与objective-c中的.h头文件中的名称相同。