將iOS或Android的第三方SDK接入到Xamarin,不是一般的坑栋操,雖然有官方文檔码撰,奈何奈何渗柿,依然十分滴蛋疼
在此,先感謝 前輩的分享 脖岛,我直接入坑了
0.前言
一個(gè)Native Library Binding項(xiàng)目可綁定多個(gè).Framework或.A類庫(kù)
綁定MaMapKit和綁定FoundationKit方式相同 - 基礎(chǔ)框架和地圖框架
.framework結(jié)尾可能為.a靜態(tài)庫(kù)朵栖,也可能為.dylib動(dòng)態(tài)庫(kù)
在Linker Flags添加動(dòng)態(tài)庫(kù)時(shí),添加-ObjC -all_load柴梆,之后再添加動(dòng)態(tài)庫(kù):各動(dòng)態(tài)庫(kù)以中橫線開(kāi)頭
必須去掉lib的ib字母:官方說(shuō)法要簡(jiǎn)寫(xiě)陨溅,如libz需要添加中橫線且去掉ib:-lz(模擬器Debug編譯OK,運(yùn)行報(bào)錯(cuò)無(wú)效 IL Code绍在,真機(jī)Release運(yùn)行OK:猜測(cè)是模擬器可能沒(méi)有加載進(jìn)動(dòng)態(tài)庫(kù)门扇,真機(jī)在Debug下編譯報(bào)錯(cuò):找不到引用的動(dòng)態(tài)庫(kù))- 在Xcode內(nèi)添加動(dòng)態(tài)庫(kù)依然是需要中橫線打頭的
尤其重要的聲明:一定要在真機(jī)且Release下運(yùn)行,否則可能編譯失敗或運(yùn)行Crash:模擬器可訪問(wèn)靜態(tài)方法 - 8.21 編譯的DLL真機(jī)DEBUG下也能調(diào)試偿渡,DLL的DEBUG和RELEASE是一樣的文件 - 若是引用DLL則DEBUG下也可運(yùn)行臼寄,希望僅僅是我遇到這個(gè)BUG
無(wú)效 IL Code是針對(duì)創(chuàng)建對(duì)象的:雖然可以通過(guò)KVC賦值取值,通過(guò)運(yùn)行時(shí)特性判斷方法是否實(shí)現(xiàn)溜宽,但這些都是針對(duì)對(duì)象:C#不支持指針吉拳,我是沒(méi)法寫(xiě)調(diào)用的了;這些方式都是針對(duì)于對(duì)象适揉,類加[Static]留攒,若是類在模擬器的Debug下即使對(duì)象存在,訪問(wèn)其屬性方法也會(huì)導(dǎo)致Crash
修改iOS項(xiàng)目的iOS Build下的Linker behavior為L(zhǎng)ink Framework SDKs Only:加載依賴庫(kù)
集成MaMapKit時(shí)嫉嘀,需要在iOS項(xiàng)目下的Resources下添加MaMap.bundle炼邀,一些地圖顯示本地資源
1.語(yǔ)言轉(zhuǎn)換
- MaMapKit
sharpie bind --output=/users/timas-malk/desktop/MAMapKit --namespace=MAMapKit -framework /Users/timas-malk/Desktop/MAMapKit.framework -sdk iphoneos10.3
- AMapFoundationKit
sharpie bind --output=/users/timas-malk/desktop/AMapFoundationKit --namespace=AMapFoundationKit -framework /Users/timas-malk/Desktop/AMapFoundationKit.framework -sdk iphoneos10.3
在此備注下說(shuō)明:
1.sharpie bind 為Xamarin提供的將OC代碼轉(zhuǎn)為C#代碼的工具,僅僅針對(duì)調(diào)用吃沪,會(huì)將OC中的類轉(zhuǎn)為C#內(nèi)的接口形式進(jìn)行調(diào)用
2.output=為輸出轉(zhuǎn)換后文件夾的路徑汤善,默認(rèn)就在當(dāng)前用戶目錄下什猖,整理修改為桌面
3.--namespace為轉(zhuǎn)換的代碼咋C#內(nèi)添加一個(gè)命名空間票彪,命名空間定義不清楚自行百度
4.-framework為當(dāng)前綁定SDK的類型,后接的是需要轉(zhuǎn)換的SDK路徑
5.-sdk iphoneos10.3需要適配到的iOS系統(tǒng)版本
2.代碼修改
修改ApiDefine文件的BuildAction為ObjcBindingAPIDefinition ; Struct文件BuildAction修改為ObjcBindingCoreSource
將Stucts文件內(nèi)的uint更改為ulong:有負(fù)數(shù)則修改為int不狮;C#不允許字符作為枚舉類型降铸,因此修改為數(shù)值
[Verity]核對(duì)正確后注釋掉 ; 在ApiDefine內(nèi)將Constants的[Static]注釋掉
OC和C#方法命名方式不一樣:因此Sharpie轉(zhuǎn)換會(huì)出現(xiàn)很多同名方法,這不是重載摇零。C#聲明修改為不一樣即可
合并同名的Constants接口推掸,報(bào)錯(cuò)Unsupported type for Fields
某些類繼承/接口,出現(xiàn)找不到該類,注釋掉繼承即可:C#實(shí)現(xiàn)都是通過(guò)接口形式谅畅,而不是類
去掉所有聲明里面的*:C#沒(méi)有指針概念
OC點(diǎn)語(yǔ)法是編譯器特性登渣,其本質(zhì)還是調(diào)用方法發(fā)送消息,因此若出現(xiàn)訪問(wèn)屬性Crash可嘗試將屬性定義為方法
3.引用和依賴
- 引用:添加 Native References引用的framework文件:將引用的Framework文件拷貝到該綁定項(xiàng)目下毡泻,因?yàn)檫@是引用(引用的項(xiàng)目可以是.framework整個(gè)包胜茧,也可以是framework下的該類庫(kù)文件:沒(méi)有后綴)
- 依賴:右擊添加引用的類庫(kù),彈出選擇Properies仇味,勾選Force Load和Smart Link呻顽;在Frameworks下添加.framework結(jié)尾的系統(tǒng)依賴庫(kù)(.framework可能為.a,也可能為.dylib)丹墨,在Linker Flags其她后綴的依賴庫(kù)廊遍,這里基本為動(dòng)態(tài)庫(kù)
- 修改iOS項(xiàng)目的iOS Build下的Linker behavior為L(zhǎng)ink Framework SDKs Only:加載依賴庫(kù)
- 集成MaMapKit時(shí),需要在iOS項(xiàng)目下的Resources下添加MaMap.bundle贩挣,一些地必須的顯示本地資源
添加的內(nèi)容
1.Frameworks
OpenGLES UIKit Foundation CoreGraphics QuartzCore CoreLocation CoreTelephony SystemConfiguration Security AdSupport JavaScriptCore GLKit
2.Linker Flags
全寫(xiě):-ObjC -all_load -libz -libc++ -libstdc++.6.0.9 (復(fù)制簡(jiǎn)寫(xiě))
簡(jiǎn)寫(xiě)(官方說(shuō)法:過(guò)長(zhǎng)的描述可能導(dǎo)致引用失敽砬啊):-ObjC -all_load -lz -lstdc++ -lc++
在Linker Flags添加動(dòng)態(tài)庫(kù)時(shí),添加-ObjC -all_load王财,之后再添加動(dòng)態(tài)庫(kù):各動(dòng)態(tài)庫(kù)以中橫線開(kāi)頭:必須去掉lib的ib字母:官方說(shuō)法要簡(jiǎn)寫(xiě)被饿,如libz需要添加中橫線且去掉ib:-lz(模擬器Debug編譯OK,運(yùn)行報(bào)錯(cuò)無(wú)效 IL Code搪搏,真機(jī)Release運(yùn)行OK:猜測(cè)是模擬器可能沒(méi)有加載進(jìn)動(dòng)態(tài)庫(kù)狭握,真機(jī)在Debug下編譯報(bào)錯(cuò):找不到引用的動(dòng)態(tài)庫(kù))
4.權(quán)限設(shè)置
1.NSAppTransportSecurity字典下NSAllowsArbitraryLoads為BOOL類型其值為YES:兼容iOS 9 下版本
2.NSLocationUsageDescription:App需要您的同意,才能訪問(wèn)位置
3.NSLocationWhenInUseUsageDescription:App需要您的同意,才能在使用期間訪問(wèn)位置
4.NSLocationAlwaysUsageDescription:App需要您的同意,才能始終訪問(wèn)位置
若要后臺(tái)定位,需要開(kāi)啟設(shè)置
5.新增接口
若該類有這個(gè)方法實(shí)現(xiàn)疯溺,Sharpie轉(zhuǎn)換后沒(méi)有生成论颅,或是其父類的代碼:此時(shí)都可以添加接口聲明進(jìn)行調(diào)用
若方法通過(guò)init...方式初始化,那么將alloc方法聲明為[Static]囱嫩,之后init照常聲明恃疯,調(diào)用時(shí)先調(diào)用alloc導(dǎo)出方法,在對(duì)應(yīng)init...方法:這兩個(gè)方法都是返回相同的對(duì)象墨闲,這是alloc沒(méi)有參數(shù):本質(zhì)是alloc分配內(nèi)存和初始化屬性今妄,iniit...才是自定義,因此init...在iOS中成為偽構(gòu)造方法鸳碧,若是init不做任何事盾鳞,可直接調(diào)用new即可,new在C#中是可行的
6.代理使用
C#將類庫(kù)的所有調(diào)用都轉(zhuǎn)為接口形式瞻离,協(xié)議只是加了 [Protocol, Model] 修飾腾仅,因此在C#調(diào)用還是要基于接口形式(在OC中協(xié)議有optional和require兩種形式,Xamarin默認(rèn)實(shí)現(xiàn)是通過(guò)類套利,聲明其方法未virtual和abstract形式)
C#也沒(méi)有多繼承推励,OC的多繼承可通過(guò)協(xié)議實(shí)現(xiàn)鹤耍;在C#中若要實(shí)現(xiàn)OC的協(xié)議,需要添加一個(gè)類验辞,繼承于該接口稿黄,在類的實(shí)現(xiàn)內(nèi)重寫(xiě)接口內(nèi)的實(shí)現(xiàn),即OC協(xié)議的實(shí)現(xiàn)跌造;將該類的對(duì)象賦值給代理抛猖,高德MaMapView代理有強(qiáng)弱兩個(gè),賦值其中一個(gè)就行:C#來(lái)實(shí)現(xiàn)OC協(xié)議可能會(huì)出現(xiàn)嵌套情況鼻听,因?yàn)獒槍?duì)沒(méi)有協(xié)議都需要實(shí)現(xiàn)一個(gè)類
7.新增:地位集成(地位和地圖是兩套框架)
== 定位模塊支持真機(jī)Debug和Release财著;模擬器只能獲取到經(jīng)緯度且不準(zhǔn)確,沒(méi)有地址描述 ==
== iOS項(xiàng)目在引用DLL時(shí)撑碴,需要設(shè)置iOS項(xiàng)目的iOS Build下的Linker Behavior為L(zhǎng)ink Framework SDKs Only ==
- 語(yǔ)言轉(zhuǎn)換
sharpie bind --output=/users/timas-malk/desktop/AMapLocationKit --namespace=AMapLocationKit -framework /Users/timas-malk/Desktop/AMapLocationKit.framework -sdk iphoneos10.3
備注:Define內(nèi)的最外層 [Static] 是需要被注釋掉的撑教,Structs內(nèi)是不用
== iOS的協(xié)議在C#中是通過(guò)類建立一對(duì)一聯(lián)系的,因此若出現(xiàn)回調(diào)醉拓,需要將調(diào)用類繼承于定位類:作強(qiáng)制類型轉(zhuǎn)換后回調(diào)源對(duì)象代理事件 ==== 無(wú)效:高德地圖的類映射到C#變成了接口伟姐,而不再是類了。例如亿卤,繼承AMapLocationManager愤兵,定位會(huì)不準(zhǔn)確,而且永遠(yuǎn)獲取不到逆地理編碼:定位失敗 - base調(diào)用也不可行排吴;因此回調(diào)事件為靜態(tài)事件 ==
再次備注 參考鏈接秆乳,感謝作者的入門(mén)分享