iOSネットワーク要求モジュールパッケージ-OC

10307 ワード

SwiftのAlamofireを長く使ってから、OCのアイテムを振り返って書く-request:success:failure:このような形式のネットワークリクエストはあまり慣れていません......そこでAFNetworking 3に基づいてパッケージ化しました.1フレームAlamofireスタイルのネットワークリクエストモジュール
コードgithubアドレス:ARKHTTPModule
きほんきのう
  • 要求の作成
  • 取得要求のステータスプロセス
  • 要求動作
  • 応答
  • これらの基本機能のクラスはARKRequestです
    1、要求の作成
    要求アドレス、要求パラメータなどからネットワーク要求インスタンスを作成する
    //    HTTP  ,  GET  ,      15 
    + (instancetype)requestWithURLString:(NSString *)URLStr
                              parameters:(nullable NSDictionary *)params;
    
    + (instancetype)requestWithMethod:(ARKRequestMethod)method
                           serializer:(ARKRequestSerializerType)serializer
                            URLString:(NSString *)URLStr
                           parameters:(nullable NSDictionary *)params
                       requestTimeout:(NSTimeInterval)timeout;
    
    //   
    + (instancetype)uploadWithType:(ARKSessionType)type
                         URLString:(NSString *)URLStr
                        parameters:(nullable NSDictionary *)params
                          fromData:(nullable NSData *)bodyData;
    
    //   
    + (instancetype)downloadWithType:(ARKSessionType)type
                           URLString:(NSString *)URLStr
                          parameters:(nullable NSDictionary *)params
                         destination:(nonnull DownloadDidFinishTargetBlock)destination;
    
    // etc...
    

    2、取得要求のステータスプロセス
    リクエストの進行状況、実行中、一時停止中、キャンセル中、バックグラウンドリクエスト完了ステータスは、次の方法で取得できます.
    //     
    - (ARKRequest *(^)(_Nullable ProgressBlock))requestProgressBlock;
    
    //       
    - (ARKRequest *(^)(_Nullable RequestStateBlock))requestWillResume;
    
    //       
    - (ARKRequest *(^)(_Nullable RequestStateBlock))requestWillSuspend;
    
    //       
    - (ARKRequest *(^)(_Nullable RequestStateBlock))requestWillCancel;
    
    //         
    - (ARKRequest *(^)(_Nullable SessionDidFinishEventsForBackgroundURLSessionBlock))didFinishEventsForBackgroundURLSession;
    

    3、要求された操作
    リクエストの開始、一時停止、キャンセルなどの操作を行う
    //     
    - (ARKRequest *(^)(void))resume;
    
    //     
    - (ARKRequest *(^)(void))suspend;
    
    //     
    - (ARKRequest *(^)(void))cancel;
    

    4、応答
    ここではAlamofireのリクエスト完了コールバック形式ARKRequestクラスにNSOperationQueueシリアルキューがあります.このキューは、作成時に一時停止状態にあるユーザーがResponseを使用してコードを追加したときに、このキューにBlockコードを入れます.応答がある場合、キュー内のBlockを順次実行します.
    //   NSData
    - (ARKRequest *(^)(ResponseDataBlock))responseDataOnMainThread;
    
    //   NSString
    - (ARKRequest *(^)(ResponseStringBlock))responseStringOnMainThread;
    
    //   JSON(NSArray NSDictionary)
    - (ARKRequest *(^)(ResponseJSONBlock))responseJSONOnMainThread;
    
    //   JSON    (      JSON    )
    //             < ARKMappableObject >  
    //    JSON   ,      Class            
    - (ARKRequest *(^)(ResponseMappableObjectBlock, Class))responseMappableObjectOnMainThread;
    
    //   JSON      (      JSON    )
    //   ,  JSON  ,        
    - (ARKRequest *(^)(ResponseMappableObjectArrayBlock, Class))responseMappableObjectArrayOnMainThread;
    
    //     
    @protocol ARKMappableObject 
    + (nullable id)objectWithResponseObject:(id)object;
    @end
    
    @protocol ARKMappableObjectArray 
    + (nullable NSArray> *)arrayWithResponseObject:(id)object;
    @end
    

    リクエスト例
    仮にJSONデータを要求
    - (IBAction)startRequest:(UIButton *)sender {
      //     
      ARKRequest *request = [ARKRequest requestWithURLString:@"http://www.example.com/json" parameters:nil];
    
      //   self   request,  block  self        ,  block        
      //    ,        (  ViewController)         
      //             ,         ,    block   weak self
      request.requestWillResume(^(ARKRequest *request) {
        
          //         ,      
          [self showLoadingView];
        
      }).requestProgressBlock(^(NSProgress *progress) {
        
          //     ,requestProgressBlock     
          dispatch_async(dispatch_get_main_queue(), ^{
              self.progressView.progress = (float)progress.completedUnitCount / (float)progress.totalUnitCount;
          });
        
      }).responseJSONOnMainThread(^(NSURLSessionTask *task, id json, NSError *error) {
        
          //       
          [self hideLoadingView];
          NSLog(@"    , thread: %@", [NSThread currentThread]);
        
          if (error == nil) {
              //     
              [self requestSuccessWithJSON:json];
          } else {
              //     
              [self requestFailureWithError:error];
          }
    
      }).resume();
    }
    

    補助クラス
    他にも2つの補助クラスがあります.
  • ARKRequestCacheManager
  • ARKNonRepetitiveRequestManager

  • ARKRequestCacheManager重複しない要求を開始するためのキャッシュ要求ARKNonRepetiveRequestManager
    1、ARKRequestCacheManager(単例)
    ARKRequestCacheManagerを使用してネットワークリクエストを開始すると、managerはリクエストインスタンスをキャッシュします.リクエストが完了すると、managerは対応するリクエストインスタンスを削除します.このアシストクラスを使用して、リクエストの一時停止とキャンセルを簡単に実現できます.
    ARKRequestCacheManagerを使用して開始されたダウンロード要求の場合、managerはerrorからダウンロードに失敗します.userInfo辞書では、NSURLSessionDownloadTaskResumeDataを取り出し、URLをキーとしてNSCacheにキャッシュし、ディスクCacheディレクトリの下に保存します.
    次回ダウンロードリクエストを開始すると、URLによりローカルにブレークポイントデータがあるか否かが判断されます
  • ブレークポイントデータがある場合、-downloadWithType:resumeData:destination:ブレークポイント継続
  • が呼び出されます.
  • ブレークポイントデータがない場合は、ダウンロード要求
  • を再作成する.
    ARKRequestCacheManagerを使用してネットワークリクエストを開始
    - (void)startDownload {
        
        //    ARKRequestCacheManager       
        // ARKRequestCacheManager        ,      
        //       ,          ,                    
    
        ARKRequestCacheManager *manager = [ARKRequestCacheManager sharedManager];
        ARKRequest *request = [manager downloadWithType:ARKSessionTypeDefault 
                                              URLString:kURLString
                                             parameters:nil
                                            destination:^NSURL * _Nonnull(NSURL * _Nonnull location, NSURLResponse * _Nonnull response) {
            
            //       
            NSString *documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
            NSString *path = [documentDir stringByAppendingPathComponent:@"image.jpg"];
    
            // TODO: = =
            //     fileURL,    response      
            return [NSURL fileURLWithPath:path];
        }];
        
        
        __weak typeof(&*self) weakSelf = self;
        
        request.requestWillResume(^(ARKRequest *request) {
            
            //       
            [weakSelf showLoadingView];
            
        }).requestWillSuspend(^(ARKRequest *request) {
            
            NSLog(@"      ,state: %ld", request.task.state);
            
        }).requestProgressBlock(^(NSProgress *progress) {
            
            //      
            dispatch_async(dispatch_get_main_queue(), ^{
                weakSelf.progressView.progress = (float)progress.completedUnitCount / (float)progress.totalUnitCount;
            });
            
        }).responseDataOnMainThread(^(NSURLSessionTask *task, NSData *data, NSError *error) {
            
            //       
            [weakSelf hideLoadingView];
            
            NSLog(@"    , thread: %@", [NSThread currentThread]);
            
            if (error != nil) {
                [weakSelf showErrorMessage:[NSString stringWithFormat:@"    , error:%@", error.localizedDescription]];
                return ;
            }
            
            if (data == nil || [data isKindOfClass:[NSNull class]]) {
                [weakSelf showErrorMessage:[NSString stringWithFormat:@"     "]];
                return ;
            }
            
            weakSelf.imageView.image = [UIImage imageWithData:data];
    
        }).resume();
    }
    
    //   
    - (IBAction)suspendDownload {
        //   ARKRequestCacheManager     
        ARKRequest *request = [[ARKRequestCacheManager sharedManager] requestCacheWithURLString:kURLString];
        if (request != nil) {
            request.suspend();
            [self hideLoadingView];
        }
    }
    
    //   
    - (IBAction)resumeDownload {
        //   ARKRequestCacheManager     
        ARKRequest *request = [[ARKRequestCacheManager sharedManager] requestCacheWithURLString:kURLString];
    
        if (request != nil && (request.state == NSURLSessionTaskStateSuspended)) {
            //     
            request.resume()
            [self showLoadingView];
        } else {
            //     
            [self startDownload];
        }
    }
    

    2、ARKNonRepetitiveRequestManager(単例)
    ARKNonRepetitiveRequestManagerも同様にARKRequestCacheManageの機能を持ち、ARKNonRepetiveRequestManagerを使用して複数の同じリクエストを開始する場合、最初に開始したリクエストのみが有効になり、残りのリクエストは無視されます.
    ARKNonRepetitiveRequestManagerを使用してネットワークリクエストを開始
    - (IBAction)backgroundDownload:(UIButton *)sender {
        ARKNonRepetitiveRequestManager *manager = [ARKNonRepetitiveRequestManager sharedManager];
    
        //                ,        
        ARKRequest *request = [manager downloadWithType:ARKSessionTypeBackground //     
                                              URLString:kImageURLString
                                             parameters:nil
                                            destination:^NSURL * _Nonnull(NSURL * _Nonnull location, NSURLResponse * _Nonnull response) {
            
            NSString *documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
            NSString *path = [documentDir stringByAppendingPathComponent:@"BackgrounDownloadImage.jpg"];
            return [NSURL fileURLWithPath:path];
        }];
        
        __weak typeof(&*self) weakSelf = self;
        
        request.responseDataOnMainThread(^(NSURLSessionTask *task, NSData *data, NSError *error) {
            
            NSLog(@"    , thread: %@", [NSThread currentThread]);
            
            if (data.length > 0) {
                weakSelf.imageView.image = [UIImage imageWithData:data];
            }
    
        }).didFinishEventsForBackgroundURLSession(^(NSURLSession *session) {
            NSLog(@"      ");
            
            AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
            void(^completionHandler)() = delegate.didFinishEventsForBackgroundURLSession;
            delegate.didFinishEventsForBackgroundURLSession = nil;
            
            //             ,          
            completionHandler();
            
        }).resume();
    }
    

    その他
    現在OCのフレームワークにおけるネットワーク層は依然として-request:success:failure:の呼び出し形式(結局成熟しており、呼び出し形式がより普及している==)というネットワークモジュールのパッケージは一時的に興っており、セキュリティメカニズムの問題など、考慮されていない問題が多く、要するに完璧である必要がある.
    皆さんのご提案を歓迎します