在上一篇《TypeSDK安卓平台统一化接口结构及思路》中我们阐述了安卓平台的接口结构和思路。在这里我们将阐述iOS平台下的接口结构和思路。

       ios平台主要是基于Objective-C的语言,总体的设计思路和安卓类似,具体实现的细节和接口的结构会有细微的不同。

       在ios平台,我们会涉及到部分的c语法以及oc和c的混编,相对安卓需要注意点会多一点。

       那好,接下来我们来具体的阐述一下接口的结构,以及设计的思路。

       和安卓一样,我们先来看看需要考虑的几点需求。

一、相关的需求

       iOS平台的统一化接口,我们需要考虑到具体以下的几点:

       1.对外需要有统一的接口,保证不同的渠道sdk 对同一个游戏来说,是调用相同的接口,传递相同的参数

       2.对内需要有一套扩展性很好的框架,可以应对不同渠道的sdk差异性

二、设计的模块

       那么针对这些考虑点,安卓平台的统一化接口,我们将主要分成以下几个部分来设计:

       1.基础架构设计

       2.具体渠道实现类

       3.统一化对外平台接口

       4.跨平台交互的设计

三、具体的细节


TYPESDK手游聚合SDK客户端设计思路与架构之三:iOS平台统一化接口结构及思路-LMLPHP

我们主要实现了这么一套结构

1.我们创建通用的基础抽象类(BaseBonjour)。

       基于oc的特性,我们对基础类添加了2个protocol,一个是必须实现的基础接口,一个是可以不去实现的拓展接口的申明

       1.1必须实现的基础接口,我们做如下的定义

       1.1.1 初始化接口 @required-(void)InitSDK:(NSString*)_in_data;

       1.1.2  登录接口 @required-(void)ShowLogin:(NSString*)_in_data;

       1.1.3 登出接口 @required-(void)ShowLogout;

       1.1.4 支付接口@required-(NSString*)PayItem:(NSString*)_in_data;

       1.1.5 显示分享接口@required-(void)ShowShare:(NSString*)_in_data;


       1.2 非必需实现的拓展接口

       1.2.1 获取缓存在ios层的用户信息 @optional -(NSString*)GetUserData;

       1.2.2 获取本地渠道的配置 @optional -(NSString*)GetPlatformData;

       1.2.3 根据函数名,调用具体实现类中的函数@optional -(NSString*)DoAnyFunction:(NSString*)_funcNamewithArgs:(NSString*)_json_string;

       1.2.4 大退游戏(杀进程) @optional-(void)ExitGame;

       1.2.4 提交玩家数据 -(void)SetPlayerInfo:(NSString*)_in_data;

2.我们根据每一个渠道的sdk不同,单独创建每个渠道自己的实现类Bonjour_xx。

       2.1 这个类继承通用的框架基类(BaseBonjour)。

       2.2在该框架下,实现基类所有的必需实现的抽象接口。如果没有该接口的功能,也需要做出相应的处理,例如输出log日志。

       2.3同时该类可以增加渠道自有的特殊接口(例如获取好友列表)

3.发布平台有一个统一的给外部调用接口实现的类:TypeSDK

       3.1该类作为一个单例类,可以给在任何地方方便的提供接口的调用。

       3.2该类的单利对象是框架基类对象(BaseBonjour)

       3.3该类不是框架基类对象的子类

       3.4通过配置文件,利用类名,创建基类对象的子类,该子类是该渠道的具体实现类,该子类赋值给单利对象

       3.5所有的接口调用,通过获取TypeSDK类的单利对象来调用

具体的实现,可以参照以下一部分代码

单例对象


点击(此处)折叠或打开

  1. static TypeBaseBonjour* sharedInstance = nil;



获取单例对象的静态函数


点击(此处)折叠或打开

  1. @implementation TypeSDK
  2.  
  3. +(TypeBaseBonjour*)GetIns
  4. {
  5.  
  6.     if(nil == sharedInstance)
  7.     {
  8.         [self InitBonjourClass];
  9.     }
  10.     return sharedInstance;
  11. }
  12. @end


具体渠道实现类


点击(此处)折叠或打开

  1. @interface TypeBonjour_demo : TypeBaseBonjour
  2. @end



通过类名动态创建子类对象


点击(此处)折叠或打开

  1. Class _cls = NSClassFromString(_type_name);
  2.    
  3.    if(_cls && [_cls isSubclassOfClass:[TypeBaseBonjour class]])
  4.    {
  5.             NSLog(@"success get bonjour class");
  6.           sharedInstance = [[ _cls alloc]init];
  7.                NSLog(@"share instance address %p",sharedInstance);
  8.     }



这样 我们就可以让基础框架,具体实现,对外调用接口三方的耦合性进一步的降低。这三部分是可以完全各自独立维护。   

4.跨平台交互部分

       跨平台交互我们需要考虑两个方面

              a.如何将从发布平台调用开发平台函数

              b.如何将从开发平台调用发布平台函数

4.1.在ios层,我们只需要将需要给到unity调用的函数

       ios给unity调用,需要写c的接口。c和oc混编,需要吧相关的类文件后缀名从.m修改成.mm

       提供以下代码参考


点击(此处)折叠或打开

  1. @implementation TypeSDKExtern
  2.  
  3. @end
  4.  
  5. #if defined(__cplusplus)
  6. extern "C"
  7. {
  8. #endif
  9.  
  10.     void CallShowLogin ()
  11.     {
  12.        
  13.              [[TypeSDK GetIns]ShowLogin:@""];
  14.     }
  15.    
  16.    
  17. #if defined(__cplusplus)
  18. }
  19. #endif


有关c接口代码的一个注意点

       所有的返回值,需要返回的是常量,所以不能直接把原始oc代码里的char*返回出去,需要拷贝一份常量返回出去

       切记c的代码不要写在oc的类申明里面

另有情提供2个非常有用的小函数


点击(此处)折叠或打开

  1. #if defined(__cplusplus)
  2. extern "C"{
  3. #endif
  4.    
  5.     //字符串转化的工具函数
  6.    
  7.     NSString* SDKCreateNSString (const char* string)
  8.     {
  9.         if (string)
  10.             return [NSString stringWithUTF8String: string];
  11.         else
  12.             return [NSString stringWithUTF8String: ""];
  13.     }
  14.    
  15.     char* SDKMakeStringCopy( const char* string)
  16.     {
  17.         if (NULL == string) {
  18.             return NULL;
  19.         }
  20.         char* res = (char*)malloc(strlen(string)+1);
  21.         strcpy(res, string);
  22.         return res;
  23.     }
  24.    
  25.    
  26. #if defined(__cplusplus)
  27. }
  28. #endif



第一个函数是把 char*类型数据转换成nsstring*

第二个函数是 char*的拷贝函数

在unity中的调用oc层面的c接口举例


点击(此处)折叠或打开

  1. [DllImport("__Internal")]
  2. private static extern void CallShowLogin ();
  3. public void ShowLogin()
  4. {
  5.        CallShowLogin();
  6. }


在cocos2dx中调用c接口举例


点击(此处)折叠或打开

  1. extern void CallShowLogin ();
  2.  
  3. void showLogin()
  4. {
  5.        CallShowLogin();
  6. }


4.2.在unity层,提供了我们通用的跨平台调用接口


点击(此处)折叠或打开

  1. extern void UnitySendMessage(const char *, const char *, const char *);



我们只需要知道unity部分用来接收消息的脚本名字,需要执行的脚本函数名,以及传递的参数,就可以调用unity的响应函数了。

       以下给出调用举例


点击(此处)折叠或打开

  1. -(void)SendEvent:(NSString *)_notify_class_name withJson:(NSString *)_json_string
  2.        {
  3.                UnitySendMessage("TypeSDK" , [_notify_class_name UTF8String], [_json_string UTF8String]);
  4.        }



       综上ios向unity平台传递数据和调用函数,主要通过消息机制发送消息

       unity向安ios平台传递参数和调用函数,则是直接调用oc层的c接口。


       以上就是我们ios发布平台的聚合sdk设计思路细节,下一章我们将讲述unity聚合sdk的设计思路细节。

这个项目已开源,大家有兴趣可以自己研究或者参照项目编写自己的聚合SDK
项目地址:https://code.csdn.net/typesdk_code
项目地址:https://github.com/typesdk

09-29 04:39