使用AFNetworking和ReactiveCocoa时如何重构几乎相同的逻辑?

时间:2014-05-06 13:39:30

标签: objective-c refactoring afnetworking-2 reactive-cocoa

我有几种方法可以返回由

创建的信号
+ (RACSignal *)createSignal:

在信号中,我使用AFNetworking中AFHTTPRequestOperationManager的方法发送不同的请求:

- GET:parameters:success:failure
- POST:parameters:success:failure
- PUT:parameters:success:failure
- DELETE:parameters:success:failure

假设我有一个属性来存储AFHTTPRequestOperationManager的实例:

@property(strong, nonatomic) AFHTTPRequestOperationManager *manager;

这是GET请求方法的主体,除了来自AFHTTPRequestOperationManager的方法调用之外,其他几乎与它相同:

- (RACSignal *)GET:(NSString *)url parameters:(NSDictionary *)parameters {
  @weakify(self)
  return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    @strongify(self)
 // [self.manager POST:...
 // [self.manager PUT:...
 // [self.manager DELETE:...
    [self.manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, NSDictionary *response) {
      [subscriber sendNext:response];
      [subscriber sendCompleted];
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      [subscriber sendError:error];
  }];
  return nil;
}];

我想提取[self.manager GET...]逻辑,以便我可以消除重复的代码,只传递不同的选择器(或类似的东西)来发送不同的请求。

我如何实现它?

3 个答案:

答案 0 :(得分:2)

这是未经测试的,但应该让你大部分时间都在那里:

- (RACSignal *)GET:(NSString *)url parameters:(NSDictionary *)parameters {
  SEL sel = @selector(GET:parameters:success:failure:);
  return [self signalForRequest:sel url:url parameters:parameters];
}

- (RACSignal *)POST:(NSString *)url parameters:(NSDictionary *)parameters {
  SEL sel = @selector(POST:parameters:success:failure:);
  return [self signalForRequest:sel url:url parameters:parameters];
}

- (RACSignal *)PUT:(NSString *)url parameters:(NSDictionary *)parameters {
  SEL sel = @selector(PUT:parameters:success:failure:);
  return [self signalForRequest:sel url:url parameters:parameters];
}

- (RACSignal *)DELETE:(NSString *)url parameters:(NSDictionary *)parameters {
  SEL sel = @selector(DELETE:parameters:success:failure:);
  return [self signalForRequest:sel url:url parameters:parameters];
}

- (RACSignal *)signalForRequest:(SEL)requestSEL url:(NSURL *)url parameters:(NSDictionary *)parameters {
  @weakify(self);

  return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    @strongify(self);

    void (^success)(AFHTTPRequestOperation *, NSDictionary *) = ^(AFHTTPRequestOperation *operation, NSDictionary *response) {
      [subscriber sendNext:response];
      [subscriber sendCompleted];
    };
    void (^failure)(AFHTTPRequestOperation *, NSDictionary *) = ^(AFHTTPRequestOperation *operation, NSError *error) {
      [subscriber sendError:error];
    };

    NSMethodSignature *methodSignature = [self.manager methodSignatureForSelector:requestSEL];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    [invocation setSelector:requestSEL];
    [invocation setTarget:self.manager];
    [invocation rac_setArgument:url atIndex:2];
    [invocation rac_setArgument:parameters atIndex:3];
    [invocation rac_setArgument:success atIndex:4];
    [invocation rac_setArgument:failure atIndex:5];

    [invocation invoke];
  }];
}

答案 1 :(得分:0)

你见过Reactive AFNetworking吗? 它应该解决你的问题

答案 2 :(得分:0)

修改

以下代码根本不起作用。

我从Reactive AFNetworking借了一些代码,代码如下是我的解决方案:

- (void)GET:(NSString *)URL parameters:(NSDictionary *)parameters {
  return [self signal_requestURL:URL method:@"PUT" parameters:parameters];
}


- (RACSignal *)signal_requestURL:(NSString *)URL method:(NSString *)method parameters:(NSDictionary *)parameters {
  AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializer];

  NSURLRequest *request = [serializer requestWithMethod:method URLString:URL parameters:parameters error:NULL];

  RACReplaySubject *subject = [RACReplaySubject replaySubjectWithCapacity:1];

  [self.manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
    [subject sendNext:responseObject];  
    [subject sendCompleted];
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    [subject sendError:error];
  }];

  return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    [subject subscribe:subscriber];
    return nil;
  }];
}