6

https://github.com/ReactiveCocoa/ReactiveCocoaで最初のコードを実装しています。

ユーザーのログイン用です。回線[subscriber sendNext:user];は 2 回呼び出されますが、1 回だけであると予想しています。そして、マップはまったく呼び出されません (したがって、自動ログインは呼び出されません)

これは私の実装です:

-(RACSignal *) login:(NSString *)email pwd:(NSString *)pwd
{
    DDLogInfo(@"Login user %@", email);

    RACSignal *login = [RACSignal createSignal:^ RACDisposable *(id<RACSubscriber> subscriber)
    {        
        [PFUser logInWithUsernameInBackground:email password:pwd block:^(PFUser *user, NSError *error) {

            if (error) {
                [subscriber sendError:error];
            } else {
                [subscriber sendNext:user];

                [subscriber sendCompleted];
            }
        }];

        return nil;
    }];

    [login map:^(PFUser *user) {
        return [self autoLogin:user];
    }];

    return login;
}

このように呼ばれます:

NSString *email = data[@"email"];
NSString *pwd = data[@"pwd"];
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];

RACSignal *login = [[SyncEngine server] login:email pwd:pwd];

[login
 subscribeCompleted:^
{
    [[NSNotificationCenter defaultCenter]
     postNotificationName:NOTIFY_LOGIN_CHANGED
     object:self];

     [SVProgressHUD showSuccessWithStatus:LOC_OK];


     [self cancelForm];
}];

[login
 subscribeError:^(NSError *error)
{
    [SVProgressHUD dismiss];

    [AppUrls alertError:LOC_ERROR_LOGING msg:error.userInfo[@"error"]];
}];
4

2 に答える 2

10

+[RACSignal createSignal:]これは、シグナルへのサブスクリプションが作成されるたびに に渡されたブロックが実行され、コードが 2 つの別個のサブスクリプションを作成するために発生します。

[login subscribeCompleted:^{ ... }];

[login subscribeError:^(NSError *error) { ... }];

サブスクリプションを 1 つだけ作成する場合は、次のメソッドを使用します-[RACSignal subscribeError:completed:]

[login subscribeError:^(NSError *error) {
        [SVProgressHUD dismiss];

        [AppUrls alertError:LOC_ERROR_LOGING msg:error.userInfo[@"error"]];
    }
    completed:^{
        [[NSNotificationCenter defaultCenter]
         postNotificationName:NOTIFY_LOGIN_CHANGED
         object:self];

         [SVProgressHUD showSuccessWithStatus:LOC_OK];


         [self cancelForm];
    }];
于 2013-11-29T02:09:27.580 に答える
5

このソリューションで十分な場合もありますが、サブスクリプション ブロックが 1 回だけ呼び出されるようにしたい場合もあります。これは、おそらく副作用が生じるためです。この場合、信号の呼び出しを返すことができます-replay:

return [[RACSignal createSignal:^ RACDisposable *(id<RACSubscriber> subscriber) {        
    [PFUser logInWithUsernameInBackground:email password:pwd block:^(PFUser *user, NSError *error) {

        if (error) {
            [subscriber sendError:error];
        } else {
            [subscriber sendNext:user];

            [subscriber sendCompleted];
        }
    }];

    return nil;
}] map:^(PFUser *user) {
    return [self autoLogin:user];
}] replay];

この新しい派生シグナルは、同じメッセージまたはエラーをすべてのサブスクライバーに送信します。シグナルが完了し、新しいサブスクライバーがいる場合、これはすぐにすべてのメッセージも受信します。

于 2014-03-04T04:09:07.960 に答える