ios – 通过重试将NSOperation子类化为互联网 *** 作

ios – 通过重试将NSOperation子类化为互联网 *** 作,第1张

概述我在后台线程中将NSOperation子类化为http post. 那些特定的http帖子不需要返回任何值. 我想要做的是当我出现错误或超时时我希望它在增加延迟后发送(斐波那契). 到目前为止我已经这样做了: NSInternetOperation.h: #import <Foundation/Foundation.h>@interface NSInternetOperation : NSOp 我在后台线程中将NSOperation子类化为http post.
那些特定的http帖子不需要返回任何值.

我想要做的是当我出现错误或超时时我希望它在增加延迟后发送(斐波那契).

到目前为止我已经这样做了:

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 sethttpMethod:@"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子类化为互联网 *** 作所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1065901.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存