项目中集成了环信,点击联系客服时须要调取环信的接口,如今有个要求,若是调取环信的登陆接口失败了,就要从新登陆,可是这个操做不能影响主线程的操做,登陆次数达到必定的数量后中止登陆。
首先:环信的登陆时同步的,须要咱们开启一个线程,否则当环信登陆失败时会很容易形成界面卡死的状况。
+ (void)loginWithSuccessBlock:(void(^)())success FailureBlock:(void(^)())failure{ // 本身封装的一个公共类
// 开启一个线程防止登陆失败时形成主线程卡死
NSOperationQueue *q = [[NSOperationQueue alloc]init];
[q addOperationWithBlock:^{
EMError *error = [[EMClient sharedClient] loginWithUsername:USER_NAME password:@"123456"];
// 主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
if (!error)
{
[[EMClient sharedClient].options setIsAutoLogin:YES];
success();
}else{
failure(); // 登陆失败调取另外一个方法继续尝试登陆,登陆5次中止登陆
[[[self alloc] init] HXLoginFailed];
}
}];
}];
}
而后就是登陆失败 开启一个线程继续登陆,登陆5次后中止登陆
- (void)HXLoginFailed
{
[self.thread cancel];
self.thread = nil;
NSString* countStr = [SKUserDefaults valueForKey:@"HXCount"];
if ([countStr intValue]>5) {
return;
}
DLog(@"========%@=====%d",[NSThread currentThread],[countStr intValue]);
self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(HXLoginFailed2) object:nil];
[self.thread start];
self.requestCount++;
}
- (void)HXLoginFailed2
{
EMError *error = [[EMClient sharedClient] loginWithUsername:USER_NAME password:@"123456"];
if (error) {
NSString* countStr = [SKUserDefaults valueForKey:@"HXCount"];
countStr = [NSString stringWithFormat:@"%d",[countStr intValue]+1];
[SKUserDefaults setValue:countStr forKey:@"HXCount"];
[self HXLoginFailed];
} else {
}
}
------------------------------------------------------------------------华丽分割线---------------------------------------------------------------------------------------------
最后看看NSOperation怎么实现
原理:只要将一个NSOperation(实际开中须要使用其子类NSInvocationOperation、NSBlockOperation)放到NSOperationQueue这个队列中线程就会依次启动。
NSOperation有两个经常使用子类用于建立线程操做:NSInvocationOperation和NSBlockOperation,两种方式本质没有区别,可是是后者使用Block形式进行代码组织,使用相对方便。
- (instancetype)init
{
self = [super init];
if (self) {
self.OperationQueue = [[NSOperationQueue alloc]init];
self.OperationQueue.maxConcurrentOperationCount = 1;
}
return self;
}
+ (void)loginWithSuccessBlock:(void(^)())success FailureBlock:(void(^)())failure{
// 开启一个线程防止登陆失败时形成主线程卡死
NSOperationQueue *q = [[NSOperationQueue alloc]init];
[q addOperationWithBlock:^{
EMError *error = [[EMClient sharedClient] loginWithUsername:USER_NAME password:@"jimaijie654321"];
// 主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
if (!error)
{
[[EMClient sharedClient].options setIsAutoLogin:YES];
success();
}else{
failure();
[SKUserDefaults setValue:@"0" forKey:@"HXCount"];
[[[self alloc] init] HXLoginFailed];
}
}];
}];
}
- (void)HXLoginFailed
{
NSString* countStr = [SKUserDefaults valueForKey:@"HXCount"];
if ([countStr intValue]>5) {
self.OperationQueue = nil;
return;
}
DLog(@"========%@=====%d",[NSThread currentThread],[countStr intValue]);
[self.OperationQueue addOperationWithBlock:^{
DLog(@"+++++++++++++%@=====%d",[NSThread currentThread],[countStr intValue]);
EMError *error = [[EMClient sharedClient] loginWithUsername:USER_NAME password:@"jimaijie654321"];
// 主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
if (!error)
{
[[EMClient sharedClient].options setIsAutoLogin:YES];
}else{
NSString* countStr = [SKUserDefaults valueForKey:@"HXCount"];
countStr = [NSString stringWithFormat:@"%d",[countStr intValue]+1];
[SKUserDefaults setValue:countStr forKey:@"HXCount"];
[self HXLoginFailed];
}
}];
}];
}线程