代码之家  ›  专栏  ›  技术社区  ›  Curt Rand

目标C:是否有一种方法可以为另一个方法中的方法调用完成块?

  •  0
  • Curt Rand  · 技术社区  · 6 年前

    我有多重 GET API请求在完成时调用完成块的方法。下面是一个例子。

    - (void)getUserInfo
        onSuccess:(void (^)(id))successBlock
        onFailure:(void (^)(NSError *))failureBlock {
    
        NSString *urlStr = [NSString stringWithFormat:@"%@/user/", baseUrl];
    
        [manager GET:urlStr parameters:nil progress:nil
              success:^(NSURLSessionTask *task, id responseObject) {
                  successBlock(responseObject);
              }
              failure:^(NSURLSessionTask *operation, NSError *error) {
                  failureBlock(error);
              }];
    }
    

    但是,我注意到我在重复经理的话 得到 用其他方法请求代码。我想创建另一个方法来处理所有请求并删除重复的代码。URL似乎是唯一改变的东西。然而,有一个缺陷。我需要打电话给 successBlock 让方法知道请求已经完成。

    也许我需要走另一条路,做些不同的事情。

    2 回复  |  直到 6 年前
        1
  •  2
  •   R4N    6 年前

    您可以传递完成块,然后从处理所有GET请求的最终方法调用它们。为了简洁起见,我通常制作将被重用的typedef的完成块。这是我的意思的一个例子 getRequestWithURLString:onSuccess:onFailure: 方法:

    拉法克曼

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    typedef void (^_Nullable SuccessCompletionBlock)(id responseObject);
    typedef void (^_Nullable FailureCompletionBlock)(NSError *error);
    
    @interface LLFakeManager : NSObject
    - (void)getUserInfoOnSuccess:(SuccessCompletionBlock)successBlock onFailure:(FailureCompletionBlock)failureBlock;
    - (void)getBooksCheckedOutOnSuccess:(SuccessCompletionBlock)successBlock onFailure:(FailureCompletionBlock)failureBlock;
    @end
    
    NS_ASSUME_NONNULL_END
    

    拉法克曼

    #import "LLFakeManager.h"
    
    @interface LLFakeManager()
    - (void)getRequestWithURLString:(NSString *)urlString
                          onSuccess:(SuccessCompletionBlock)successBlock
                          onFailure:(FailureCompletionBlock)failureBlock;
    @end
    
    @implementation LLFakeManager
    
    - (void)getUserInfoOnSuccess:(SuccessCompletionBlock)successBlock onFailure:(FailureCompletionBlock)failureBlock {
        NSString *urlStr = @"FakeUserUrlPath";
        [self getRequestWithURLString:urlStr onSuccess:successBlock onFailure:failureBlock];
    }
    
    - (void)getBooksCheckedOutOnSuccess:(SuccessCompletionBlock)successBlock onFailure:(FailureCompletionBlock)failureBlock {
        NSString *urlString = @"FakeBooksUrlPath";
        [self getRequestWithURLString:urlString onSuccess:successBlock onFailure:failureBlock];
    }
    
    // central method that will handle all the get requests
    - (void)getRequestWithURLString:(NSString *)urlString
                          onSuccess:(SuccessCompletionBlock)successBlock
                          onFailure:(FailureCompletionBlock)failureBlock {
        // some fake implementation here to do your request, then use the completion block passed in from whatever other method
        if (successBlock) {
            successBlock(@"responseObjectPassedBackHere");
        }
    }
    
    @end
    

    举个例子:

    LLFakeManager *manager = [[LLFakeManager alloc] init];
    [manager getUserInfoOnSuccess:^(id  _Nonnull responseObject) {
        NSLog(@"Here's my response object = %@", responseObject);
    } onFailure:^(NSError * _Nonnull error) {
        // no implementation but same idea
    }];
    

    将生成此日志:

    Here's my response object = responseObjectPassedBackHere
    

    本网站: http://goshdarnblocksyntax.com 是一个方便的块语法列表,它也可能对您有所帮助。

        2
  •  0
  •   danh    6 年前

    这些块——如果它们有相同的签名——就可以沿着一系列方法传递。GET块带有一个不必要的第一个参数。这个 NSURLSessionTask * 如果要返回,则应同步返回。将其移出块签名将允许您标准化块。

    用代码更容易说…

    // changed this method name so it would compile
    
    - (void)getUserInfoOnSuccess:(void (^)(id))successBlock
                       onFailure:(void (^)(NSError *))failureBlock {
    
        NSString *urlStr = [NSString stringWithFormat:@"%@/user/", baseUrl];
    
       // two things: get the task as a return value (if you need it)
       // pass the blocks directly, without nesting them in new blocks
        NSURLSessionTask *task = [manager GET: urlStr
                                   parameters: nil
                                     progress: nil
                                      success: successBlock
                                      failure: failureBlock];
        // do something with the task
    }
    

    若要使此工作,请更改get方法返回类型和块签名…

    - (NSURLSessionTask *)GET:(NSString *)url parameters:(id)params progress:(id)progress success:(void (^)(id))successBlock failure:(void (^)(NSError *))failureBlock {
        // return the session task created here
        return task
    }
    
    推荐文章