2014-04-05 61 views
2

我努力讓我的第一個Xamarin綁定工作。我正在嘗試創建一個FlatUIKit庫的綁定:https://github.com/Grouper/FlatUIKitXamarin中Objective-c綁定的問題

我設法創建了上述項目的fat靜態庫(universal .a)。 我使用Objective Sharpie來爲我生成ApiDefinition.cs。 我在Xamarin中使用該ApiDefinition.cs創建了一個BindingProject(稍作修改以使項目編譯)。 我帶着這個新的.dll文件,並在一個新的項目中嘗試過。 從該.dll調用方法工作正常並編譯。但是,我在運行時遇到問題。所有對FlatUI_UIColor執行的靜態調用都返回null。這使得這個API不可用。

這裏是包含顏色的初始.H:

@interface的UIColor(FlatUI)

  • (的UIColor *)colorFromHexCode:(的NSString *)十六進制串;
  • (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

下面是客觀記號筆生產的綁定:

[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評論後

UPDATE:

感謝您的答覆。

我已經建立了使用生成文件的脂肪庫中 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。我真的不知道發生了什麼事。

+0

模擬器和設備有什麼不同嗎?有時你會在其中一箇中看到更好的錯誤消息。 –

+0

我有同樣的問題(靜態= null)。 Xamarin.Binding項目可以很好地構建,並且我在構建模擬器時使用.dll的項目(但嘗試使用靜態屬性時會崩潰)以及它不會構建的設備。錯誤是:錯誤MT5211:本機鏈接失敗,未定義Objective-C類:_OBJC_CLASS _ $ _ IZettleSDK。如果'_OBJC_CLASS _ $ _ IZettleSDK'是來自第三方綁定的協議,請檢查它的api定義文件中是否存在[協議]屬性,否則驗證所有必要的框架已被引用並且本地庫已正確鏈接。 – Boris

回答

1

如果/當它們不能將P/Invoke調入本機庫時,綁定方法通常會返回null。所以問題可能是你在編譯時根本沒有與本地庫進行鏈接(或者你正在Simulator上運行,並且本地庫在FAT二進制文件中沒有i386支持),或者你有錯誤的鏈接器標誌。

有指定連接標誌爲Xamarin.iOS本機庫兩種方式,但我會帶你通過什麼,我認爲是最簡單的方法:

如果您正在使用Xamarin Studio和你」已經使用Objective-C綁定項目模板創建了一個項目,您可以添加本地庫(帶有.a擴展名),Xamarin Studio將創建一個新的源文件以及具有相同基本名稱的本地庫但帶有「.linkwith.cs」擴展名。

您需要做的是編輯該文件並進行所需的任何調整。

初始LinkWith屬性應該是這個樣子(這是從內存,因此它可能不是100%準確):

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

如果庫是C++,你需要添加:

IsCxx = true 

您還可以指定這取決於它的框架:

Frameworks = "UIKit" 

如果本地禮brary需要與其他本地庫鏈接,您可以使用LinkerFlags屬性(字符串)指定它們。

(你只有真正需要指定該應用程序是不是已經打算與鏈接的框架 - 所以你通常可以跳過基金會和UIKit,但它也沒有破壞)

還有其他性質可以設置,但我不記得他們都是我的頭頂,所以你可能想檢查docs以獲取更多可用屬性(Google可能會調出更多資源)。

+0

謝謝,但仍然無法正常工作。我更新了我的問題。 如果有幫助,我可以爲您提供各種項目。 – jhondel

0

我有同樣的問題,以及解決方案很簡單:

  • 在.H頭的接口被稱爲「iZettle」
  • 目的記號筆將它譯成「IZettle」

我有權訪問靜態屬性,但它們是空的。經過幾天嘗試不同的事情後,最後我們將接口名稱改爲'iZettle'(注意開頭的小'i'),所以它會匹配頭文件中的接口,並猜測靜態是否不再爲null !另外,正如@Rolf Bjarne Kvinge指出的那樣,當我們爲模擬器構建時,沒有錯誤,但是當它是爲設備構建的時候,它報告了一個錯誤,'iZettle'框架丟失了。

因此,也許你應該嘗試將public partial interface的名稱更改爲與objective-c中的.h頭文件中的名稱相同。