大佬教程收集整理的这篇文章主要介绍了ios – 通过重试将NSOperation子类化为互联网操作,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我想要做的是当我出现错误或超时时我希望它在增加延迟后发送(斐波那契).
到目前为止我已经这样做了:
NSInternetOperation.h:
#import <Foundation/Foundation.h> @interface NSInternetOperation : NSOperation @property (nonatomiC) BOOL execuTing; @property (nonatomiC) BOOL finished; @property (nonatomiC) BOOL completed; @property (nonatomiC) BOOL cancelled; - (id)initWebservicename:(NSString*)webservicename andPerameters:(NSString*)parameters; - (void)start; @end
NSInternetOperation.m:
#import "NSInternetOperation.h" static NSString * const kFinishedKey = @"isFinished"; static NSString * const kExecuTingKey = @"isExecuTing"; @interface NSInternetOperation () @property (strong,nonatomiC) NSString *servicename; @property (strong,nonatomiC) NSString *params; - (void)completeOperation; @end @implementation NSInternetOperation - (id)initWebservicename:(NSString*)webservicename andPerameters:(NSString*)parameters { self = [super init]; if (self) { _servicename = webservicename; _params = parameters; _execuTing = NO; _finished = NO; _completed = NO; } return self; } - (BOOL)isExecuTing { return self.execuTing; } - (BOOL)isFinished { return self.finished; } - (BOOL)isCompleted { return self.completed; } - (BOOL)isCancelled { return self.cancelled; } - (BOOL)isConcurrent { return YES; } - (void)start { if ([self isCancelled]) { [self willChangeValueForKey:kFinishedKey]; self.finished = YES; [self didChangeValueForKey:kFinishedKey]; return; } // If the operation is not cancelled,begin execuTing the task [self willChangeValueForKey:kExecuTingKey]; self.execuTing = YES; [self didChangeValueForKey:kExecuTingKey]; [self main]; } - (void)main { @try { // // Here we add our asynchronized code // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{ NSURL *completeURL = [NSURL URLWithString:[NSString StringWithFormat:@"%@/%@",kWEB_serviCE_URL,self.servicename]]; NSData *body = [self.params dataUsingEncoding:NSUTF8StringEncoding]; NSMutableURLrequest *request = [[NSMutableURLrequest alloc] initWithURL:completeURL]; [request sethttpR_123_11845@ethod:@"POST"]; [request SETVALue:kAPP_password_VALUE forhttpHeaderField:kAPP_password_HEADER]; [request sethttpBody:body]; [request SETVALue:[NSString StringWithFormat:@"%lu",(unsigned long)body.length] forhttpHeaderField:@"Content-Length"]; [request SETVALue:@"application/x-www-form-urlencoded" forhttpHeaderField:@"Content-Type"]; if (__iOS_7_AND_HIGHER) { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:[Netroads sharedInstance] delegateQueue:[NSOperationQueue new]]; NSURLSessionDataTask *dataTask = [session dataTaskWithrequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) { if (error) { NSLog(@"%@ Error: %@",self.servicename,error.localizedDescription); } else { //NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //NSLog(@"\n\nResponseXML(%@):\n%@",webservicename,responseXML); } }]; [dataTask resume]; } else { [NSURLConnection sendAsynchronousrequest:request queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response,NSData *data,NSError *connectionError) { if (connectionError) { NSLog(@"%@ Error: %@",connectionError.localizedDescription); } else { //NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //NSLog(@"\n\nResponseXML(%@):\n%@",responseXML); } }]; } }); [self completeOperation]; } @catch (NSException *exception) { NSLog(@"%s exception.reason: %@",__PRETTY_FUNCTION__,exception.reason); [self completeOperation]; } } - (void)completeOperation { [self willChangeValueForKey:kFinishedKey]; [self willChangeValueForKey:kExecuTingKey]; self.execuTing = NO; self.finished = YES; [self didChangeValueForKey:kExecuTingKey]; [self didChangeValueForKey:kFinishedKey]; } @end
>在解决重试逻辑之前,您应该将对[self completeOperation]的调用移到NSURLSessionDataTask或sendAsynchronousrequest的完成块内.您当前的操作类过早地完成(因此不会遵循依赖关系和您的网络操作队列的预期maxConcurrentOperationCount).
>重试逻辑似乎不起眼.也许是这样的:
- (void)main { NSURLrequest *request = [self createrequest]; // maybe move the request creation stuff into its own method [self tryrequest:request currentDelay:1.0]; } - (void)tryrequest:(NSURLrequest *)request currentDelay:(NSTimeInterval)delay { [NSURLConnection sendAsynchronousrequest:request queue:[self networkOperationCompletionQueue] completionHandler:^(NSURLResponse *response,NSError *connectionError) { BOOL success = NO; if (connectionError) { NSLog(@"%@ Error: %@",connectionError.localizedDescription); } else { if ([response isKindOfClass:[NShttpURLResponse class]]) { NSInteger statusCode = [(NShttpURLResponse *)response statusCode]; if (statusCode == 200) { // parse XML response here; if successful,set `success` to `YES` } } } if (success) { [self completeOperation]; } else { dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_Now,(int64_t)(delay * NSEC_PER_SEC)); dispatch_after(popTime,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,^(void){ NSTimeInterval nextDelay = [self nextDelayFromCurrentDelay:delay]; [self tryrequest:request currentDelay:nextDelay]; }); } }]; }
>就个人而言,我对这整个努力都很谨慎.令我感到震惊的是你应该根据错误的类型使用逻辑.值得注意的是,如果由于缺少互联网连接而导致错误失败,则应使用Reachability确定连接并响应通知,以便在恢复连接时自动重试,而不是仅按重复间隔的规定数学级别重试.
除了网络连接(使用Reachability可以更好地解决)之外,我还不清楚其他网络故障是否需要重试逻辑.
一些不相关的观察:
>注意,我将main中请求发出的dispatch_async消除到后台队列,因为你已经使用了异步方法(即使你没有,你可能还是把这个操作添加到后台队列) .
>我还删除了try / catch逻辑,因为与其他语言/平台不同,异常处理不是处理运行时错误的首选方法.通常,Cocoa中的运行时错误是通过NSError处理的.在Cocoa中,异常通常仅用于处理程序员错误,但不用于处理用户将遇到的运行时错误.请参阅“使用Objective-C编程”指南中的Apple讨论Dealing with Errors.
>如果您只是在各自的声明中为属性定义适当的getter方法,则可以删除手动实现的isExecuTing和isFinished getter方法:
@property (nonatomic,readwrite,getter=isExecuTing) BOOL execuTing; @property (nonatomic,getter=isFinished) BOOL finished;
>但是,您可能希望编写自己的setExecuTing和setFinished setter方法,如果需要,可以为您执行通知,例如:
@synthesize finished = _finished; @synthesize execuTing = _execuTing; - (void)setExecuTing:(BOOL)execuTing { [self willChangeValueForKey:kExecuTingKey]; _execuTing = execuTing; [self didChangeValueForKey:kExecuTingKey]; } - (void)setFinished:(BOOL)finished { [self willChangeValueForKey:kFinishedKey]; _finished = finished; [self didChangeValueForKey:kFinishedKey]; }
然后,当您使用setter时,它会为您执行通知,并且您可以删除分散在代码中的willChangeValueForKey和didChangeValueForKey.
>另外,我认为您不需要实现isCancelled方法(因为已经为您实现了).但是你真的应该覆盖一个调用其超级实现的cancel方法,但是也会取消你的网络请求并完成你的操作.或者,您可以移动到基于委托的网络请求再现,而不是实现取消方法,但请确保在didReceiveData方法中检查[self isCancelled].
并且isCointed让我觉得与isFinished一样多余.看起来你可以完全消除已完成的属性和isCompleted方法.>您可能通过支持NSURLSession和NSURLConnection来不必要地重复网络代码的数量.如果你真的想要,你可以这样做,但他们向我们保证NSURLConnection仍然受支持,所以它让我觉得不必要(除非你想要享受iOS 7设备的一些NSURLSession特定功能,你目前没有这些功能).做任何你想要的,但就个人而言,我正在使用NSURLConnection,我需要支持早期的iOS版本,而NSURLSession,我不需要,但我不会倾向于实现它们,除非有一些令人信服的业务要求这样做.
以上是大佬教程为你收集整理的ios – 通过重试将NSOperation子类化为互联网操作全部内容,希望文章能够帮你解决ios – 通过重试将NSOperation子类化为互联网操作所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。