Xamarin演练:绑定一个Objective-C类库

Xamarin演练:绑定一个Objective-C类库


使用Objective-Sharpie绑定现有Objective-C类库



本文提供一个手把手的练习,通过Xamarin.iOS绑定(Binding)到一个现有的Obj-C类库:InfColorPicker。这将涉及诸如编译一个静态的Obj-C类库,绑定这个类库,Xamarin.iOS应用程序使用这个绑定等问题。



概括


当工作在iOS时,你可能会碰到需要调用第三方Obj-C库的情况。在这些情况下,你可以通过Xamarin.iOS新建一个绑定项目(Binding Project) 绑定到第三方库,使得C#可以使用这个库。

本文使用一个开源Obj-C项目 InfColorPicker做例子,一步一步演练如何新建一个绑定项目到InfColorPicker。InfColorPicker库的功能是提供可复用的视图控制器(View controller ),允许用户根据HSB来选择颜色,使颜色选择更方便。



我们将完成Xamarin.iOS调用这个Obj-C API的所有必要步骤:
●首先,我们用xcode创建一个Obj-C静态库。
●之后我们用Xamarin.iOS绑定这个静态库。
●接着使用工具 Objective Sharpie自动生成一些(是的,不是全部)必要的API定义,这能减少自己定义的工作量。
●最后,我们建立一个Xamarin.iOS项目来使用这个绑定。

这个示例将演示我们的c#代码使用强委托(strong delegate 译注1)调用InfColorPicker API。之后我们通过弱委托(weak delegate)来实现同样的功能。




要求

本文假设读者对Xcode和Obj-C有一定了解,并且已经读过 Binding Objective-C这篇文档。
此外,下列的这些是必须的:
●Xcode 6 和 iOS --在苹果机上已经安装Xcode 6和最近的iOS API。
●Xcode Command Line Tools --在苹果机上已经安装当前Xcode版本匹配的Xcode命令行工具。(参阅下文的安装细节)
●Xamarin Studio 或 Visual Studio --在开发机已安装最新版的Xamarin Studio 或VisualStudio。Xamarin Studio (或Xamarin Build Host) 和一台苹果mac机是开发Xamarin应用必须的。( 译注2)
●Objective Sharpie--当前版本的Objective Sharpie可以在 这里下载。

安装Xcode命令行工具Xcode Command Line Tools

如上所述,我们会使用到Xcode命令行工具(特别是make和lipo命令)。make命令是一个非常普遍的Unix命令,能执行makefile中的命令对项目程序和库进行编译。( 译注3
lipo是一个OS X的命令工具,能把适用于不同硬件架构的多个静态库文件(.a文件)打包到一个文件中。 
按照苹果文档 Building from the Command Line with Xcode FAQ,在OS X10.9版本和更新的版本中,Xcode的首选项(默认)不再支持command-line tools的下载。

你可以使用下列的一些方法安装command-line tools:

安装Xcode6 或新版本--在安装X6时,一些命令行工具已捆绑安装。 在OS X 10.9及之后,可以使用xcrun命令。


●使用终端(Terminal Application)-- 可以在终端中使用xcode-select --install命令安装:
   打开终端
   输入xcode-select --install 并回车
   会有安装向导,点击“安装”(Install)


   安装包会从苹果服务器下载并安装:



●从Apple Developers下载--Downloads for Apple Developers:


安装完命令行工具后,我们已经准备好继续进行这个演练。



演练

在这个演练里,我们会进行下列步骤:

●新建一个静态库--这步包括创建一个 Obj-C格式的静态库项目InfColorPicker ,输出一个.a扩展名的         静态库文件,该文件最终将被嵌入到.Net的类库中。

新建一个Xamarin绑定项目-- 当完成一个静态库后,我们需要创建一个Xamarin的绑定项目(译注4)。这个绑定项目由之前我们创建的静态库及C#形式的元数据(meta-data)组成,C#的元数据描述了这些Obj-C API能被怎么使用。 这些元数据通常称为API 定义(API definitions)。我们将使用工具Objective Sharpie来帮助我们自动生成这些API定义。

规范API定义--Objective Sharpie帮助我们做了很多工作,但在API能被使用前我们需要处理些变化--对自动生成的某些API做些调整。

使用绑定的类库--最后,我们创建一个Xamarin应用来展示怎么使用之前创建好的绑定库。


现在我们已经知道了会涉及哪些步骤,让我们继续前进完成这些步骤。


创建一个静态类库

如果我们查看在Github上的 InfColorPicker项目:

我们可以看到项目中的3个文件夹:
InfColorPicker - 这个文件夹包含项目的Objective-C 代码
PickerSamplePad - 这个包含一个iPad的示例。
PickerSamplePhone - 这个包含一个iPhone的示例。

让我们从 GitHub下载InfColorPicker,并解压到本地的文件夹,用Xcode打开其中的PickerSamplePhone项目,我们能看到如下的项目结构:


那些InfColorPicker下的源代码文件是完整的底层方法(红框内的),可以直接复制到 新的项目中供使用。 在蓝框中的是示范的界面应用部分。因为这个下载项目没有直接提供静态类库,需要我们在自己的Xcode项目中编译一下,生成一个静态库。

让我们做以下这些:
1.启动Xcode
2.在文件菜单(File)下选择新建一个项目(New>Project) ...



3.选中Framework&Library,选择Cocoa Touch Static Library项,点击下一步按钮(Next):



4.输入项目名称InfColorPicker,点击下一步按钮(Next)


5.选择一个本地路径用来保存项目,点击OK按钮创建项目。

6.现在我们需要从下载来的 InfColorPicker项目中把源文件拷贝到我们自己的静态库项目中。
因为InfColorPicker.h文件已经默认生成,Xcode不允许我们覆盖它(不一定),我们打开Finder,定位到之前从github下载解压的项目中,拷贝InfColorPicker 下的所有文件并黏贴到我们新建的静态库项目中:


7.返回Xcode,在InfColorPicker文件夹上右击弹出菜单,选择 Add files to "InfColorPicker...":



8. 定位到我们刚刚拷贝到的文件,选择所有,点击Add按钮:


9.这些源文件将被添加到我们的项目里:



10.在Xcode中选中InfColorPicker.m文件( 译注5),在代码编辑窗口注释掉最后2句(因为对应的头文件已经被覆盖,不需要实现)。




11.在Xcode方案选择(Scheme Selector)中,选择 InfColorPicker > iOS Device (确认下载的代码能在本机编译):


12.选中 InfColorPicker Target,然后选择Build Settings  选项:


13.滚动到Code Signing 部分,在Code Signing Identity下选中 Automatic > iOS Developer:




14.在Xcode菜单Product 下,选择 Build For > Running:


这个库项目将被编译,并且生成一个 InfColorPicker.a 文件。到这来我们已经很接近了,但还没有完成。我们刚生成的这个.a静态库适用于ARM架构的芯片,并且只能工作在iOS设备上。为了让库也能在iOS模拟器上运行(x86架构的硬件),我们需要建立一个完全版的(fat binary)的库。



创建一个完全版的类库

如上所述,刚建立的库文件只能适用于真正的iOS设备。为了也能在iOS模拟器上适用,我们需要创建一个完全版的类库。这有如下3个步骤的工作:
•创建一个ARM 7版本的静态库
•创建一个x86 版本的静态库
•使用lipo命令将2个库打包到一起
虽然这3步是相当简单的,但当Obj-C更新或是我们自己的代码更新时,必须要重复这些操作。如果你决定自动化这些操作,这个iOS绑定项目的支持和维护工作也能简单点。

有很多工具可以自动化这样的任务--一个shell脚本、rake、build、和make。当我们安装命令行工具时已经自动安装了make,所以在这个练习里我们会使用make。这里给出一段makefile命令,它可以生成适用于iOS设备与模拟器的InfColorPicker库并打包成一个:

XBUILD=/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild
PROJECT_ROOT=./InfColorPicker
PROJECT=$(PROJECT_ROOT)/InfColorPicker.xcodeproj
TARGET=InfColorPicker

all: libInfColorPickerSDK.a

libInfColorPicker-i386.a:
    $(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphonesimulator -configuration Release clean build
    -mv $(PROJECT_ROOT)/build/Release-iphonesimulator/lib$(TARGET).a $@

libInfColorPicker-armv7.a:
    $(XBUILD) -project $(PROJECT) -target $(TARGET) -sdk iphoneos -arch armv7 -configuration Release clean build
    -mv $(PROJECT_ROOT)/build/Release-iphoneos/lib$(TARGET).a $@

libInfColorPickerSDK.a: libInfColorPicker-i386.a libInfColorPicker-armv7.a
    xcrun -sdk iphoneos lipo -create -output $@ $^

clean:
    -rm -f *.a *.dll

(译注:命令注意用tab键分隔)

在文本编辑器中输入makefile命令并保存,保存路径为我们之前创建的InfColorPicker Xcode静态库同一目录。(保存为makefil,不用扩展名,见下图) ( 译注6


在mac机上打开终端,并定位到 InfColorPicker Xcode 静态库项目( Static Library)所在文件夹
输入make命令并回车,Makefile 将被执行:


运行make命令你会看到很多滚动信息,如果没什么错误,你会看到“ BUILD SUCCEEDED ”,并且在makefile文件的相同目录下看到生成的三个文件: 
libInfColorPicker-armv7.a,libInfColorPicker-i386.a , libInfColorPickerSDK.a

到这里,我们完成了整个练习的第一步:使用Xcode和命令行make\lipo生成一个静态库。让我们前进到下一步,使用Objective-Sharpie工具为我们自动生成API定义。




创建Xamarin.iOS绑定项目

在我们可以使用Objective-Sharpie自动处理前,我们需要先创建一个Xamarin.iOS绑定项目来容纳这些API定义(Objective-Sharpie会为我们自动生成定义)及C#的连接描述。


让我们做以下:
1.启动Xamarin Studio 
2.在“File”菜单下选择新建一个方案(New > Solution...):


3.在新建方案对话框,选择新建一个绑定项目(Library > iOS Binding Project):


4.点击下一步"Next"
5.输入InfColorPickerBinging作为绑定项目的名称,点击"Create"按钮创建方案:


方案被创建并默认已经包含2个文件:


ApiDefinition.cs -- 这个文件是Obj-C API怎样被包装成C#的约定。

StructsAndEnums.cs -- 这个文件里列出必要的结构和枚举声明。


我们之后将用到这2个文件。但首先,我们需要把InfColorPicker的静态库添加到绑定项目里。

在绑定项目中添加库

让我们做以下:
1.在刚创建的方案里右击InfColorPicker项目,在弹出菜单选择添加文件Add > Add Files...:


2.定位到 libInfColorPickerSDK.a文件,选中它并点击"Open"按钮

3.选择拷贝文件到文件夹(Copy the file to the directory),点击"OK"按钮

4.文件会被添加到项目里

当这个.a文件被添加到绑定项目,Xamarin.iOS会自动识别出这个Obj-C库,生成一个特定名称的文件libInfColorPickerSDK.linkwith.cs:

这个文件中的LinkWith属性告诉Xamarin该怎么处理这个刚添加的静态库。文件中内容是如下的一段代码:
using ObjCRuntime;

[assembly: LinkWith ("libInfColorPickerSDK.a", SmartLink = true, ForceLoad = true)]


LinkWith属性可以定义绑定项目怎么处理静态库,同时可以设置些重要的链接标志 。

接下来的一件事情就是为 InfColorPicker项目建立API定义,为达成这个目标,我们将使用Objective Sharpie 自动生成具体的ApiDefinition.cs文件。


使用Objective Sharpie

Objective Sharpie是个命令行的工具(由Xamarin提供),能生成绑定到第三方Obj-C库时需要的接口定义。在这个小节,我们将使用Objective Sharpie生成InfColorPicker项目的初始 ApiDefinition.cs。


开始,让我们下载Objective Sharpie的安装包,运行安装程序,按照屏幕上的向导完成安装。


安装成功后,运行终端,输入下列命令可以查看这个工具提供的功能。
sharpie -help

如果执行了上面的命令,会有如下面的一些输出:
Europa:Resources kmullins$sharpie -help
usage: sharpie [OPTIONS] TOOL [TOOL_OPTIONS]
 
Options:
  -h, --helpShow detailed help
  -v, --versionShow version information
 
Available Tools:
 
  xcode    Get information about Xcode installations and available SDKs.
 
  bind     Create a Xamarin C#binding to Objective-C APIs
Europa:Resources kmullins$

我们会用到 ObjectiveSharpie的如下命令:

xcode --这个命令提供一些当前的Xcode、及iOS和MacAPIs的版本信息。当之后我们进行绑定工作时会用到这些信息。
bind --我们将使用这个命令来解析InfColorPicker 项目的头文件(.h文件)来初始化ApiDefinition.cs 和StructsAndEnums.cs 文件。


要获取 Objective Sharpie具体工具的帮助信息,可以输入工具的名称和 -help命令。 例如输入sharpie xcode -help会得到下列的信息:

Europa:Resources kmullins$sharpie xcode -help
usage: sharpie xcode [OPTIONS]+
 
Options:
  -h, --help                 Show detailed help
  -v, --verbose              Be verbose with output
      --sdks                 List all available Xcode SDKs. Pass -verbose for
                               more details.
Europa:Resources kmullins$

在我们处理绑定前,需要确认当前安装的一些SDK的信息。在终端输入以下命令sharpie xcode -sdks:

查看上面,可以看到机器上已经安装有 iphoneos8.1 SDK 。根据这个,我们已经准备好解析 InfColorPicker 项目的头文件,并初始生成 ApiDefinition.cs 和 StructsAndEnums.cs文件了。

Europa:Resources kmullins$ sharpie xcode -sdks macosx10.10 macosx10.9 iphoneos8.1 iphonesimulator8.1 iphonesimulator7.1 Europa:Resources kmullins$

查看上面,可以看到机器上已经安装有 iphoneos8.1 SDK 。根据这个,我们已经准备好解析 InfColorPicker 项目的头文件,并初始生成 ApiDefinition.cs 和 StructsAndEnums.cs文件了。


在终端输入下面的命令:

sharpie bind --output=InfColorPicker --namespace=InfColorPicker --sdk=iphoneos8.1 [full-path-to-project]/InfColorPicker/InfColorPicker/*.h

[full-path-to-project]是你机器上 InfColorPicker 项目的Xcode 项目文件(.xcodepro)所在的路径。这个例子中,我们使用了*.h的通配符来解析文件夹下的所有头文件。通常你可以不用这样处理,你可以使用一个顶级的头文件,并在里面正确引用所有相关的头文件,然后只要把这个顶级头文件指定给Objective Sharpie就可以。

终端上会有如下输出:

Europa:Resources kmullins$sharpie bind -output InfColorPicker -namespace InfColorPicker -sdk iphoneos8.1 /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h -unified
Compiler configuration:
    -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -miphoneos-version-min=8.1 -resource-dir /Library/Frameworks/ObjectiveSharpie.framework/Versions/1.1.1/clang-resources -arch armv7 -ObjC
 
[  0%] parsing /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h
In file included from /Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPicker.h:60:
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: no 'assign',
      'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* sourceColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:28:1: warning: default property
      attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: no 'assign',
      'retain', or 'copy' attribute is specified - 'assign' is assumed [-Wobjc-property-no-attribute]
@property (nonatomic) UIColor* resultColor;
^
/Users/kmullins/Projects/InfColorPicker/InfColorPicker/InfColorPickerController.h:29:1: warning: default property
      attribute 'assign' not appropriate for non-GC object [-Wobjc-property-no-attribute]
4 warnings generated.
[100%] parsing complete
[bind] InfColorPicker.cs
Europa:Resources kmullins$


同时,在我们的文件夹下,InfColorPicker.enums.cs 和InfColorPicker.cs文件已被创建 :



在Xamarin中打开这2个文件。复制InfColorPicker.cs 中的内容到ApiDefinition.cs ,即用InfColorPicker.cs中namespace开始的代码段替换掉现有的。(using引用声明不用替换)。




目前版本的 Objective Sharpie有时候会创建重复的接口定义,所以我们要找到第一个InfColorPickerControllerDelegate定义删除它。



InfColorPicker 会用到些CoreGraphics的类,需要添加CoreGraphics 的引用:

using CoreGraphics;


这个版本的Objective Sharpie翻译委托定义(Delegate)时有时会有问题,所以要用下面的的代码替换掉InfColorPickerControllerDelegate接口定义部分的[Protocol, Model] 行。

[BaseType(typeof(NSObject))]
[Model]

替换后的定义如下:



类似的,我们操作InfColorPicker.enums.cs文件。 除了using引用部分,复制所有内容到StructsAndEnums.cs:



这个版本的Objective Sharpie 还不能创建一个枚举类型的名称(醉了)。我们需要替换掉 <unamed-C-enum>,比如这里使用InfComponentIndex:



到这步,我们的绑定项目已经完成了。让我们编译一下看看有无错误。





使用绑定

我们现在已经有了一个绑定到InfColorPicker  Obj-C库的绑定库。让我们创建一个iPhone 的示例应用来使用这个绑定库。


1.创建Xamarin.iOS项目,新建一个叫InfColorPickerSample的Xamarin.iOS项目,如下截图:





2.添加对绑定项目的引用-使InfColorPickerSample 项目引用InfColorPickerBinding项目。



3.创建iPhone的UI-双击InfColorPickerSample项目的MainStoryboard.storyboard,在iOS设计界面添加一个叫 ChangeColorButton的按钮控件(Button),如下图:




4.添加 InfColorPickerView.xib --在InfColorPicker 的Obj-C库中包含(include)一个.xib文件,但Xamarin并未把它包含进绑定项目,这会导致我们运行示例程序时错误。解决办法是把这个.xib添加到我们的Xamarin项目。 右击我们的Xamarin项目,选择Add > Add Files,并定位到这个.xib文件。如下图:



5.在对话框中选择拷贝这个文件到项目


接下来,让我们快速浏览下Obj-C中的协议(Protocols  译注7) 是怎么被C#代码解析绑定的。


Protocols 和 Xamarin.iOS

在Obj-C中,一个协议(protocol)定义的方法(或message)可以在某些情况下被使用。概念上,Obj-C中的协议与C#中的接口(interface)是非常类似的,两者间一个主要的不同是,协议中可以有可选的方法--遵从该协议的类不一定非要实现这些方法。Obj-C中使用@optional 关键字来表明那些可选(optional)方法。关于protocol的更多信息可以访问Events, Protocols and Delegates。

InfColorPickerController中有一个这种协议,如下面的代码:
@protocol InfColorPickerControllerDelegate

@optional

- (void) colorPickerControllerDidFinish: (InfColorPickerController*) controller;
// This is only called when the color picker is presented modally.

- (void) colorPickerControllerDidChangeColor: (InfColorPickerController*) controller;

@end


InfColorPickerController 实现了该协议,当用户选取了一个新的颜色,InfColorPickerController 处理完后将进行回调通知。Objective Sharpie将这个协议映射为如下的代码段:
[BaseType(typeof(NSObject))]
[Model]
public partial interface InfColorPickerControllerDelegate {

    [Export ("colorPickerControllerDidFinish:")]
    void ColorPickerControllerDidFinish (InfColorPickerController controller);

    [Export ("colorPickerControllerDidChangeColor:")]
    void ColorPickerControllerDidChangeColor (InfColorPickerController controller);
}

当绑定库(binding library)编译时,Xamarin会创建一个叫InfColorPickerControllerDelegate的抽象基类,该基类中用虚方法实现了这个接口。


有2种办法可以在Xamarin应用中实现这个接口:
强委托(Strong Delegate)-- 使用强委托是指创建一个继承了InfColorPickerControllerDelegate的子类,并且实现(override)相应的方法。InfColorPickerController 将使用这个类的一个实例来与它的客户沟通。

弱委托(Weak Delegate) -- 一个弱委托是种稍微不同技术方法,它是指在某个类中(比如InfColorPickerSampleViewController)创建一个公共方法并通过添加Export属性把该方法指定(exposing)给InfColorPickerDelegate协议。


强委托是可感知(可推断),类型安全,及封装良好的。出于这些原因,我们应该尽可能的使用强委托来代替弱委托。

在这个演练中,2种方法我们都会讨论到。 让我们从实现一个强委托开始,再完成一个弱委托。


实现一个强委托

用强委托来响应colorPickerControllerDidFinish的信息以完成我们的Xamarin应用。
 InfColorPickerControllerDelegate的子类--在这个步骤中我们为项目新添加一个类:ColorSelectedDelegate,编辑这个类如下:

using InfColorPickerBinding;
using UIKit;

namespace InfColorPickerSample
{
    public class ColorSelectedDelegate:InfColorPickerControllerDelegate
    {
        readonly UIViewController parent;

        public ColorSelectedDelegate (UIViewController parent)
        {
            this.parent = parent;
        }

        public override void ColorPickerControllerDidFinish (InfColorPickerController controller)
        {
            parent.View.BackgroundColor = controller.ResultColor;
            parent.DismissViewController (false, null);
        }
    }
}


Xamarin会绑定Obj-C中的委托(delegate)到新建的抽象基类InfColorPickerControllerDelegate,我们的子类继承它并覆盖实现了ColorPickerControllerDidFinish方法,在方法中获取InfColorPickerController属性ResultColor的值。


新建ColorSelectedDelegate的实例-- 我们的事件处理程序需要一个实例,类型是之前我们创建的ColorSelectedDelegate。编辑类InfColorPickerSampleViewController ,添加一个如下的实例变量:

ColorSelectedDelegate selector;

初始化这个ColorSelectedDelegate变量--根据下面的代码,更新ViewController中的方法ViewDidLoad,以确保实例selector可用。

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithStrongDelegate;
    selector = new ColorSelectedDelegate (this);
}

实现HandleTouchUpInsideWithStrongDelegate方法--接下来我们需要实现事件处理--当用户点击ColorChangeButton按钮时。编辑ViewController,添加下来的方法:

using InfColorPicker;
...

private void HandleTouchUpInsideWithStrongDelegate (object sender, EventArgs e)
{
    InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
    picker.Delegate = selector;
    picker.PresentModallyOverViewController (this);
}

我们首先通过静态方法得到 InfColorPickerController的实例, 再把我们定义的强委托赋给InfColorPickerController.Delegate,这个属性是Objective Sharpie为我们自动生成的。
最后我们调用PresentModallyOverViewController方法展示界面InfColorPickerSampleViewController.xib,用户得以选择颜色。


运行程序

到这里我们已经完成了所有功能代码,如果你运行程序,你可以设置背景色如下:



恭喜!你已经实现了在一个Xamarin应用中调用一个Obj-C类库。 接着,我们可以学习下弱委托的使用。


实现弱委托

作为子类继承及使用特定的委托以实现Obj-C协议方式的替代,Xamarin同样提供给你使用任何继承自NSObject的类的方法来实现Obj-C协议的方式--用Export属性装饰你的方法,并提供相应的选择(selectors)。当使用这种方式,你可以将你的类的一个实例赋给WeakDelegate属性来替换使用Delegate属性。弱委托为你提供了灵活性,将委托处理下降到不同的继承层次。让我们看看怎么在Xamarin应用中使用弱委托。


为TouchUpInside创建事件处理
让我们给设置背景色的按钮的TouchUpInside 事件添加事件处理。这个处理和之前章节创建的HandleTouchUpInsideWithStrongDelegate 有相同的职能,不过我们将使用弱委托来替换强委托。
编辑 ViewController类并添加如下的方法:

private void HandleTouchUpInsideWithWeakDelegate (object sender, EventArgs e)
{
    InfColorPickerController picker = InfColorPickerController.ColorPickerViewController();
    picker.WeakDelegate = this;
    picker.SourceColor = this.View.BackgroundColor;
    picker.PresentModallyOverViewController (this);
}

更新ViewDidLoad--我们必须修改ViewDidLoad来使用我们新建的事件处理,修改ViewDidLoad如下的代码段:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    ChangeColorButton.TouchUpInside += HandleTouchUpInsideWithWeakDelegate;
}

处理 colorPickerControllerDidFinish: Message--当ViewController处理完成,iOS会发送消息colorPickerControllerDidFinish:给弱委托。我们需要建一个C#方法来处理这个消息。为了完成这个,我们创建一个C#方法并用 Export属性修饰。编辑ViewController类并添加如下的方法:

[Export("colorPickerControllerDidFinish:")]
public void ColorPickerControllerDidFinish (InfColorPickerController controller)
{
    View.BackgroundColor = controller.ResultColor;
    DismissViewController (false, null);
}

运行这个程序,它和之前的功能是一样的,但使用弱委托替换了强委托。
到这里,你已经全部完成了整个演练。现在,你应该对怎么创建和使用一个Xamarin绑定项目有了一个了解。


摘要

本文演示了创建和使用一个Xamarin绑定项目的各个过程。首先我们讨论了怎样编译一个现有的Obj-C库到一个静态库。接着我们涉足了怎么创建一个Xamarin绑定项目,及怎么使用Objective Sharpie 生成Obj-C静态库的API定义。我们讨论了怎样更新和调整生成的API定义使它们能恰当的给外部调用。在Xamarin绑定项目完成后,我们转到在Xamarin应用项目中使用这个绑定,特别的,我们还讨论了强委托与弱委托的使用。



译注1:strong delegate在这里使用了C#中更熟悉的"委托"的叫法,但在iOS更强调的是引用的意思。weak delegate类似。
译注2:本文中的Xamarin.iOS是指在苹果机上的Xamarin环境,其实在 windows环境--Xamarin Studio或VS Xamarin中,你可以直接做类似的操作,如在VS里新建一个Xamarin binding project。
译注3:.Net程序员可能对makefile不熟悉,可以理解为一段脚本命令或一个批处理文件,其中会通过命令的方式调用IDE的编译器。在苹果机上可以通过文本软件创建,也有很多插件工具,或者,在终端直接输入命令:touch Makefile。更多信息请搜索makefil相关。
译注4:你同样可以在Windows环境创建绑定项目。
译注5:Obj-C中.h是头文件,.m文件是具体的实现内容。
译注6:可以直接指定具体的路径,也可以使用cd定位到文件夹,使用相对路径。
译注7:Obj-C中的Interface关键字是对类的声明,Protocols关键字 才更接近C#中的interface。

你可能感兴趣的:(Xamarin演练:绑定一个Objective-C类库)