SDK 开发中,在处理业务时,应该开一个新线程来处理,主要的考虑是当业务逻辑比较重的时候,SDK不应该直接影响到使用者的产品。所以我们在启动 SDK 的时候开一个新线程,来处理 SDK 的业务逻辑:
sdkThread = [[NSThread alloc] initWithTarget:self
selector:@selector(sdkThreadMain)
object:nil];
[sdkThread start];
/*!
* 保持线程一直运行
*/
- (void)sdkThreadMain {
@autoreleasepool {
[sdkThread setName:@"cn.sdkSample.thread"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
然后我们可以通过 NSobject 中的 performSelector 方法来调用线程执行方法:
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
为了方便也可以自定义一个宏来调用,这里就不多说了。
在 SDK 中的对外接口都是不涉及线程的问题的,主要是内部方法的实现需要考虑是要用主线程,还是sdk线程,还是其它线程。因为方法可能有很多,所以可以考虑写一个统一的线程跳转方法:
- (void)sdkBridgeRequest {
//这里也可以做相应的过滤,比如SDK没有启动时就不允许调用接口
......
}
因为考虑到要跳转的目标是谁,应该传一个跳转目标:
- (void)sdkBridgeRequest:(SDKMainRequestBridge *)bridge {
}
这个跳转的目标为了适应大多场景,应该包含跳转类型、参数集 和 回调block,大概可以这样定义:
@interface SDKRequestBridge : NSObject
@property(nonatomic, assign) SDKRequestType type;
@property(nonatomic, strong) id parameter;
@property(nonatomic, copy) SDKCompletionHandler completionHandler;
@end
所以线程集中的跳转的方法可以写成这样:
- (void)sdkBridgeRequest:(SDKMainRequestBridge *)bridge {
if (过滤条件) {
return;
}
switch (bridge.type) {
case: .......
case: .......
}
}
举例个用户登录的例子:
NSDictionary *parameter = @{KEY_USERNAME : username,
KEY_PASSWORD : password,
};
SDKMainRequestBridge *bridge = [[SDKMainRequestBridge alloc] init];
bridge.parameter = parameter;
bridge.type = kUserLogin;
bridge.completionHandler = handler;
[类名 performSelector:@selector(sdkBridgeRequest:) onThread:SDK.sdkThread withObject:bridge waitUntilDone:NO];
统一跳转主要方便管理,还可以添加过滤器,其它就不多说了,可以根据实际的需求来做。
SDK线程相关的问题
在SDK里面,有些方法是用 SDK 线程执行的,有些方法是用到主线程执行的,根据实际的使用场景来定,但要注意的是,多线程同时访问同一个对象的问题,这可能会导致脏数据、死锁、crash等,要适当地使用多线程,或者根据需要添加锁。
当前我遇到了一个问题:我开发的 SDK 依赖于另外一个 SDK ,我在当前开发的 SDK 里面会调用另一个 SDK 的方法,别一个 SDK 也会主动去调用该方法,因为两个 SDK 不在同一个线程上,导致可能存在同时访问同一对象而出现问题。
最简单的解决方法是在调用的方法上面加个同步的锁,但方法有很多,不可能每个都加锁,另一个原因:那是别的人的 SDK,我根本不可能随便改~~~
有经验的朋友,如有更好解决办法的跪求分享一下,谢谢。
网友评论