Ios 反应性和代表性

Ios 反应性和代表性,ios,objective-c,reactive-cocoa,Ios,Objective C,Reactive Cocoa,我正在尝试与登录服务通信,并以反应式方式更新UI。问题是,我的登录服务与委托一起工作,我发现的几乎每个示例都与块一起工作 我写了一个可行的解决方案,但似乎有点笨拙,我不确定这是否是最好的方法: 登录查看控制器: - (void) viewDidLoad { [super viewDidLoad]; //Assign the "loginCommand" command to the button. It'll get executed on button pressed and

我正在尝试与登录服务通信,并以反应式方式更新UI。问题是,我的登录服务与委托一起工作,我发现的几乎每个示例都与块一起工作

我写了一个可行的解决方案,但似乎有点笨拙,我不确定这是否是最好的方法:

登录查看控制器

- (void) viewDidLoad
{
    [super viewDidLoad];

    //Assign the "loginCommand" command to the button. It'll get executed on button pressed and the button is only enabled when the command says so.
    self.entrarBtn.rac_command = self.viewModel.loginCommand;

    //Subscribe and respond to command's successful signals
    @weakify(self);
    [self.viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *loginSignal) {
        [loginSignal subscribeNext:^(id x) {
            @strongify(self);
            [self.viewPresenter enterMainNavigation];
        }];
    }];

    //Subscribe and respond to command's error signals
    [self.viewModel.loginCommand.errors
     subscribeNext:^(NSError* error) {
         UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"ERROR" message:[NSString stringWithFormat:@"Error: %@", error.localizedDescription]  delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
         [alert show];
     }];    
}
- (id)init
{
    self = [super init];

    if(self) {
        self.loginCommand = [[RACCommand alloc] initWithEnabled:self.enableLoginSignal
                                signalBlock:^RACSignal *(id input) {
                                    return  [self loginSignal];
                                }];
    }

    return self;
}


- (RACSignal *)loginSignal
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        //LOGIN OK
        RACDisposable* loginOKDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginOK)
                                                           fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            PositionGlobalService *positionGlobalService = [PositionGlobalService sharedInstance];
            positionGlobalService.delegate = self;
            [positionGlobalService getPositionGlobal];
        }];

        //GETTING USER INFO DELEGATE THEN SEND THE COMPLETED SIGNAL
        RACDisposable* positionOKDisposable = [[self rac_signalForSelector:@selector(positionGlobalServiceDidReceivePositionGlobal)
                                                              fromProtocol:@protocol(PositionGlobalServiceDelegate)] subscribeNext:^(id x) {
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
        }];
        RACDisposable* positionErrorDisposable = [[self rac_signalForSelector:@selector(positionGlobalServiceDidReceivePositionGlobalError:)
                                                                 fromProtocol:@protocol(PositionGlobalServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorGettingUserInfo userInfo:nil];
            [subscriber sendError:error];
        }];

        //ERRORS
        RACDisposable* loginKODisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKO)
                                                           fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorKO userInfo:nil];
            [subscriber sendError:error];
        }];


        RACDisposable* deniedDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKOAccessDenied)
                                                          fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorAccessDenied userInfo:nil];
            [subscriber sendError:error];
        }];

        RACDisposable* connectionErrorDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveConnectionError)
                                                                   fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorConnectionError userInfo:nil];
            [subscriber sendError:error];
        }];

        RACDisposable* genericErrorDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveGenericError:)
                                                                fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorGenericError userInfo:nil];
            [subscriber sendError:error];
        }];


        LoginService *loginService = [LoginService sharedInstance];
        loginService.delegate = self;
        [loginService checkLogin:self.usuario withPassword:self.password documentType:LoginDocumentTypeNIF saveLogin:YES];


        return [RACDisposable disposableWithBlock:^{
            [loginOKDisposable dispose];
            [positionOKDisposable dispose];
            [positionErrorDisposable dispose];
            [loginKODisposable dispose];
            [deniedDisposable dispose];
            [connectionErrorDisposable dispose];
            [genericErrorDisposable dispose];
        }];

    }];
}
登录视图模型

- (void) viewDidLoad
{
    [super viewDidLoad];

    //Assign the "loginCommand" command to the button. It'll get executed on button pressed and the button is only enabled when the command says so.
    self.entrarBtn.rac_command = self.viewModel.loginCommand;

    //Subscribe and respond to command's successful signals
    @weakify(self);
    [self.viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *loginSignal) {
        [loginSignal subscribeNext:^(id x) {
            @strongify(self);
            [self.viewPresenter enterMainNavigation];
        }];
    }];

    //Subscribe and respond to command's error signals
    [self.viewModel.loginCommand.errors
     subscribeNext:^(NSError* error) {
         UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"ERROR" message:[NSString stringWithFormat:@"Error: %@", error.localizedDescription]  delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
         [alert show];
     }];    
}
- (id)init
{
    self = [super init];

    if(self) {
        self.loginCommand = [[RACCommand alloc] initWithEnabled:self.enableLoginSignal
                                signalBlock:^RACSignal *(id input) {
                                    return  [self loginSignal];
                                }];
    }

    return self;
}


- (RACSignal *)loginSignal
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        //LOGIN OK
        RACDisposable* loginOKDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginOK)
                                                           fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            PositionGlobalService *positionGlobalService = [PositionGlobalService sharedInstance];
            positionGlobalService.delegate = self;
            [positionGlobalService getPositionGlobal];
        }];

        //GETTING USER INFO DELEGATE THEN SEND THE COMPLETED SIGNAL
        RACDisposable* positionOKDisposable = [[self rac_signalForSelector:@selector(positionGlobalServiceDidReceivePositionGlobal)
                                                              fromProtocol:@protocol(PositionGlobalServiceDelegate)] subscribeNext:^(id x) {
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
        }];
        RACDisposable* positionErrorDisposable = [[self rac_signalForSelector:@selector(positionGlobalServiceDidReceivePositionGlobalError:)
                                                                 fromProtocol:@protocol(PositionGlobalServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorGettingUserInfo userInfo:nil];
            [subscriber sendError:error];
        }];

        //ERRORS
        RACDisposable* loginKODisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKO)
                                                           fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorKO userInfo:nil];
            [subscriber sendError:error];
        }];


        RACDisposable* deniedDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKOAccessDenied)
                                                          fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorAccessDenied userInfo:nil];
            [subscriber sendError:error];
        }];

        RACDisposable* connectionErrorDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveConnectionError)
                                                                   fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorConnectionError userInfo:nil];
            [subscriber sendError:error];
        }];

        RACDisposable* genericErrorDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveGenericError:)
                                                                fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            NSError* error = [NSError errorWithDomain:LoginErrorDomain code:LoginErrorGenericError userInfo:nil];
            [subscriber sendError:error];
        }];


        LoginService *loginService = [LoginService sharedInstance];
        loginService.delegate = self;
        [loginService checkLogin:self.usuario withPassword:self.password documentType:LoginDocumentTypeNIF saveLogin:YES];


        return [RACDisposable disposableWithBlock:^{
            [loginOKDisposable dispose];
            [positionOKDisposable dispose];
            [positionErrorDisposable dispose];
            [loginKODisposable dispose];
            [deniedDisposable dispose];
            [connectionErrorDisposable dispose];
            [genericErrorDisposable dispose];
        }];

    }];
}
-(id)init
{
self=[super init];
如果(自我){
self.loginCommand=[[RACCommand alloc]initWithEnabled:self.enableLoginSignal
信号块:^RACSignal*(id输入){
返回[自登录签名];
}];
}
回归自我;
}
-(RACSignal*)登录信号
{
返回[RACSignal createSignal:^RACSignal*(id订户){
//登录OK
RACDisposable*loginOKDisposable=[[self-rac_signalForSelector:@selector(loginServiceDidReceiveLoginOK)
fromProtocol:@protocol(LoginServiceDelegate)]subscribeNext:^(id x){
PositionGlobalService*PositionGlobalService=[PositionGlobalService sharedInstance];
positionGlobalService.delegate=self;
[positionGlobalService getPositionGlobal];
}];
//获取用户信息,然后发送完成的信号
rac一次性*POSITION OK一次性=[[选择器的自身rac_信号:@选择器(POSITIONGLOBALSERVICEDIRECEIVEPOSITIONGLOBAL)
fromProtocol:@protocol(PositionGlobalServiceDelegate)]subscribeNext:^(id x){
[用户发送下一步:无];
[用户发送完成];
}];
rac一次性*位置错误一次性=[[选择器的自身rac\U信号:@选择器(位置全局服务IDReceivePositionGlobalError:)
fromProtocol:@protocol(PositionGlobalServiceDelegate)]subscribeNext:^(id x){
NSError*error=[NSError errorWithDomain:LoginErrorDomain代码:LoginErrorGettingUserInfo用户信息:nil];
[订户发送错误:错误];
}];
//错误
RACDisposable*loginKODisposable=[[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKO)
fromProtocol:@protocol(LoginServiceDelegate)]subscribeNext:^(id x){
NSError*error=[NSError errorWithDomain:LoginErrorDomain代码:LoginErrorKO用户信息:nil];
[订户发送错误:错误];
}];
RACDisposable*deniedDisposable=[[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKOAccessDenied)
fromProtocol:@protocol(LoginServiceDelegate)]subscribeNext:^(id x){
NSError*error=[NSError errorWithDomain:LoginErrorDomain代码:LoginErrorAccessDenied用户信息:nil];
[订户发送错误:错误];
}];
rac一次性*ConnectionError一次性=[[self rac_signalForSelector:@selector(loginServiceDidReceiveConnectionError)
fromProtocol:@protocol(LoginServiceDelegate)]subscribeNext:^(id x){
NSError*error=[NSErrorErrorWithDomain:LoginErrorDomain代码:LoginErrorConnectionErrorUserInfo:nil];
[订户发送错误:错误];
}];
RACDisposable*genericErrorDisposable=[[self-rac\U signalForSelector:@selector(loginServiceDidReceiveGenericError:)
fromProtocol:@protocol(LoginServiceDelegate)]subscribeNext:^(id x){
NSError*error=[NSErrorErrorWithDomain:LoginErrorDomain代码:LoginErrorGenericError用户信息:nil];
[订户发送错误:错误];
}];
LoginService*LoginService=[LoginService sharedInstance];
loginService.delegate=self;
[loginService checkLogin:self.usuario with password:self.password文档类型:LoginDocumentTypeNIF saveLogin:YES];
返回[RAC一次性处置带块:^{
[loginOKDisposable dispose];
[一次性处置];
[一次性处置];
[登录可修改处置];
[拒绝可处置处置];
[康涅狄格州];
[一般错误或可处置];
}];
}];
}

正如您所看到的,每个代理都有一堆几乎相同的代码,这就是为什么我不确定这是否是最好的方法。

您的观点看起来不错,但我对模型有一些建议。主要的一点是,我将简化
LoginService
PositionGlobalService
上的信号,将它们移动到这些服务的相应类中。然后,您可以合并错误并创建单个信号,例如:

@interface LoginService : SomeSuperclass<LoginServiceDelegate>
- (RACSignal *)loginWithID:(NSString *)userid password:(NSString *password);
@end

@implementation LoginService()

- (RACSignal *)loginWithID:(NSString *)userid password:(NSString *)password {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        RACDisposable *errorDisposable = [[RACSignal merge:@[[[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKO) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorKO userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKOAccessDenied) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorAccessDenied userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveConnectionError) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorConnectionError userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveGenericError) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorGenericError userInfo:nil]]]] subscribeNext:^(id x) {
            [subscriber sendError:x];
        }];
        RACDisposable *loginDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginOK) fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            [subscriber sendNext:x];
            [subscriber sendCompleted];
        }];

        [self checkLogin:userid withPassword:password documentType:LoginDocumentTypeNIF saveLogin:YES];        
        return [RACDisposable disposableWithBlock:^{
            [errorDisposable dispose];
            [loginDisposable dispose];
        }];
    }
}
@end

你的观点看起来不错,但我对模型有一些建议。主要的一点是,我将简化
LoginService
PositionGlobalService
上的信号,将它们移动到这些服务的相应类中。然后,您可以合并错误并创建单个信号,例如:

@interface LoginService : SomeSuperclass<LoginServiceDelegate>
- (RACSignal *)loginWithID:(NSString *)userid password:(NSString *password);
@end

@implementation LoginService()

- (RACSignal *)loginWithID:(NSString *)userid password:(NSString *)password {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        RACDisposable *errorDisposable = [[RACSignal merge:@[[[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKO) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorKO userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginKOAccessDenied) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorAccessDenied userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveConnectionError) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorConnectionError userInfo:nil]],
                                                             [[self rac_signalForSelector:@selector(loginServiceDidReceiveGenericError) fromProtocol:@protocol(LoginServiceDelegate)] mapReplace:[NSError errorWithDomain:LoginErrorDomain code:LoginErrorGenericError userInfo:nil]]]] subscribeNext:^(id x) {
            [subscriber sendError:x];
        }];
        RACDisposable *loginDisposable = [[self rac_signalForSelector:@selector(loginServiceDidReceiveLoginOK) fromProtocol:@protocol(LoginServiceDelegate)] subscribeNext:^(id x) {
            [subscriber sendNext:x];
            [subscriber sendCompleted];
        }];

        [self checkLogin:userid withPassword:password documentType:LoginDocumentTypeNIF saveLogin:YES];        
        return [RACDisposable disposableWithBlock:^{
            [errorDisposable dispose];
            [loginDisposable dispose];
        }];
    }
}
@end

这正是我一直在寻找的答案,我会试试,让你知道。太好了!我错过了mapReplace位,它看起来更好知道“合并”这正是我想要的答案,我会尝试一下,让你知道。完美!我错过了mapReplace位,它看起来更像是“合并”