前言
大約一個(gè)月前收到領(lǐng)導(dǎo)新布置的任務(wù)稚瘾,要用Unity直接接入發(fā)行方ios sdk。當(dāng)時(shí)我一下子就懵了,ios的Object-c沒接觸過啊翰苫,Unity和ios該怎么交互呀,完全什么都不懂这橙。接到消息的那一刻整個(gè)人狀態(tài)都不好了奏窑,查閱了很多資料完全沒有頭緒也看不進(jìn)去任何有關(guān)OC的基礎(chǔ)知識。還好有我們部門大楊哥耐心的講了一遍怎么弄屈扎。經(jīng)過大楊鍋的講解還有Google理解出來的一些知識埃唯,現(xiàn)已完整的對接完好幾個(gè)IOS 的SDK的接入工作。其實(shí)ios sdk接入并沒有你想的那么難鹰晨,接下來我會舉例說明墨叛,跟大家分享一下我學(xué)到的東西止毕,讓新手同學(xué)不要跟我一樣上來就懵。
文章目錄
Unity與IOS交互層C#代碼編寫
Unity接 iOS SDK你需要了解的Objective-C基礎(chǔ)知識
Unity 與IOS交互工作原理
ios 小7手游sdk接入演示
編譯器版本介紹
Unity :Unity 19.4.2f1 Personal
Xcode : Xcode 12.2
Unity與IOS交互層C#代碼編寫
Unity 廣泛的支持原生插件漠趁,即用 C扁凛、C++、Objective-C 等編寫的原生代碼庫闯传。插件允許游戲代碼(用 C# 編寫)調(diào)用這些庫中的函數(shù)谨朝。
為了使用原生插件,首先需要使用基于 C 的語言編寫函數(shù)來訪問所需的功能并將它們編譯到庫中甥绿。在 Unity 中字币,還需要?jiǎng)?chuàng)建一個(gè) C# 腳本來調(diào)用本機(jī)庫中的函數(shù)。
原生插件應(yīng)提供一個(gè)簡單的 C 接口供 C# 腳本隨后向其他用戶腳本公開共缕。當(dāng)某些低級渲染事件發(fā)生時(shí)(例如洗出,創(chuàng)建圖形設(shè)備時(shí)),Unity 也可以調(diào)用原生插件導(dǎo)出的函數(shù)⊥脊龋現(xiàn)在編寫一下C#的腳本共苛,此代碼來源于實(shí)際項(xiàng)目部分截取。
using System.Runtime.InteropServices;
namespace GameChannel
{
public class ChannelManager : Singleton<ChannelManager>
{
#if UNITY_IOS //c#中宏的概念 蜓萄,意思是當(dāng)前平臺是iOS
[DllImport("__Internal")]
private static extern void SDk_Login(); //登錄
[DllImport("__Internal")]
private static extern void SDk_Logout();//注銷
[DllImport("__Internal")]
private static extern void SDk_SwitchAccount();//切換賬號(可選參數(shù))
[DllImport("__Internal")]
private static extern void SDk_Pay(string payData);//支付
[DllImport("__Internal")]
private static extern void SDk_Data(string thisdata); //向渠道發(fā)送游戲數(shù)據(jù)
//當(dāng)前平臺是安卓隅茎,交互層插件對外調(diào)用名稱是通用的,但是方式上是略有不同用宏的概念做區(qū)分嫉沽。
#elif UNITY_ANDROID
}
}
對上述代碼做下說明:在 iOS 上辟犀,插件以靜態(tài)方式鏈接到可執(zhí)行文件中,因此我們必須使用“ __Internal” 作為庫名绸硕。其他的平臺會通過動(dòng)態(tài)的方式加載插件 [DllImport ("PluginName")]名稱堂竟。C#調(diào)用其他模塊的接口都是通過DllImport的方式來實(shí)現(xiàn)的。例如c#定義了void SDk_Login()方法玻佩,在ios的object-c中 也一定有void SDk_Login()方法出嘹。
Unity接 iOS SDK你需要了解的Objective-C基礎(chǔ)知識
Unity項(xiàng)目開發(fā),iOS平臺要接SDK的話咬崔,就需要寫Objective-C原生代碼的税稼,對于沒使用過Objective-C的小伙伴不要慌。我一說你就懂了垮斯。
.h : 頭文件作為一種包含功能函數(shù)郎仆、數(shù)據(jù)接口聲明的載體文件,主要用于保存程序的聲明兜蠕,而定義文件用于保存程序的實(shí)現(xiàn)
.m : 它是對.h頭文件中方法的實(shí)現(xiàn)扰肌,外部不能訪問
.mm : 源代碼文件。和.m文件類似熊杨,唯一的不同點(diǎn)就是曙旭,除了可以包含Objective-C和C代碼以外盗舰,還可以包含C++代碼。
include與#import
當(dāng)你需要在源代碼中包含頭文件的時(shí)候桂躏,你可以使用#include編譯選項(xiàng)也可以使用#import 钻趋,但是OC官方更推薦的方法是:#import。這個(gè)跟java的import 導(dǎo)包思想上非常相似沼头。
""和<>的區(qū)別
例如 #import "UnityIos.h" 和 #import <Foundation/Foundation.h>兩種。使用""引入的是本地工程的文件书劝,而使用<>引入的是系統(tǒng)庫的文件进倍。
@interface與@implementation
@interface是類為對象提供特性描述(接口),@implementation是對@interface定義接口具體的實(shí)現(xiàn)购对。這兩個(gè)跟java中的接口的定義與實(shí)現(xiàn)上思想上是一致的猾昆。
方法前的+ 和 -
加號(+)的方法為類方法,這類方法是可以直接用類名來調(diào)用的骡苞。
減號(-)的方法為實(shí)例方法垂蜗,必須使用這個(gè)類的實(shí)例才可以調(diào)用它。
打印日志
NSLog打印日志解幽。如 NSlog(@"")
基本數(shù)據(jù)類型
NSString : 字符串
CGfloat : 浮點(diǎn)值的基本類型
NSInteger : 整型
BOOL : 布爾型
json使用
Unity和OC要傳遞數(shù)據(jù)贴见,常用的就是json格式。但是OC還和java的不一樣躲株。
//json字符串轉(zhuǎn)化成字典
-(NSDictionary*)getJsonDic:(NSString*)jsonString{
NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
return [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
}
//字典轉(zhuǎn)化成json字符串
-(NSString*)arrayToJson:(NSMutableDictionary *)dic{
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
這些知識僅做作為基礎(chǔ)了解片部,其他詳細(xì)的用法大家可以找下Google和度娘
Unity 與IOS交互工作原理
熟悉工作原理前大家不妨看一下之前寫的博客:Unity 導(dǎo)出Xcode 項(xiàng)目的結(jié)構(gòu) 作為一個(gè)了解,每個(gè)Unity ios Xcode 項(xiàng)目都會有如下結(jié)構(gòu):
UnityFramework 庫文件部分霜定,其中包含源档悠、插件和相關(guān)框架。它還生成 UnityFramework.framework 文件望浩。
Unity-iPhone 主啟動(dòng)器部分辖所,其中包含應(yīng)用程序表示數(shù)據(jù)并會運(yùn)行該庫。Unity-iPhone 目標(biāo)對 UnityFramework 目標(biāo)具有單一依賴關(guān)系磨德。
要將 Unity 集成到另一個(gè) Xcode 項(xiàng)目中缘回,必須將兩個(gè) Xcode 項(xiàng)目(原生項(xiàng)目和 Unity 生成的項(xiàng)目)合并到一個(gè) Xcode 工作空間中,并將 UnityFramework.framework 文件添加到原生 Xcode 項(xiàng)目的應(yīng)用程序 (Application) 目標(biāo)的嵌入式二進(jìn)制文件 (Embedded Binaries) 中典挑。完成此操作后切诀,可以使用 UnityFramework 類來控制 Unity 運(yùn)行時(shí)。Unity直接導(dǎo)出Xcode工程目錄結(jié)構(gòu)如下圖:
要想了解原理就要找到程序的入口搔弄,熟悉OC或者C的朋友一定知道m(xù)ain方法,這是整個(gè)程序的入口幅虑。我們先看下MainApp/main.mm,這個(gè)文件做了什么呢。
從代碼中大概讀懂的意思將/Frameworks/UnityFramework.framework庫文件加載到應(yīng)用程序中顾犹。然后看下UnityFramework/UnityFramework.h,通過UnityFramework Objective-C 類(該類是 UnityFramework.framework 的主體類)的實(shí)例來控制 Unity 運(yùn)行時(shí):其中的屬性方法我羅列一下倒庵。
UnityFramework類
+(UnityFramework*)getInstance :單例類方法褒墨,可將實(shí)例返回到 UnityFramework。
-(UnityAppController*)appController :返回 UIApplicationDelegate 的 UnityAppController 子類擎宝。這是原生端的根 Unity 類郁妈,可以訪問應(yīng)用程序的視圖相關(guān)對象,例如 UIView绍申、UIViewControllers噩咪、CADisplayLink 或 DisplayConnection。
-(void)setDataBundleId:(const char*)bundleId:設(shè)置捆綁包极阅,Unity 運(yùn)行時(shí)應(yīng)在其中查找 Data 文件夾胃碾。應(yīng)在調(diào)用 runUIApplicationMainWithArgc 或 runEmbeddedWithArgc 之前調(diào)用此方法。
-(void)runUIApplicationMainWithArgc:(int)argc argv:(char*[])argv:從沒有其他視圖的主要方法中運(yùn)行 Unity 的默認(rèn)方式筋搏。
-(void)runEmbeddedWithArgc:(int)argc argv:(char[])argv appLaunchOpts:(NSDictionary)appLaunchOpts:存在其他視圖時(shí)仆百,如果需要運(yùn)行 Unity,需要調(diào)用此方法奔脐。
-(void)unloadApplication :調(diào)用此方法可卸載 Unity俄周,并在卸載完成后接收對 UnityFrameworkListener 的回調(diào)。Unity 將釋放占用的大部分內(nèi)存髓迎,但不會全部釋放峦朗。
-(void)registerFrameworkListener:(id<UnityFrameworkListener>)obj :注冊監(jiān)聽器對象,用于接收 UnityFramework 生命周期相關(guān)事件的回調(diào)排龄。
-(void)unregisterFrameworkListener:(id<UnityFrameworkListener>)obj:取消注冊監(jiān)聽器對象甚垦。
-(void)showUnityWindow:在顯示非 Unity 視圖時(shí)調(diào)用此方法,也會顯示已經(jīng)在運(yùn)行的 Unity 視圖涣雕。
- -(void)pause:(bool)pause:暫停 Unity
- -(void)setExecuteHeader:(const MachHeader*)header:必須在運(yùn)行 Unity 之前調(diào)用此命令艰亮,CrashReporter 才能正常工作。
-(void)sendMessageToGOWithName:(const char)goName functionName:(const char)name message:(const char*)msg:此方法是 UnitySendMessage 的代理挣郭。它通過名稱查找游戲?qū)ο笃#⑹褂脝巫址?shù)來調(diào)用 functionName。
(void)quitApplication:(int)exitCode:調(diào)用此方法可完全卸載 Unity兑障,并在 Unity 退出后接收對 UnityFrameworkListener 的回調(diào)侄非。Unity 將釋放所有內(nèi)存。
注意:進(jìn)行此調(diào)用后流译,將無法在同一進(jìn)程中再次運(yùn)行 Unity逞怨。可在 AppController 上設(shè)置 quitHandler 以覆蓋默認(rèn)進(jìn)程終止
然后再看下Classes/main.mm福澡,這個(gè)文件做了什么叠赦,根據(jù)代碼得知(UIApplicaitonMain方法),程序需要?jiǎng)?chuàng)建UnityAppController對象,也就是說UnityAppController.mm才是真正的程序入口革砸。
- 到UnityAppController.mm里先調(diào)用- (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary)launchOptions生命周期方法,進(jìn)行Unity界面初始化
- 然后則調(diào)用- (void)applicationDidBecomeActive:(UIApplication*)application方法,方法中設(shè)置了UnityPause(0);表示Unity為啟動(dòng)狀態(tài),在方法最后,執(zhí)行[self performSelector:@selector(startUnity:) withObject:application afterDelay:0];.
- 最后調(diào)用到-(void)startUnity:(UIApplication*)application方法,展示Unity游戲界面除秀,完成了原生OC和Unity的交互糯累。
ios 小7手游sdk接入演示
正常情況下要接入小7蘋果sdk,公司商務(wù)或者運(yùn)營會提供相應(yīng)的參數(shù)和接入文檔册踩。本文演示不提供文檔和參數(shù)泳姐。
進(jìn)入正題把小7 ios對應(yīng)的庫文件加入進(jìn)來,首先工程Libraries 創(chuàng)建一個(gè)文件夾(例如SDK文件夾),把小7依賴所有庫放到創(chuàng)建的SDK文件夾下,然后Libraries右鍵add files to Unity-iPhone ...把文件添加進(jìn)來(下圖是添加后的圖)暂吉,xcode 會自動(dòng)把小7的文件添加到對應(yīng)的庫和引用文件上胖秒。
按小7的文檔要求配置好info.plist文件然后需要設(shè)置的屬性也都弄好,準(zhǔn)備工作就完事慕的,然后進(jìn)行下一步阎肝。接入sdk其實(shí)可以在UnityAppController.mm文件中進(jìn)行的。但是為了清晰业稼,創(chuàng)建一個(gè)UnityIos.m(UnityIos.h可忽略)外部引用放在Libraries/SDK文件夾下盗痒。
有同學(xué)會奇怪我在Unity c#層定義好了例如登陸的方法蚂蕴,也沒看到在OC中調(diào)用暗蜕ⅰ?怎么拉起登陸啊骡楼。年輕人勿要著急繼續(xù)看熔号。在UnityIos.m中我們定義一個(gè)和c#層SDk_Login()名一樣的方法體。請看如下代碼:(這一部分代碼是真實(shí)項(xiàng)目中部分截取鸟整,其中包含了小7 sdk 完整的登陸 支付 切換賬號等功能
#import "UnityIos.h"
#import <Foundation/Foundation.h>
#import <AdSupport/AdSupport.h>
#import <SMSDK/SMSDK.h>
#import "UnityAppController.h"
#import "UnityInterface.h"
@implementation UnityIos
//調(diào)用sdk登陸
void SDk_Login(){
NSLog(@"SDk_Login");
[SMSDK smLogin];
}
//調(diào)用sdk切換賬號功能
void SDk_Logout(){
NSLog(@"SDk_Logout");
[SMSDK smLogout];
}
//這個(gè)方法只是為了兼容sdk
void SDk_SwitchAccount(){
NSLog(@"SDk_SwitchAccount");
}
//調(diào)用sdk支付引镊,游戲傳入sdk需要的參數(shù)數(shù)據(jù)(游戲客戶端協(xié)定好字段要統(tǒng)一)
void SDk_pay(void *payData){
NSLog(@"SDk_pay");
//直接傳json,oc無法識別所以要進(jìn)行一個(gè)轉(zhuǎn)化
NSString *idList = [NSString stringWithUTF8String:payData];
NSData *jsonData = [idList dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers error:&err];
if(err) {
NSLog(@"json解析失敗:%@",err);
return;
}
NSLog(@"dic解析:%@",dic);
NSString *_price = [NSString stringWithFormat:@"%@",[dic valueForKey:@"price"]];
NSString *_p_level = [NSString stringWithFormat:@"%@",[dic valueForKey:@"playerlevel"]];
NSString *_game_sign= [NSString stringWithFormat:@"%@",[dic valueForKey:@"game_sign"]];
NSString *_subject= [NSString stringWithFormat:@"%@",[dic valueForKey:@"subject"]];
NSString *_game_area= [NSString stringWithFormat:@"%@",[dic valueForKey:@"area"]];
NSString *_game_role_id= [NSString stringWithFormat:@"%@",[dic valueForKey:@"roleId"]];
NSString *_game_role_name= [NSString stringWithFormat:@"%@",[dic valueForKey:@"roleName"]];
NSString *_game_guid= [NSString stringWithFormat:@"%@",[dic valueForKey:@"guid"]];
SMPayInfo *payInfo = [[SMPayInfo alloc] init];
payInfo.game_orderid =[NSString stringWithFormat:@"%@",[dic valueForKey:@"orderid"]]; //游戲訂單號 60個(gè)字符
payInfo.game_sign =_game_sign; //服務(wù)器返回的簽名?????????????
payInfo.game_price =_price; //價(jià)格單位:元
payInfo.subject =_subject; //道具簡介
payInfo.game_area =_game_area; //角色所在區(qū)服
payInfo.game_level =_p_level; //角色等級
payInfo.game_role_id =_game_role_id; //角色I(xiàn)D
payInfo.game_role_name =_game_role_name; //角色名稱
payInfo.notify_id = @"-1"; //回調(diào)通知ID 默認(rèn)可以在后臺填寫
payInfo.extends_info_data = @""; //自定義擴(kuò)展數(shù)據(jù)
payInfo.game_guid=_game_guid; //游戲登陸后服務(wù)器通過token解析拿到的guid
//調(diào)用支付接口
[SMSDK smPayWithNewPayInfo:payInfo];
}
// 把格式化的JSON格式的字符串轉(zhuǎn)換成字典
// @param jsonString JSON格式的字符串
// @return 返回字典
- (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
if (jsonString == nil) {
return nil;
}
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&err];
if(err) {
NSLog(@"json解析失斃禾酢:%@",err);
return nil;
}
return dic;
}
@end
上面的代碼看完了弟头。還會有點(diǎn)小困惑,既然在Libraries/SDK/UnityIos.m文件下涉茧,OC是如何找到登陸方法的呢赴恨?UnityIos.m定義了SDk_Login(),這個(gè)方法在Classes/Native中能找到解釋,我給大家看一個(gè)圖啊.
這個(gè)圖就是在Unity c#層定義好的同名方法伴栓,編譯成了c++代碼放到了Xcode工程路徑下,成了溝通OC和c#的橋梁伦连。游戲用戶點(diǎn)擊登陸按鈕即可調(diào)用OC的登陸方法完成登陸的客戶端流程。
至于回調(diào)為什么放在UnityAppController.mm里钳垮,有兩個(gè)點(diǎn)惑淳,其一小7 sdk設(shè)計(jì)問題,要做個(gè)全局回調(diào)我不知道怎么弄饺窿,其二是游戲把初始化放在生命周期哪里處理的歧焦,不這樣寫我也沒什么好辦法,畢竟我不是一個(gè)真正的ios開發(fā)者肚医。正常的接sdk方法和回調(diào)都可以寫在UnityIos.m文件里面的倚舀。小7比較特殊啊所以這樣寫叹哭。到這里接入結(jié)束嘍,回調(diào)和相關(guān)代碼放在下面了痕貌。
#import <SMSDK/SMSDK.h>
#define SMSDKAppKey @"小7后臺申請的appKey"
@implementation UnityAppController //展示部分核心需要部分
- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary<NSString*, id>*)options
{
id sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey], annotation = options[UIApplicationOpenURLOptionsAnnotationKey];
NSMutableDictionary<NSString*, id>* notifData = [NSMutableDictionary dictionaryWithCapacity: 3];
if (url) notifData[@"url"] = url;
if (sourceApplication) notifData[@"sourceApplication"] = sourceApplication;
if (annotation) notifData[@"annotation"] = annotation;
AppController_SendNotificationWithArg(kUnityOnOpenURL, notifData);
return [SMSDK handleApplication:app openURL:url
sourceApplication:[options valueForKey:@"UIApplicationOpenURLOptionsSourceApplicationKey"]
annotation:[options valueForKey:@"UIApplicationOpenURLOptionsAnnotationKey"]];
}
//生命周期啟動(dòng)時(shí)調(diào)用sdk初始化方法(ios的生命周期跟安卓概念差不多)
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//省略了部分代碼
//設(shè)置全局回調(diào)
//初始化?
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(SMSDKInitCallback:) name:SMSDKInitDidFinishNotification object:nil];
//登陸
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(SMSDKLoginCallback:) name:SMSDKLoginNotification object:nil];
//注銷
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(SMSDKLogoutCallback:) name:SMSDKLogoutNotification object:nil];
//支付
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(SMSDKPayResultCallback:) name:SMSDKPayResultNotification object:nil];
//使用appKey初始化SDK
[SMSDK smInitWithAppKey:SMSDKAppKey];
return YES;
}
//初始化回調(diào)
- (void)SMSDKInitCallback:(NSNotification *)notify {
if (notify.object == kSMSDKSuccessResult) {
NSLog(@"初始化成功");
} else if (notify.object == kSMSDKFailedResult) {
NSLog(@"初始化失敗");
[SMSDK smInitWithAppKey:SMSDKAppKey]; //初始化失敗可以重新初始化
}
}
//登陸回調(diào)
- (void)SMSDKLoginCallback:(NSNotification *)notify {
NSLog(@"SMSDKLoginCallback");
if (notify.object == kSMSDKSuccessResult) {
NSLog(@"login callback success");
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSString *deviceUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSString *deviceModel = [[UIDevice currentDevice] model];
NSString *token = notify.userInfo[kSMSDKLoginTokenKey];
NSLog(@"解析token========:%@",token);
//這一步是和服務(wù)器協(xié)定需要的參數(shù)风罩,這里不做真實(shí)展示每個(gè)游戲邏輯都不一樣
NSDictionary *resultDict=@{@"":@1,@"":@"",@"":"",@"token":token,@"deviceUdid":deviceUUID,@"deviceId":deviceModel,@"idFa":idfa
};
NSData *data = [NSJSONSerialization dataWithJSONObject:resultDict options:NSJSONWritingPrettyPrinted error:nil];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"json解析:%@",string);
//向 Unity發(fā)送數(shù)據(jù)
// 參數(shù)1綁定的場景 參數(shù)2 為對象上的腳本的一個(gè)成員方法名稱(腳本名稱不限制)
//參數(shù)3傳遞的json數(shù)據(jù)。這個(gè)跟安卓的一樣舵稠。
UnitySendMessage("GameLaunch","OnSdkLoginSuc",[string cStringUsingEncoding:NSASCIIStringEncoding]);
} else {
NSLog(@"login callback fail");
}
}
//切換賬號回調(diào)
- (void)SMSDKLogoutCallback:(NSNotification *)notify {
NSLog(@"LogoutCallback");
}
//支付結(jié)果回調(diào)
- (void)SMSDKPayResultCallback:(NSNotification *)notify {
//支付結(jié)果
if (notify.object == kSMSDKSuccessResult) {
//支付成功超升,刷新用戶數(shù)據(jù)
NSLog(@"支付成功");
} else if (notify.object == kSMSDKUserCancelResult) {
NSLog(@"支付取消");
} else if (notify.object == kSMSDKFailedResult) {
//支付錯(cuò)誤,刷新用戶數(shù)據(jù)哺徊,保障不漏單
NSString *errMsg = notify.userInfo[kSMSDKErrorShowKey];
errMsg = errMsg && [errMsg isEqualToString:@""] ? errMsg : @"支付失敗";
NSLog(@"支付錯(cuò)誤");
}
}
為了方便只展示結(jié)果室琢,展示初始化成功,意味著 sdk初始化接入是沒問題的
感悟
應(yīng)標(biāo)題那句話接入ios SDK沒有你想的那么難落追,這不是噱頭這是我真實(shí)的感受盈滴。我是一個(gè)搞安卓SDK的程序員,ios里面的很多思想都是和安卓Java 相通的文中我也做過解釋轿钠。只要你會用安卓接sdk巢钓,那么ios也不是那么難。大家要是有興趣可以看下Android sdk接入Unity 與 Android交互通信 之OPPO篇疗垛。
剛開始弄的時(shí)候症汹,我承認(rèn)我非常無助,找了oc語法大全贷腕”痴颍看了一會就看不下了治唤,即使看了一會也就忘了惶凝。等真正去操作的時(shí)候(實(shí)踐才是正道,光看知識點(diǎn)一會就忘)啄巧,發(fā)現(xiàn)真沒那么難涮总。思想上跟安卓接sdk一樣的,就是語法略微不同胸囱。稍微查一下就知道怎么搞了。如果文章對你有幫助留下一個(gè)贊唄妹卿,你的支持是我繼續(xù)寫下去的動(dòng)力旺矾。
收尾
寫博文不易,希望大家多多支持夺克,如有不對大家多多指正箕宙。寫出來就是記錄、學(xué)習(xí)和成長的過程铺纽。