2014-10-16 5 views
0

Я пытаюсь реализовать обработку UITextFieldDelegate textFieldShouldReturn с помощью ReactiveCocoa. К сожалению, блок subscribeNext запускается, когда я подписываюсь на сигнал.UITextFieldDelegate textFieldShouldReturn with ReactiveCocoa

Реализация с использованием делегации будет:

- (void)viewDidLoad 
{ 
    ... 
    self.myTextField.delegate = self; 
} 

... 

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    if (textField == self.myTextField) { 
     NSLog(@"Let's go!"); 
    } 

    return YES; 
} 

В ReactiveCocoa я добавил категорию UITextField аналогичным образом, как UITextView + RACSignalSupport.

@implementation UITextField (RACKeyboardSupport) 

static void RACUseDelegateProxy(UITextField *self) 
{ 
    if (self.delegate == self.rac_delegateProxy) return; 

    self.rac_delegateProxy.rac_proxiedDelegate = self.delegate; 
    self.delegate = (id)self.rac_delegateProxy; 
} 

- (RACDelegateProxy *)rac_delegateProxy 
{ 
    RACDelegateProxy *proxy = objc_getAssociatedObject(self, _cmd); 
    if (proxy == nil) { 
     proxy = [[RACDelegateProxy alloc] initWithProtocol:@protocol(UITextFieldDelegate)]; 
     objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
    } 

    return proxy; 
} 

- (RACSignal *)rac_keyboardReturnSignal 
{ 
    @weakify(self); 
    RACSignal *signal = [[[[RACSignal 
          defer:^{ 
           @strongify(self); 
           return [RACSignal return:RACTuplePack(self)]; 
          }] 
          concat:[self.rac_delegateProxy signalForSelector:@selector(textFieldShouldReturn:)]] 
          takeUntil:self.rac_willDeallocSignal] 
         setNameWithFormat:@"%@ -rac_keyboardReturnSignal", [self rac_description]]; 

    RACUseDelegateProxy(self); 

    return signal; 
} 

@end 

Здесь subscribeNext блок выполняется, даже если возврат ключа никогда не нажата:

- (void)viewDidLoad 
{ 
    ... 
    [self.myTextField.rac_keyboardReturnSignal subscribeNext:^(id x) { 
     Log(@"Let's go with RAC!"); 
    }]; 
} 

Я должен использовать пропуском: 1, чтобы избежать этой проблемы:

- (void)viewDidLoad 
{ 
    ... 
    [[self.myTextField.rac_keyboardReturnSignal skip:1] subscribeNext:^(id x) { 
     Log(@"Let's go with RAC!"); 
    }]; 
} 

Любая идея, почему Бывает?

Решение:

- (RACSignal *)rac_keyboardReturnSignal 
{ 
    RACSignal *signal = [[[self.rac_delegateProxy 
          signalForSelector:@selector(textFieldShouldReturn:)] 
          takeUntil:self.rac_willDeallocSignal] 
         setNameWithFormat:@"%@ -rac_keyboardReturnSignal", [self rac_description]]; 

    RACUseDelegateProxy(self); 

    return signal; 
} 

ответ

1

Вы возвращаете сигнал, который немедленно возвращает значение в вашем defer блоке, то concat -ную новые значения на поток, когда textFieldShouldReturn вызывается.

Код в UITextView+RACSignalSupport.m вызывает reduceEach, чтобы вернуть строковое значение, которое извлекается из экземпляра UITextView. defer используется, чтобы иметь только начальное значение, генерируемое при подписке.

В принципе, я не думаю, что вы хотите defer вообще для вашего прецедента.

Смежные вопросы