문제

I have several methods that return signals that created by

+ (RACSignal *)createSignal:

And in the signals I send different requests using the methods from AFHTTPRequestOperationManager in AFNetworking:

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

Supposed that I have a property to store the instance of AFHTTPRequestOperationManager:

@property(strong, nonatomic) AFHTTPRequestOperationManager *manager;

This is the body of the GET request method, others are almost identical with it except the method calls from 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;
}];

And I want to extract the [self.manager GET...] logic out so that can I eliminate the duplicate code and only to pass different selectors(or something like it) to send different requests.

How do I achieve it ?

도움이 되었습니까?

해결책

This is untested, but should get you most of the way there:

- (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];
  }];
}

다른 팁

Have you seen Reactive AFNetworking. It should solve your problem

Edit:

The code below doesn't work at all.

I borrowed some code from Reactive AFNetworking and the code as follows is my solution:

- (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;
  }];
}  
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top