Xamarin.iOS使用Objective-C静态类库.a(Linking Native Libraries)

2024-06-23 02:58

本文主要是介绍Xamarin.iOS使用Objective-C静态类库.a(Linking Native Libraries),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 Xamarin静态类库的binding实际上是一个C#与Objective-C方法间映射过程,由于第三方SDK对iOS开发至关重要,因此官方文档中也对这块也做了完整的介绍(Binding Objective-C Libraries),但对于一个完全入门级的程序员来说,这块还是有诸多麻烦,并且部分Api类型文档上也未曾提到。下面将以百度地图作为案例,全面解析静态类库binding工程的知识与问题(Mac OS 10.8.4及以上系统)。生成dll过程:

    在开始之前需要了解几个iOS原生开发中的基础知识: 

     1.Command Line Tools for Xcode(XCode命令行工具)

      里面包含了一些常用的命令,在处理静态类库时经常用到,有两种安装方法:

      1)是在Xcode设置>>Downloads更新安装;

      2)使用Mac os下“终端”中敲入命令 xcode-select --install 安装即可。

  
  
  2.静态类库(.a)编译类型
    由于iOS编译机制上的区分,静态类库分为模拟器(i386),真机(ARMv7/ARMv7s/ARMv64等),这是由设备CPU决定的。一般厂商提供的静态类库都会分别提供(例如BaiduMap:Release-iphoneos(真机)/Release-iphonesimulator(模拟器)),那在没有明确标识的情况下,我们怎么区分这些静态类库是真机还是模拟器呢?简单直观的查看方法,打开Xamarin Studio,新建BindingProject,然后将[libBaidu.a]添加到工程上,打开自动生成的linkwith.cs文件就可以查看到静态类库的类型【可参考Monotouch BindingProject之友盟SDK】。


    

    3.真机模拟器通用静态类库.a生成
    为什么要使用这种通用类库?方便你模拟器真机调试。由于通用包比原来增加接近一倍,因此发布的时候记得只使用真机包,以减少.ipa的大小。操作方法:
    1)在桌面新建文件夹[BaiduLib],打开终端,输入命令cd,并且拖动[BaiduLib]到终端命令后面,按回车(意在将文件默认保存在此文件夹下)。
    2)接着输入命令lipo -create [libbaidumapapi.a] [libbaidumapapi.a] -output libBaiduSDK.a,(其中[libbaidumapapi.a] [libbaidumapapi.a]只要拖动到终端框内即可)敲回车,稍等片刻就可以在文件夹[BaiduLib]下看到[libBaiduSDK.a],将其添加到Binding工程中就可以查看到三种类型都存在:LinkTarget.Simulator | LinkTarget.ArmV7 | LinkTarget.ArmV7s




3) 输入命令lipo -info libBaiduSDK.a 来检测.a文件支持的系统架构。

    4.Framework系统框架引用
     几乎每个静态类库的实现都引用了或多或少的系统framework,规范的静态类库引用都会提醒你使用了哪些系统framework,而在xcode中添加是件简单的事,但在xamarin studio中地却要使用gcc命令来添加。文档中有介绍:【Linking Your Library】
     注意几个关键字:
     1)-gcc_flags,普通native library编译
     2)-cxx,包含C++代码类型编译
     3)-L${ProjectDir},当前文件目录
     4)-framework,框架类型,例如:[-framework CFNetwork]
     5)--registrar:legacy,引用文档解释:The new registrars (first introduced in 6.2.6) are now enabled by default. They catch many more errors and will prevent many bugs or undefined runtime behaviors. It is possible to fallback to the previous registrars by using --registrar:legacy as an additional mtouch argument。简单来说应该是编译器版本问题的一个控制开关;
     6)-ObjC,一般放命令行尾部,需要时添加

     完整的命令,以百度地图为例:

[csharp]  view plain copy
  1. --registrar:legacy -cxx -gcc_flags "-L${ProjectDir} -framework MapKit -framework CoreLocation -framework QuartzCore  -framework OpenGLES  -framework SystemConfiguration -framework CoreGraphics -framework Security -ObjC"  
     命令添加在UI工程中,工程选项>>iOS Build>>Additional Options>>Additional mtouch arguments      

     5.C#与ObjC数据类型

     

    了解完Xamarin.iOS的基础所需,正式开始接下来繁多无味而重要的映射方法binding工作,当然xamarin官方也提供了一个自动生成工具,但这个工具给我感觉不太能用,也许没深入研究吧,感兴趣的朋友可以下载试用一下【objective_sharpie】(如果你还无法开始时,建议参考【友盟SDK的调用】)。 

    开始之前简单介绍一下:
一个头文件中可以出现多个@interface,每个@interface在C#中都是一个类,例如:BMKActionPaopaoView.h文件:

[objc]  view plain copy
  1. @interface BMKActionPaopaoView : UIView  
  2. - (id)initWithCustomView:(UIView*)customView;  
  3. @end  

[csharp]  view plain copy
  1. //BMKActionPaopaoView.h  
  2. [BaseType (typeof(UIView))]  
  3. interface BMKActionPaopaoView  
  4. {  
  5.     /// <summary>  
  6.     /// [构造函数模式]  
  7.     /// 初始化并返回一个BMKActionPaopaoView  
  8.     /// - (id)initWithCustomView:(UIView*)customView;  
  9.     /// </summary>  
  10.     /// <param name="customView">Custom view.</param>  
  11.     [Export ("initWithCustomView:")]  
  12.     IntPtr Constructor (UIView customView);  
  13. }  


    1.打开StructsAndEnums.cs文件,如其名字一样这里是编写结构体和枚举的,也是最简单的一块:
      1)枚举(Enums)
     打开头文件[BMKAnnotationView.h],可以看到原生代码:
[objc]  view plain copy
  1.    enum {  
  2.     BMKAnnotationViewDragStateNone = 0,      ///< 静止状态.  
  3.     BMKAnnotationViewDragStateStarting,      ///< 开始拖动  
  4.     BMKAnnotationViewDragStateDragging,      ///< 拖动中  
  5.     BMKAnnotationViewDragStateCanceling,     ///< 取消拖动  
  6.     BMKAnnotationViewDragStateEnding         ///< 拖动结束  
  7. };  
  8. typedef NSUInteger BMKAnnotationViewDragState;  
[csharp]  view plain copy
  1. public enum BMKAnnotationViewDragState  
  2. {  
  3.     None = 0,      ///< 静止状态.  
  4.     Starting,      ///< 开始拖动  
  5.     Dragging,      ///< 拖动中  
  6.     Canceling,     ///< 取消拖动  
  7.     Ending         ///< 拖动结束  
  8. }  
    简单的把有含义的单词提取出来,以方便在C#中使用,枚举无非就是使用整数0、1、2代表各实际含意。
     2)结构体(Structs)
    打开头文件[BMKType.h],可以看到原生代码:
[objc]  view plain copy
  1. typedef struct {  
  2.     CLLocationCoordinate2D center;  ///< 中心点经纬度坐标  
  3.     BMKCoordinateSpan span;     ///< 经纬度范围  
  4. } BMKCoordinateRegion;  
[csharp]  view plain copy
  1. public struct BMKCoordinateSpan  
  2. {  
  3.     public double latitudeDelta;  
  4.     public double longitudeDelta;  
  5. }  
   2.Binding APIs
      打开ApiDefinition.cs,以下将开始对头文件中出现的原生语法类型进行介绍

      1)Binding Methods(基础方法)

[objc]  view plain copy
  1. - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate;  
  2. + (BMKArcline *)arclineWithPoints:(BMKMapPoint *)points;  
  3. + (BMKCircle *)circleWithCenterCoordinate:(CLLocationCoordinate2D)coord radius:(CLLocationDistance)radius;  
     C#代码, “+”代表静态方法,加Statice标识 ;当遇到不是基本数据类型时,例如[BMKCircle],可找着对应头文件,先进行其对象binding
[csharp]  view plain copy
  1. [Export ("setCoordinate:")]  
  2. void SetCoordinate (CLLocationCoordinate2D newCoordinate);  
  3.   
  4. [Static,Export ("arclineWithPoints:")]  
  5. BMKArcline ArclineWithPoints (BMKMapPoint points);  
  6.   
  7. [Static,Export ("circleWithCenterCoordinate:radius:")]  
  8. BMKCircle CircleWithCenterCoordinate (CLLocationCoordinate2D coord, double radius);  
        带out/ref parameters的方法
[objc]  view plain copy
  1. - (void) someting:(int) foo withError:(NSError **) retError;  
  2. - (void) someString:(NSObject **)byref;  
[csharp]  view plain copy
  1. [Export ("something:withError:")]  
  2. void Something (int foo, out NSError error);  
  3. [Export ("someString:")]  
  4. void SomeString (ref NSObject byref);  
2)Binding Properties(属性)

[objc]  view plain copy
  1. @property (nonatomic) CGPoint calloutOffset;  
  2. @property (nonatomicgetter=isSelected) BOOL selected;  
  3. @property (nonatomicgetter=isDraggable) BOOL draggable __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2);  
  4. @property (nonatomicretain) NSArray   *POIs;  
      C#代码,相关对应[Memory management attributes内存管理标识] ArgumentSemantic标识有三个:Assign,Copy,Retain ,依情况而定;与静态方法同样如果是带“+”,也要进行 [Static] 标识

[csharp]  view plain copy
  1. [Export ("calloutOffset")]  
  2. PointF CalloutOffset{ getset; }  
  3.   
  4. [Export ("selected")]  
  5. bool Selected{ [Bind ("isSelected")]getset; }  
  6.   
  7. [Export ("draggable")]  
  8. bool Draggable{ [Bind ("isDraggable")]getset; }  
  9.   
  10. [Export ("POIs", ArgumentSemantic.Retain)]  
  11. NSArray POIs{ getset; }  
     3)Binding Constructors(构造函数)
[objc]  view plain copy
  1. - (id)initWithCustomView:(UIView*)customView;  
C#对应,id可以理解为一个实例化对象
[csharp]  view plain copy
  1. [Export ("initWithCustomView:")]  
  2. IntPtr Constructor (UIView customView);  
     4)Binding Protocols(委托协议)
Protocol需要在interface对应头上添加 [Model][Protocol] ,以标明为Delegate
[objc]  view plain copy
  1. @protocol BMKLocationServiceDelegate <NSObject>  
  2. @optional  
  3. - (void)willStartLocatingUser;  
  4. - (void)didStopLocatingUser;  
  5. @end  
C#对应,@optional可选标识不用标识
[csharp]  view plain copy
  1. [Model][Protocol]  
  2. [BaseType (typeof(NSObject))]  
  3. interface BMKLocationServiceDelegate  
  4. {  
  5.     [Export ("willStartLocatingUser")]  
  6.     void willStartLocatingUser ();  
  7.   
  8.     [Export ("didStopLocatingUser")]  
  9.     void didStopLocatingUser ();  
  10. }  
而需要使用委托协议方法的对应类中,需要这样实现

[objc]  view plain copy
  1. @property (nonatomic, assign) id<BMKLocationServiceDelegate> delegate;  
C#对应,Assign与属性标识一致,根据实际添加
[csharp]  view plain copy
  1. [Export ("delegate", ArgumentSemantic.Assign)]  
  2. NSObject WeakDelegate { getset; }  
  3.   
  4. [Wrap ("WeakDelegate")]  
  5. BMKLocationServiceDelegate Delegate { getset; }  
     5)Binding Class Extensions

还未使用过:

[csharp]  view plain copy
  1. [BaseType (typeof (UIResponder))]  
  2. interface UIView {  
  3.         [Bind ("drawAtPoint:withFont:")]  
  4.         SizeF DrawString ([Target] string str, PointF point, UIFont font);  
  5. }  
      6)Binding Objective-C Argument Lists
[objc]  view plain copy
  1. - (void) appendWorkers:(XWorker *) firstWorker, ... NS_REQUIRES_NIL_TERMINATION ;  
[csharp]  view plain copy
  1. [Export ("appendWorkers"), Internal]  
  2. void AppendWorkers (Worker firstWorker, IntPtr workersPtr)  
     7)Binding Fields
Sometimes you will want to access public fields that were declared in a library.
还未使用过:
[csharp]  view plain copy
  1. [Field ("NSSomeEventNotification")]  
  2. NSString NSSomeEventNotification { get; }  
      8)Binding Notifications(通知)
还未使用过:
[csharp]  view plain copy
  1. interface MyClass {  
  2.     [Notification]  
  3.     [Field ("MyClassDidStartNotification")]  
  4.     NSString DidStartNotification { get; }  
  5. }  
      9)Binding Categories(类别)

这个百度地图上出现比较多,还有几个问题官网没提到的问题:

[objc]  view plain copy
  1. @interface BMKMapView (LocationViewAPI)  
  2. /// 问题出现在此  
  3. @property (nonatomicBOOL showsUserLocation;  
  4.   
  5. -(void)updateLocationData:(BMKUserLocation*)userLocation;  
  6. @end  
[Category]标识声明;文档中只提到了对方法的解析,但没有对属性进行说明,如果就按之前对属性进行解析,编译时会报错cannot declare instance members in a static class(不能在静态类中声明实例成员),语法上的错误,根据要对其进行改造,利用ObjC上get,set构造器的规则进行赋取值修改,这时showsUserLocation就可以用了

[csharp]  view plain copy
  1. [Category,BaseType (typeof(BMKMapView))]  
  2. public partial interface LocationViewAPI  
  3. {  
  4.     [Export ("setShowsUserLocation:")]  
  5.     void SetShowsUserLocation(bool isShow);  
  6.   
  7.     [Export ("updateLocationData:")]  
  8.     void UpdateLocationData (BMKUserLocation userLocation);  
  9. }  
      10)Binding Blocks(可理解为Action)

ObjC是为了避免Protocol的混乱而设计的

[objc]  view plain copy
  1. (void)asyncInitWithSuccess:(void (^)())onSuccess failure:(void (^)(NSError *))onFailure;
[csharp]  view plain copy
  
  1. [Export ("asyncInitWithSuccess:failure:")]
  2. void AsyncInitWithSuccess (Action onSuccess, Action<NSError> onFailure); 
      11)Asynchronous Methods(异步方法)
这个api中也比较少见
[csharp]  view plain copy
  1. [Export ("loadfile:completed:")]  
  2. [Async]  
  3. void LoadFile (string file, Action<string> completed);  

     12)Binging [typedef] 

     使用typedef为现有类型创建同义字,定义易于记忆的类型名

[objc]  view plain copy
  1. typedef void(^ESTCompletionBlock)(NSError* error);  
  2. typedef void(^ESTUnsignedCompletionBlock)(unsigned value, NSError* error);  
  3. typedef void(^ESTBoolCompletionBlock)(BOOL value, NSError* error);  
  4. typedef void(^ESTStringCompletionBlock)(NSString* value, NSError* error);  
[csharp]  view plain copy
  1. public delegate void ESTCompletionBlock(NSError error);  
  2. public delegate void ESTUnsignedCompletionBlock(byte value, NSError error);  
  3. public delegate void ESTBoolCompletionBlock(bool value, NSError error);  
  4. public delegate void ESTStringCompletionBlock(NSString value, NSError error);  
   3.备注

     1)NSArray数组

由于ObjC中直接以NSObjce进行操作,因此有些时候并不知道NSArray的对象到底是何种数据类型,但如果在解析过程中,你很明确知道时,可以这样解析

[objc]  view plain copy
  1. - (NSArray *)getPeerViews ();  
  2. - (void) setViews:(NSArray *) views  
[csharp]  view plain copy
  1. [Export ("getPeerViews")]  
  2. UIView [] GetPeerViews ();  
  3.   
  4. [Export ("setViews:")]  
  5. void SetViews (UIView [] views);  
      2)NSString类型,可以直接使用string替换
      3)委托协议的使用

[objc]  view plain copy
  1. @interface Demo : NSObject <UIAlertViewDelegate>  
  2. @end  
[csharp]  view plain copy
  1. [BaseType (typeof (NSObject), KeepUntilRef="Dismiss"),   
  2. Delegates=new string [] { "WeakDelegate" }, Events=new Type [] { typeof (SomeDelegate) }) ]  
  3. class Demo {  
  4.     [Export ("show")]  
  5.     void Show (string message);  
  6. }  
      4)public partial的使用
在Binding Categories(类别)中,必须使用public partial [interface LocationViewAPI]标识,否则就无法成功调用。



参考链接: http://ipixels.net/blog/specify-extra-gcc-flags-for-native-library-binding-in-xamarin-ios/
http://www.aaronheise.com/2013/08/gooddynamicsmonotouch/

这篇关于Xamarin.iOS使用Objective-C静态类库.a(Linking Native Libraries)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086088

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti