美文网首页
编写SDK注意事项

编写SDK注意事项

作者: woniu | 来源:发表于2022-06-07 20:29 被阅读0次

SDK设计的几个原则:稳定性、可扩展性、无侵性、崩溃问题采集、相应位置的打点监听。

一、稳定性

SDK最最重要的一个原则就是稳定向,一般要保持崩溃率在万分之一二以下,否则用户那边是很难过的去的。那么我们要保证我们的稳定性就要做到以下几点来降低崩溃率。

1、对使用的数据进行安全化处理

不要太相信后端传过来的数据,有时候数据是nil让你崩的猝不及防,所以就需要对获取的数据进行安全化处理。
所谓安全化处理,就是我们使用类别的方法,进行安全化处理,比如NSString、NSArray、NSDictonry,要对内部的数据做判空等处理。防止出现调用的数据出现nil或者数组越界从而引发的崩溃。

2、初始化调用的方法要保证在主线程操作

用户调用的时候会有各种奇葩的调用,有的甚至在子线程调用SDK的初始化方法,SDK一些定时操作会失效,导致功能缺失问题。所以在SDK初始化的方法里面要强制进入主线程,杜绝线程方面的问题。

3、各种系统版本需要考虑,尽量要做到新老版本的方法判断调用。
  if (@available(iOS 15.0, *)) { //表区头会空出一段距离
        [UITableView appearance].sectionHeaderTopPadding = 0;
    }
4、接口稳定

接口并不轻易改变调用方法或者参数,有稳定回调、数据格式不发生变化等。这很重要,一旦修改,必然导致所有的客户都要修改,所以这是原则问题,在设计的时候就要考虑到。
1、所有的回调都在主线程。
2、无论成功还是失败,都要给出相应的结果。

5、对应的各个手机类型都要做好适配避免出现UI问题

二、可扩展性

SDK的接口要有扩展性,随着SDK的迭代,可能需要的传参有增加。这就需要我们扩展SDK,如果我们使用直接一个个传递参数的的方式调用就会让SDK的方法调用十分冗长且不优美,而且还要用户修改调用方法,多方面考虑这种方式都不合理。
所以,我们需要创建个对象,将传递的参数做为这个对象的属性,一旦需要增加参数,那么我们只需要增加属性就足够了,用户也只需要增加这个对象的参数配置就行了,调用方式也不用改变。

+ (BOOL)showMessage:(ZNMessageConfig *)config;

三、无侵性

1、不能影响宿主App功能。

SDK对于宿主App的依赖应该足够小,如不能跟宿主App起相同的类名、使用相同的扩展、依赖相同的第三方库等

2、不会导致宿主App卡顿。

内部所有操作应该尽可能放在自定义子线程中

3、尽量不使用第三方库。

使用三方库这个是难免的,所以我们需要注意避免和用户的三方库产生冲突。
a、需要rename类名包括类别以及类别方法,加上本公司的特定标识。
b、extern 声明的外部全局变量,也是都需要修改的。

.h文件声明
初始化接口
extern NSString * const kAPIInitGet;
.m文件实现
NSString * const kAPIInitGet =@"/sdk/api/v4.0/ticket/uploadlog";

拓展:在开发中,我们通常会单独抽一个类来管理一些全局的变量或常量,通常搞一个GlobeConst文件,里面专门定义全局常量或常量。
extern和#defineh定义的区别:
extern与const组合:只需要定义一份全局常量或变量,多个文件共享。编译时刻,有类型检查,const仅仅用来修饰右边的变量,被const修饰的变量是只读的。
#define 预编译,简单的字符串替换,没有类型检查,可以预编译表达式,也可以定义常量

四、崩溃问题采集

由于SDK在线上会面临各种各样的问题,所以我们需要实时统计SDK的崩溃问题,并及时修复,所以需要我们对SDK内的崩溃进行统计并上传。
注册unCaughtExceptionHandler(),发现崩溃及时上报。

1、采集的重点

除了还需要采集崩溃的堆栈信息,还需要添加上附加信息,比如手机系统版本号、手机型号、SDK版本号等等重要标识,方便我们定位问题。

2、发送时机

不能在崩溃的时候直接发送给服务器,会导致我们收不到发送成功还是失败的信息,我们会在下次启动初始化SDK的时候发送出去。

.h文件:
+ (void)setDefaultHandler;

.m文件:
#import "ANCrashHandler.h"
#import "ANExceptionCollection.h" //采集崩溃信息存储起来
#import <math.h>

static NSUncaughtExceptionHandler *defaultExceptionHandler;

// 崩溃时的回调函数
void ANCrashHandler(NSException * exception) {
    // 数组越界,字典nil,调用未知方法.等等还有崩溃的控制器以及方法
    NSArray *arr = [exception callStackSymbols]; 
    NSString *callStackSymbols = [[arr subarrayWithRange:NSMakeRange(0, fmin(10, arr.count - 1))] componentsJoinedByString:@"\n"];
    BOOL isAN = [callStackSymbols containsString:@"ANMSS"];//采集SDK的文件标识
    if ([callStackSymbols AN_notEmpty] && isAN) {
        NSArray *components = [callStackSymbols componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        components = [components filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"self <> ''"]];
        NSString *stacktrace = [components componentsJoinedByString:@" "];        
        NSString *message = [NSString stringWithFormat:@"%@ %@", exception.name, exception.reason];
        [ANExceptionCollection anExceptionMessageSaveWithStacktrace:stacktrace message:message timestamp:@([AHSystemTool getTimestamp]) type:@"fatal"]; //加上自己的崩溃标识,比如版本号、手机型号
    }
    
    if (defaultExceptionHandler) {
        defaultExceptionHandler(exception);
    }
    
 }

@implementation ANCrashHandler
+ (void)setDefaultHandler {
    defaultExceptionHandler = NSGetUncaughtExceptionHandler();
    NSSetUncaughtExceptionHandler(&ANCrashHandler);
}
@end

相关文章

网友评论

      本文标题:编写SDK注意事项

      本文链接:https://www.haomeiwen.com/subject/nzwemrtx.html