首页 > 代码库 > 线程阻塞问题-功能:环信登录失败后自动登录5次
线程阻塞问题-功能:环信登录失败后自动登录5次
项目中集成了环信,点击联系客服时需要调取环信的接口,现在有个要求,如果调取环信的登录接口失败了,就要重新登录,但是这个操作不能影响主线程的操作,登录次数达到一定的数量后停止登录。
首先:环信的登录时同步的,需要我们开启一个线程,不然当环信登录失败时会很容易造成界面卡死的情况。
+ (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];
}
}];
}];
}
线程阻塞问题-功能:环信登录失败后自动登录5次