ios - UITextFieldDelegate textFieldShouldReturn 与 ReactiveCocoa

标签 ios uitextfield reactive-cocoa uitextfielddelegate

我正在尝试使用 ReactiveCocoa 实现 UITextFieldDelegate textFieldShouldReturn 处理。不幸的是,当我订阅信号时,subscribeNext block 正在运行。

使用委托(delegate)的实现是:

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

...

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

    return YES;
}

在 ReactiveCocoa 中,我以类似 UITextView+RACSignalSupport 的方式为 UITextField 添加了一个类别。

@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

即使没有按下 Return 键,subscribeNext block 也会执行:

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

我必须使用 skip: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;
}

最佳答案

您正在返回一个信号,该信号会立即在您的 defer block 中返回一个值,然后在 textFieldShouldReturn 时将新值concat 到流中被调用。

UITextView+RACSignalSupport.m 中的代码正在调用 reduceEach 以返回从 UITextView 实例中提取的字符串值。 defer 仅用于在订阅时生成初始值。

基本上,我认为您的用例根本不需要 defer

关于ios - UITextFieldDelegate textFieldShouldReturn 与 ReactiveCocoa,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26408460/

相关文章:

ios - CloudKit fetchUserRecordIDWithCompletionHandler 完成代码未调用?

ios - 未调用子类覆盖方法

swift - Alamofire 3.0 ReactiveCocoa 转换

ios - 设置具有 cocoa react 性细胞的图像

ios - 使用外观向 uitextfield 添加填充

ios - 没有订阅者时停止发布,有订阅者时自动开始

ios - 使用 Safari View Controller 登录时的 Swift iOS Facebook SDK 循环

ios - 2 AppDelegate 中的手指向上滑动 Action

ios - objective-c - 传递给子 block 的父函数的参数在内部没有改变

xcode - iPad "dismiss keyboard"按钮(右下角),如何检测何时发生?什么功能告诉我它被按下了?