From 241b0b85d4c9f5768f2a7f8576f442499a875ec6 Mon Sep 17 00:00:00 2001 From: StefanChannel Date: Tue, 1 Oct 2024 15:12:14 -0700 Subject: [PATCH] restored UIKit specific files --- Package.swift | 26 ++++ .../MKAnnotationView+RACSignalSupport.m | 31 ++++ ReactiveObjC/NSControl+RACCommandSupport.m | 57 +++++++ ReactiveObjC/NSControl+RACTextSignalSupport.m | 38 +++++ ReactiveObjC/NSFileHandle+RACSupport.m | 40 +++++ ReactiveObjC/NSObject+RACAppKitBindings.m | 146 ++++++++++++++++++ ReactiveObjC/NSText+RACSignalSupport.m | 38 +++++ ReactiveObjC/UIActionSheet+RACSignalSupport.m | 49 ++++++ ReactiveObjC/UIAlertView+RACSignalSupport.m | 63 ++++++++ .../UIBarButtonItem+RACCommandSupport.m | 54 +++++++ ReactiveObjC/UIButton+RACCommandSupport.m | 56 +++++++ ...ICollectionReusableView+RACSignalSupport.m | 31 ++++ ReactiveObjC/UIControl+RACSignalSupport.m | 43 ++++++ .../UIControl+RACSignalSupportPrivate.m | 48 ++++++ ReactiveObjC/UIDatePicker+RACSignalSupport.m | 19 +++ .../UIGestureRecognizer+RACSignalSupport.m | 40 +++++ ...UIImagePickerController+RACSignalSupport.m | 53 +++++++ .../UIRefreshControl+RACCommandSupport.m | 59 +++++++ .../UISegmentedControl+RACSignalSupport.m | 19 +++ ReactiveObjC/UISlider+RACSignalSupport.m | 19 +++ ReactiveObjC/UIStepper+RACSignalSupport.m | 19 +++ ReactiveObjC/UISwitch+RACSignalSupport.m | 19 +++ .../UITableViewCell+RACSignalSupport.m | 31 ++++ ...bleViewHeaderFooterView+RACSignalSupport.m | 31 ++++ ReactiveObjC/UITextField+RACSignalSupport.m | 39 +++++ ReactiveObjC/UITextView+RACSignalSupport.m | 56 +++++++ .../include/ReactiveObjC/ReactiveObjC.h | 62 ++++---- 27 files changed, 1155 insertions(+), 31 deletions(-) create mode 100644 ReactiveObjC/MKAnnotationView+RACSignalSupport.m create mode 100644 ReactiveObjC/NSControl+RACCommandSupport.m create mode 100644 ReactiveObjC/NSControl+RACTextSignalSupport.m create mode 100644 ReactiveObjC/NSFileHandle+RACSupport.m create mode 100644 ReactiveObjC/NSObject+RACAppKitBindings.m create mode 100644 ReactiveObjC/NSText+RACSignalSupport.m create mode 100644 ReactiveObjC/UIActionSheet+RACSignalSupport.m create mode 100644 ReactiveObjC/UIAlertView+RACSignalSupport.m create mode 100644 ReactiveObjC/UIBarButtonItem+RACCommandSupport.m create mode 100644 ReactiveObjC/UIButton+RACCommandSupport.m create mode 100644 ReactiveObjC/UICollectionReusableView+RACSignalSupport.m create mode 100644 ReactiveObjC/UIControl+RACSignalSupport.m create mode 100644 ReactiveObjC/UIControl+RACSignalSupportPrivate.m create mode 100644 ReactiveObjC/UIDatePicker+RACSignalSupport.m create mode 100644 ReactiveObjC/UIGestureRecognizer+RACSignalSupport.m create mode 100644 ReactiveObjC/UIImagePickerController+RACSignalSupport.m create mode 100644 ReactiveObjC/UIRefreshControl+RACCommandSupport.m create mode 100644 ReactiveObjC/UISegmentedControl+RACSignalSupport.m create mode 100644 ReactiveObjC/UISlider+RACSignalSupport.m create mode 100644 ReactiveObjC/UIStepper+RACSignalSupport.m create mode 100644 ReactiveObjC/UISwitch+RACSignalSupport.m create mode 100644 ReactiveObjC/UITableViewCell+RACSignalSupport.m create mode 100644 ReactiveObjC/UITableViewHeaderFooterView+RACSignalSupport.m create mode 100644 ReactiveObjC/UITextField+RACSignalSupport.m create mode 100644 ReactiveObjC/UITextView+RACSignalSupport.m diff --git a/Package.swift b/Package.swift index 4897dd30b..fcf497ef3 100644 --- a/Package.swift +++ b/Package.swift @@ -87,6 +87,32 @@ let package = Package( "RACUnarySequence.m", "RACUnit.m", "RACValueTransformer.m", +// "MKAnnotationView+RACSignalSupport.m", +// "NSControl+RACCommandSupport.m", +// "NSControl+RACTextSignalSupport.m", +// "NSFileHandle+RACSupport.m", +// "NSObject+RACAppKitBindings.m", +// "NSText+RACSignalSupport.m", +"UIActionSheet+RACSignalSupport.m", +"UIAlertView+RACSignalSupport.m", +"UIBarButtonItem+RACCommandSupport.m", +"UIButton+RACCommandSupport.m", +"UICollectionReusableView+RACSignalSupport.m", +"UIControl+RACSignalSupport.m", +"UIControl+RACSignalSupportPrivate.m", +"UIDatePicker+RACSignalSupport.m", +"UIGestureRecognizer+RACSignalSupport.m", +"UIImagePickerController+RACSignalSupport.m", +"UIRefreshControl+RACCommandSupport.m", +"UISegmentedControl+RACSignalSupport.m", +"UISlider+RACSignalSupport.m", +"UIStepper+RACSignalSupport.m", +"UISwitch+RACSignalSupport.m", +"UITableViewCell+RACSignalSupport.m", +"UITableViewHeaderFooterView+RACSignalSupport.m", +"UITextField+RACSignalSupport.m", +"UITextView+RACSignalSupport.m", + ], publicHeadersPath: "include", cSettings: [ diff --git a/ReactiveObjC/MKAnnotationView+RACSignalSupport.m b/ReactiveObjC/MKAnnotationView+RACSignalSupport.m new file mode 100644 index 000000000..d138a79f4 --- /dev/null +++ b/ReactiveObjC/MKAnnotationView+RACSignalSupport.m @@ -0,0 +1,31 @@ +// +// MKAnnotationView+RACSignalSupport.m +// ReactiveObjC +// +// Created by Zak Remer on 3/31/15. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +#import "MKAnnotationView+RACSignalSupport.h" +#import "NSObject+RACDescription.h" +#import "NSObject+RACSelectorSignal.h" +#import "RACSignal+Operations.h" +#import "RACUnit.h" +#import + +@implementation MKAnnotationView (RACSignalSupport) + +- (RACSignal *)rac_prepareForReuseSignal { + RACSignal *signal = objc_getAssociatedObject(self, _cmd); + if (signal != nil) return signal; + + signal = [[[self + rac_signalForSelector:@selector(prepareForReuse)] + mapReplace:RACUnit.defaultUnit] + setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; + + objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return signal; +} + +@end diff --git a/ReactiveObjC/NSControl+RACCommandSupport.m b/ReactiveObjC/NSControl+RACCommandSupport.m new file mode 100644 index 000000000..1d8f6ba25 --- /dev/null +++ b/ReactiveObjC/NSControl+RACCommandSupport.m @@ -0,0 +1,57 @@ +// +// NSControl+RACCommandSupport.m +// ReactiveObjC +// +// Created by Josh Abernathy on 3/3/12. +// Copyright (c) 2012 GitHub, Inc. All rights reserved. +// + +#import "NSControl+RACCommandSupport.h" +#import "RACCommand.h" +#import "RACScopedDisposable.h" +#import "RACSignal+Operations.h" +#import + +static void *NSControlRACCommandKey = &NSControlRACCommandKey; +static void *NSControlEnabledDisposableKey = &NSControlEnabledDisposableKey; + +@implementation NSControl (RACCommandSupport) + +- (RACCommand *)rac_command { + return objc_getAssociatedObject(self, NSControlRACCommandKey); +} + +- (void)setRac_command:(RACCommand *)command { + objc_setAssociatedObject(self, NSControlRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // Tear down any previous binding before setting up our new one, or else we + // might get assertion failures. + [objc_getAssociatedObject(self, NSControlEnabledDisposableKey) dispose]; + objc_setAssociatedObject(self, NSControlEnabledDisposableKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + if (command == nil) { + self.enabled = YES; + return; + } + + [self rac_hijackActionAndTargetIfNeeded]; + + RACScopedDisposable *disposable = [[command.enabled setKeyPath:@"enabled" onObject:self] asScopedDisposable]; + objc_setAssociatedObject(self, NSControlEnabledDisposableKey, disposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)rac_hijackActionAndTargetIfNeeded { + SEL hijackSelector = @selector(rac_commandPerformAction:); + if (self.target == self && self.action == hijackSelector) return; + + if (self.target != nil) NSLog(@"WARNING: NSControl.rac_command hijacks the control's existing target and action."); + + self.target = self; + self.action = hijackSelector; +} + +- (void)rac_commandPerformAction:(id)sender { + [self.rac_command execute:sender]; +} + +@end diff --git a/ReactiveObjC/NSControl+RACTextSignalSupport.m b/ReactiveObjC/NSControl+RACTextSignalSupport.m new file mode 100644 index 000000000..88da38f6e --- /dev/null +++ b/ReactiveObjC/NSControl+RACTextSignalSupport.m @@ -0,0 +1,38 @@ +// +// NSControl+RACTextSignalSupport.m +// ReactiveObjC +// +// Created by Justin Spahr-Summers on 2013-03-08. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "NSControl+RACTextSignalSupport.h" +#import +#import "NSObject+RACDescription.h" +#import "RACDisposable.h" +#import "RACSignal.h" +#import "RACSubscriber.h" + +@implementation NSControl (RACTextSignalSupport) + +- (RACSignal *)rac_textSignal { + @weakify(self); + return [[[[RACSignal + createSignal:^(id subscriber) { + @strongify(self); + id observer = [NSNotificationCenter.defaultCenter addObserverForName:NSControlTextDidChangeNotification object:self queue:nil usingBlock:^(NSNotification *note) { + [subscriber sendNext:note.object]; + }]; + + return [RACDisposable disposableWithBlock:^{ + [NSNotificationCenter.defaultCenter removeObserver:observer]; + }]; + }] + map:^(NSControl *control) { + return [control.stringValue copy]; + }] + startWith:[self.stringValue copy]] + setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; +} + +@end diff --git a/ReactiveObjC/NSFileHandle+RACSupport.m b/ReactiveObjC/NSFileHandle+RACSupport.m new file mode 100644 index 000000000..9d1c42f37 --- /dev/null +++ b/ReactiveObjC/NSFileHandle+RACSupport.m @@ -0,0 +1,40 @@ +// +// NSFileHandle+RACSupport.m +// ReactiveObjC +// +// Created by Josh Abernathy on 5/10/12. +// Copyright (c) 2012 GitHub. All rights reserved. +// + +#import "NSFileHandle+RACSupport.h" +#import "NSNotificationCenter+RACSupport.h" +#import "NSObject+RACDescription.h" +#import "RACReplaySubject.h" +#import "RACDisposable.h" + +@implementation NSFileHandle (RACSupport) + +- (RACSignal *)rac_readInBackground { + RACReplaySubject *subject = [RACReplaySubject subject]; + [subject setNameWithFormat:@"%@ -rac_readInBackground", RACDescription(self)]; + + RACSignal *dataNotification = [[[NSNotificationCenter defaultCenter] rac_addObserverForName:NSFileHandleReadCompletionNotification object:self] map:^(NSNotification *note) { + return note.userInfo[NSFileHandleNotificationDataItem]; + }]; + + __block RACDisposable *subscription = [dataNotification subscribeNext:^(NSData *data) { + if (data.length > 0) { + [subject sendNext:data]; + [self readInBackgroundAndNotify]; + } else { + [subject sendCompleted]; + [subscription dispose]; + } + }]; + + [self readInBackgroundAndNotify]; + + return subject; +} + +@end diff --git a/ReactiveObjC/NSObject+RACAppKitBindings.m b/ReactiveObjC/NSObject+RACAppKitBindings.m new file mode 100644 index 000000000..06fd5d011 --- /dev/null +++ b/ReactiveObjC/NSObject+RACAppKitBindings.m @@ -0,0 +1,146 @@ +// +// NSObject+RACAppKitBindings.m +// ReactiveObjC +// +// Created by Josh Abernathy on 4/17/12. +// Copyright (c) 2012 GitHub, Inc. All rights reserved. +// + +#import "NSObject+RACAppKitBindings.h" +#import +#import +#import "NSObject+RACDeallocating.h" +#import "RACChannel.h" +#import "RACCompoundDisposable.h" +#import "RACDisposable.h" +#import "RACKVOChannel.h" +#import "RACValueTransformer.h" +#import + +// Used as an object to bind to, so we can hide the object creation and just +// expose a RACChannel instead. +@interface RACChannelProxy : NSObject + +// The RACChannel used for this Cocoa binding. +@property (nonatomic, strong, readonly) RACChannel *channel; + +// The KVC- and KVO-compliant property to be read and written by the Cocoa +// binding. +// +// This should not be set manually. +@property (nonatomic, strong) id value; + +// The target of the Cocoa binding. +// +// This should be set to nil when the target deallocates. +@property (atomic, unsafe_unretained) id target; + +// The name of the Cocoa binding used. +@property (nonatomic, copy, readonly) NSString *bindingName; + +// Improves the performance of KVO on the receiver. +// +// See the documentation for for more information. +@property (atomic, assign) void *observationInfo; + +// Initializes the receiver and binds to the given target. +// +// target - The target of the Cocoa binding. This must not be nil. +// bindingName - The name of the Cocoa binding to use. This must not be nil. +// options - Any options to pass to the binding. This may be nil. +// +// Returns an initialized channel proxy. +- (instancetype)initWithTarget:(id)target bindingName:(NSString *)bindingName options:(NSDictionary *)options; + +@end + +@implementation NSObject (RACAppKitBindings) + +- (RACChannelTerminal *)rac_channelToBinding:(NSString *)binding { + return [self rac_channelToBinding:binding options:nil]; +} + +- (RACChannelTerminal *)rac_channelToBinding:(NSString *)binding options:(NSDictionary *)options { + NSCParameterAssert(binding != nil); + + RACChannelProxy *proxy = [[RACChannelProxy alloc] initWithTarget:self bindingName:binding options:options]; + return proxy.channel.leadingTerminal; +} + +@end + +@implementation RACChannelProxy + +#pragma mark Properties + +- (void)setValue:(id)value { + [self willChangeValueForKey:@keypath(self.value)]; + _value = value; + [self didChangeValueForKey:@keypath(self.value)]; +} + +#pragma mark Lifecycle + +- (instancetype)initWithTarget:(id)target bindingName:(NSString *)bindingName options:(NSDictionary *)options { + NSCParameterAssert(target != nil); + NSCParameterAssert(bindingName != nil); + + self = [super init]; + + _target = target; + _bindingName = [bindingName copy]; + _channel = [[RACChannel alloc] init]; + + @weakify(self); + + void (^cleanUp)(void) = ^{ + @strongify(self); + + id target = self.target; + if (target == nil) return; + + self.target = nil; + + [target unbind:bindingName]; + objc_setAssociatedObject(target, (__bridge void *)self, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }; + + // When the channel terminates, tear down this proxy. + [self.channel.followingTerminal subscribeError:^(NSError *error) { + cleanUp(); + } completed:cleanUp]; + + [self.target bind:bindingName toObject:self withKeyPath:@keypath(self.value) options:options]; + + // Keep the proxy alive as long as the target, or until the property subject + // terminates. + objc_setAssociatedObject(self.target, (__bridge void *)self, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [[self.target rac_deallocDisposable] addDisposable:[RACDisposable disposableWithBlock:^{ + @strongify(self); + [self.channel.followingTerminal sendCompleted]; + }]]; + + RACChannelTo(self, value, options[NSNullPlaceholderBindingOption]) = self.channel.followingTerminal; + return self; +} + +- (void)dealloc { + [self.channel.followingTerminal sendCompleted]; +} + +#pragma mark NSObject + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p>{ target: %@, binding: %@ }", self.class, self, self.target, self.bindingName]; +} + +#pragma mark NSKeyValueObserving + ++ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { + // Generating manual notifications for `value` is simpler and more + // performant than having KVO swizzle our class and add its own logic. + return NO; +} + +@end diff --git a/ReactiveObjC/NSText+RACSignalSupport.m b/ReactiveObjC/NSText+RACSignalSupport.m new file mode 100644 index 000000000..dfeff1ee2 --- /dev/null +++ b/ReactiveObjC/NSText+RACSignalSupport.m @@ -0,0 +1,38 @@ +// +// NSText+RACSignalSupport.m +// ReactiveObjC +// +// Created by Justin Spahr-Summers on 2013-03-08. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "NSText+RACSignalSupport.h" +#import +#import "NSObject+RACDescription.h" +#import "RACDisposable.h" +#import "RACSignal.h" +#import "RACSubscriber.h" + +@implementation NSText (RACSignalSupport) + +- (RACSignal *)rac_textSignal { + @unsafeify(self); + return [[[[RACSignal + createSignal:^(id subscriber) { + @strongify(self); + id observer = [NSNotificationCenter.defaultCenter addObserverForName:NSTextDidChangeNotification object:self queue:nil usingBlock:^(NSNotification *note) { + [subscriber sendNext:note.object]; + }]; + + return [RACDisposable disposableWithBlock:^{ + [NSNotificationCenter.defaultCenter removeObserver:observer]; + }]; + }] + map:^(NSText *text) { + return [text.string copy]; + }] + startWith:[self.string copy]] + setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; +} + +@end diff --git a/ReactiveObjC/UIActionSheet+RACSignalSupport.m b/ReactiveObjC/UIActionSheet+RACSignalSupport.m new file mode 100644 index 000000000..6a1a4102d --- /dev/null +++ b/ReactiveObjC/UIActionSheet+RACSignalSupport.m @@ -0,0 +1,49 @@ +// +// UIActionSheet+RACSignalSupport.m +// ReactiveObjC +// +// Created by Dave Lee on 2013-06-22. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIActionSheet+RACSignalSupport.h" +#import "RACDelegateProxy.h" +#import "RACSignal+Operations.h" +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import + +@implementation UIActionSheet (RACSignalSupport) + +static void RACUseDelegateProxy(UIActionSheet *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(UIActionSheetDelegate)]; + objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + + return proxy; +} + +- (RACSignal *)rac_buttonClickedSignal { + RACSignal *signal = [[[[self.rac_delegateProxy + signalForSelector:@selector(actionSheet:clickedButtonAtIndex:)] + reduceEach:^(UIActionSheet *actionSheet, NSNumber *buttonIndex) { + return buttonIndex; + }] + takeUntil:self.rac_willDeallocSignal] + setNameWithFormat:@"%@ -rac_buttonClickedSignal", RACDescription(self)]; + + RACUseDelegateProxy(self); + + return signal; +} + +@end diff --git a/ReactiveObjC/UIAlertView+RACSignalSupport.m b/ReactiveObjC/UIAlertView+RACSignalSupport.m new file mode 100644 index 000000000..0afc94a8d --- /dev/null +++ b/ReactiveObjC/UIAlertView+RACSignalSupport.m @@ -0,0 +1,63 @@ +// +// UIAlertView+RACSignalSupport.m +// ReactiveObjC +// +// Created by Henrik Hodne on 6/16/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIAlertView+RACSignalSupport.h" +#import "RACDelegateProxy.h" +#import "RACSignal+Operations.h" +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import + +@implementation UIAlertView (RACSignalSupport) + +static void RACUseDelegateProxy(UIAlertView *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(UIAlertViewDelegate)]; + objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + + return proxy; +} + +- (RACSignal *)rac_buttonClickedSignal { + RACSignal *signal = [[[[self.rac_delegateProxy + signalForSelector:@selector(alertView:clickedButtonAtIndex:)] + reduceEach:^(UIAlertView *alertView, NSNumber *buttonIndex) { + return buttonIndex; + }] + takeUntil:self.rac_willDeallocSignal] + setNameWithFormat:@"%@ -rac_buttonClickedSignal", RACDescription(self)]; + + RACUseDelegateProxy(self); + + return signal; +} + +- (RACSignal *)rac_willDismissSignal { + RACSignal *signal = [[[[self.rac_delegateProxy + signalForSelector:@selector(alertView:willDismissWithButtonIndex:)] + reduceEach:^(UIAlertView *alertView, NSNumber *buttonIndex) { + return buttonIndex; + }] + takeUntil:self.rac_willDeallocSignal] + setNameWithFormat:@"%@ -rac_willDismissSignal", RACDescription(self)]; + + RACUseDelegateProxy(self); + + return signal; +} + +@end diff --git a/ReactiveObjC/UIBarButtonItem+RACCommandSupport.m b/ReactiveObjC/UIBarButtonItem+RACCommandSupport.m new file mode 100644 index 000000000..225e8b751 --- /dev/null +++ b/ReactiveObjC/UIBarButtonItem+RACCommandSupport.m @@ -0,0 +1,54 @@ +// +// UIBarButtonItem+RACCommandSupport.m +// ReactiveObjC +// +// Created by Kyle LeNeau on 3/27/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIBarButtonItem+RACCommandSupport.h" +#import +#import "RACCommand.h" +#import "RACDisposable.h" +#import "RACSignal+Operations.h" +#import + +static void *UIControlRACCommandKey = &UIControlRACCommandKey; +static void *UIControlEnabledDisposableKey = &UIControlEnabledDisposableKey; + +@implementation UIBarButtonItem (RACCommandSupport) + +- (RACCommand *)rac_command { + return objc_getAssociatedObject(self, UIControlRACCommandKey); +} + +- (void)setRac_command:(RACCommand *)command { + objc_setAssociatedObject(self, UIControlRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // Check for stored signal in order to remove it and add a new one + RACDisposable *disposable = objc_getAssociatedObject(self, UIControlEnabledDisposableKey); + [disposable dispose]; + + if (command == nil) return; + + disposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; + objc_setAssociatedObject(self, UIControlEnabledDisposableKey, disposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [self rac_hijackActionAndTargetIfNeeded]; +} + +- (void)rac_hijackActionAndTargetIfNeeded { + SEL hijackSelector = @selector(rac_commandPerformAction:); + if (self.target == self && self.action == hijackSelector) return; + + if (self.target != nil) NSLog(@"WARNING: UIBarButtonItem.rac_command hijacks the control's existing target and action."); + + self.target = self; + self.action = hijackSelector; +} + +- (void)rac_commandPerformAction:(id)sender { + [self.rac_command execute:sender]; +} + +@end diff --git a/ReactiveObjC/UIButton+RACCommandSupport.m b/ReactiveObjC/UIButton+RACCommandSupport.m new file mode 100644 index 000000000..6b11dad27 --- /dev/null +++ b/ReactiveObjC/UIButton+RACCommandSupport.m @@ -0,0 +1,56 @@ +// +// UIButton+RACCommandSupport.m +// ReactiveObjC +// +// Created by Ash Furrow on 2013-06-06. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIButton+RACCommandSupport.h" +#import +#import "RACCommand.h" +#import "RACDisposable.h" +#import "RACSignal+Operations.h" +#import + +static void *UIButtonRACCommandKey = &UIButtonRACCommandKey; +static void *UIButtonEnabledDisposableKey = &UIButtonEnabledDisposableKey; + +@implementation UIButton (RACCommandSupport) + +- (RACCommand *)rac_command { + return objc_getAssociatedObject(self, UIButtonRACCommandKey); +} + +- (void)setRac_command:(RACCommand *)command { + objc_setAssociatedObject(self, UIButtonRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // Check for stored signal in order to remove it and add a new one + RACDisposable *disposable = objc_getAssociatedObject(self, UIButtonEnabledDisposableKey); + [disposable dispose]; + + if (command == nil) return; + + disposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; + objc_setAssociatedObject(self, UIButtonEnabledDisposableKey, disposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [self rac_hijackActionAndTargetIfNeeded]; +} + +- (void)rac_hijackActionAndTargetIfNeeded { + SEL hijackSelector = @selector(rac_commandPerformAction:); + + for (NSString *selector in [self actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) { + if (hijackSelector == NSSelectorFromString(selector)) { + return; + } + } + + [self addTarget:self action:hijackSelector forControlEvents:UIControlEventTouchUpInside]; +} + +- (void)rac_commandPerformAction:(id)sender { + [self.rac_command execute:sender]; +} + +@end diff --git a/ReactiveObjC/UICollectionReusableView+RACSignalSupport.m b/ReactiveObjC/UICollectionReusableView+RACSignalSupport.m new file mode 100644 index 000000000..9215c162b --- /dev/null +++ b/ReactiveObjC/UICollectionReusableView+RACSignalSupport.m @@ -0,0 +1,31 @@ +// +// UICollectionReusableView+RACSignalSupport.m +// ReactiveObjC +// +// Created by Kent Wong on 2013-10-04. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UICollectionReusableView+RACSignalSupport.h" +#import "NSObject+RACDescription.h" +#import "NSObject+RACSelectorSignal.h" +#import "RACSignal+Operations.h" +#import "RACUnit.h" +#import + +@implementation UICollectionReusableView (RACSignalSupport) + +- (RACSignal *)rac_prepareForReuseSignal { + RACSignal *signal = objc_getAssociatedObject(self, _cmd); + if (signal != nil) return signal; + + signal = [[[self + rac_signalForSelector:@selector(prepareForReuse)] + mapReplace:RACUnit.defaultUnit] + setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; + + objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return signal; +} + +@end diff --git a/ReactiveObjC/UIControl+RACSignalSupport.m b/ReactiveObjC/UIControl+RACSignalSupport.m new file mode 100644 index 000000000..df3108eb7 --- /dev/null +++ b/ReactiveObjC/UIControl+RACSignalSupport.m @@ -0,0 +1,43 @@ +// +// UIControl+RACSignalSupport.m +// ReactiveObjC +// +// Created by Josh Abernathy on 4/17/12. +// Copyright (c) 2012 GitHub, Inc. All rights reserved. +// + +#import "UIControl+RACSignalSupport.h" +#import +#import "RACCompoundDisposable.h" +#import "RACDisposable.h" +#import "RACSignal.h" +#import "RACSubscriber.h" +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" + +@implementation UIControl (RACSignalSupport) + +- (RACSignal *)rac_signalForControlEvents:(UIControlEvents)controlEvents { + @weakify(self); + + return [[RACSignal + createSignal:^(id subscriber) { + @strongify(self); + + [self addTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; + + RACDisposable *disposable = [RACDisposable disposableWithBlock:^{ + [subscriber sendCompleted]; + }]; + [self.rac_deallocDisposable addDisposable:disposable]; + + return [RACDisposable disposableWithBlock:^{ + @strongify(self); + [self.rac_deallocDisposable removeDisposable:disposable]; + [self removeTarget:subscriber action:@selector(sendNext:) forControlEvents:controlEvents]; + }]; + }] + setNameWithFormat:@"%@ -rac_signalForControlEvents: %lx", RACDescription(self), (unsigned long)controlEvents]; +} + +@end diff --git a/ReactiveObjC/UIControl+RACSignalSupportPrivate.m b/ReactiveObjC/UIControl+RACSignalSupportPrivate.m new file mode 100644 index 000000000..867f57e74 --- /dev/null +++ b/ReactiveObjC/UIControl+RACSignalSupportPrivate.m @@ -0,0 +1,48 @@ +// +// UIControl+RACSignalSupportPrivate.m +// ReactiveObjC +// +// Created by Uri Baghin on 06/08/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIControl+RACSignalSupportPrivate.h" +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACLifting.h" +#import "RACChannel.h" +#import "RACCompoundDisposable.h" +#import "RACDisposable.h" +#import "RACSignal+Operations.h" +#import "UIControl+RACSignalSupport.h" + +@implementation UIControl (RACSignalSupportPrivate) + +- (RACChannelTerminal *)rac_channelForControlEvents:(UIControlEvents)controlEvents key:(NSString *)key nilValue:(id)nilValue { + NSCParameterAssert(key.length > 0); + key = [key copy]; + RACChannel *channel = [[RACChannel alloc] init]; + + [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ + [channel.followingTerminal sendCompleted]; + }]]; + + RACSignal *eventSignal = [[[self + rac_signalForControlEvents:controlEvents] + mapReplace:key] + takeUntil:[[channel.followingTerminal + ignoreValues] + catchTo:RACSignal.empty]]; + [[self + rac_liftSelector:@selector(valueForKey:) withSignals:eventSignal, nil] + subscribe:channel.followingTerminal]; + + RACSignal *valuesSignal = [channel.followingTerminal + map:^(id value) { + return value ?: nilValue; + }]; + [self rac_liftSelector:@selector(setValue:forKey:) withSignals:valuesSignal, [RACSignal return:key], nil]; + + return channel.leadingTerminal; +} + +@end diff --git a/ReactiveObjC/UIDatePicker+RACSignalSupport.m b/ReactiveObjC/UIDatePicker+RACSignalSupport.m new file mode 100644 index 000000000..5c815c2f2 --- /dev/null +++ b/ReactiveObjC/UIDatePicker+RACSignalSupport.m @@ -0,0 +1,19 @@ +// +// UIDatePicker+RACSignalSupport.m +// ReactiveObjC +// +// Created by Uri Baghin on 20/07/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIDatePicker+RACSignalSupport.h" +#import +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UIDatePicker (RACSignalSupport) + +- (RACChannelTerminal *)rac_newDateChannelWithNilValue:(NSDate *)nilValue { + return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.date) nilValue:nilValue]; +} + +@end diff --git a/ReactiveObjC/UIGestureRecognizer+RACSignalSupport.m b/ReactiveObjC/UIGestureRecognizer+RACSignalSupport.m new file mode 100644 index 000000000..4f816eb8e --- /dev/null +++ b/ReactiveObjC/UIGestureRecognizer+RACSignalSupport.m @@ -0,0 +1,40 @@ +// +// UIGestureRecognizer+RACSignalSupport.m +// ReactiveObjC +// +// Created by Josh Vera on 5/5/13. +// Copyright (c) 2013 GitHub. All rights reserved. +// + +#import "UIGestureRecognizer+RACSignalSupport.h" +#import +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import "RACCompoundDisposable.h" +#import "RACDisposable.h" +#import "RACSignal.h" +#import "RACSubscriber.h" + +@implementation UIGestureRecognizer (RACSignalSupport) + +- (RACSignal *)rac_gestureSignal { + @weakify(self); + + return [[RACSignal + createSignal:^(id subscriber) { + @strongify(self); + + [self addTarget:subscriber action:@selector(sendNext:)]; + [self.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ + [subscriber sendCompleted]; + }]]; + + return [RACDisposable disposableWithBlock:^{ + @strongify(self); + [self removeTarget:subscriber action:@selector(sendNext:)]; + }]; + }] + setNameWithFormat:@"%@ -rac_gestureSignal", RACDescription(self)]; +} + +@end diff --git a/ReactiveObjC/UIImagePickerController+RACSignalSupport.m b/ReactiveObjC/UIImagePickerController+RACSignalSupport.m new file mode 100644 index 000000000..a5df4eec7 --- /dev/null +++ b/ReactiveObjC/UIImagePickerController+RACSignalSupport.m @@ -0,0 +1,53 @@ +// +// UIImagePickerController+RACSignalSupport.m +// ReactiveObjC +// +// Created by Timur Kuchkarov on 28.03.14. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +#import "UIImagePickerController+RACSignalSupport.h" +#import "RACDelegateProxy.h" +#import "RACSignal+Operations.h" +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import + +@implementation UIImagePickerController (RACSignalSupport) + +static void RACUseDelegateProxy(UIImagePickerController *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(UIImagePickerControllerDelegate)]; + objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + + return proxy; +} + +- (RACSignal *)rac_imageSelectedSignal { + RACSignal *pickerCancelledSignal = [[self.rac_delegateProxy + signalForSelector:@selector(imagePickerControllerDidCancel:)] + merge:self.rac_willDeallocSignal]; + + RACSignal *imagePickerSignal = [[[[self.rac_delegateProxy + signalForSelector:@selector(imagePickerController:didFinishPickingMediaWithInfo:)] + reduceEach:^(UIImagePickerController *pickerController, NSDictionary *userInfo) { + return userInfo; + }] + takeUntil:pickerCancelledSignal] + setNameWithFormat:@"%@ -rac_imageSelectedSignal", RACDescription(self)]; + + RACUseDelegateProxy(self); + + return imagePickerSignal; +} + +@end diff --git a/ReactiveObjC/UIRefreshControl+RACCommandSupport.m b/ReactiveObjC/UIRefreshControl+RACCommandSupport.m new file mode 100644 index 000000000..3301ca194 --- /dev/null +++ b/ReactiveObjC/UIRefreshControl+RACCommandSupport.m @@ -0,0 +1,59 @@ +// +// UIRefreshControl+RACCommandSupport.m +// ReactiveObjC +// +// Created by Dave Lee on 2013-10-17. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIRefreshControl+RACCommandSupport.h" +#import +#import "RACCommand.h" +#import "RACCompoundDisposable.h" +#import "RACDisposable.h" +#import "RACSignal.h" +#import "RACSignal+Operations.h" +#import "UIControl+RACSignalSupport.h" +#import + +static void *UIRefreshControlRACCommandKey = &UIRefreshControlRACCommandKey; +static void *UIRefreshControlDisposableKey = &UIRefreshControlDisposableKey; + +@implementation UIRefreshControl (RACCommandSupport) + +- (RACCommand *)rac_command { + return objc_getAssociatedObject(self, UIRefreshControlRACCommandKey); +} + +- (void)setRac_command:(RACCommand *)command { + objc_setAssociatedObject(self, UIRefreshControlRACCommandKey, command, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // Dispose of any active command associations. + [objc_getAssociatedObject(self, UIRefreshControlDisposableKey) dispose]; + + if (command == nil) return; + + // Like RAC(self, enabled) = command.enabled; but with access to disposable. + RACDisposable *enabledDisposable = [command.enabled setKeyPath:@keypath(self.enabled) onObject:self]; + + RACDisposable *executionDisposable = [[[[[self + rac_signalForControlEvents:UIControlEventValueChanged] + map:^(UIRefreshControl *x) { + return [[[command + execute:x] + catchTo:[RACSignal empty]] + then:^{ + return [RACSignal return:x]; + }]; + }] + concat] + deliverOnMainThread] + subscribeNext:^(UIRefreshControl *x) { + [x endRefreshing]; + }]; + + RACDisposable *commandDisposable = [RACCompoundDisposable compoundDisposableWithDisposables:@[ enabledDisposable, executionDisposable ]]; + objc_setAssociatedObject(self, UIRefreshControlDisposableKey, commandDisposable, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +@end diff --git a/ReactiveObjC/UISegmentedControl+RACSignalSupport.m b/ReactiveObjC/UISegmentedControl+RACSignalSupport.m new file mode 100644 index 000000000..782cabca0 --- /dev/null +++ b/ReactiveObjC/UISegmentedControl+RACSignalSupport.m @@ -0,0 +1,19 @@ +// +// UISegmentedControl+RACSignalSupport.m +// ReactiveObjC +// +// Created by Uri Baghin on 20/07/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UISegmentedControl+RACSignalSupport.h" +#import +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UISegmentedControl (RACSignalSupport) + +- (RACChannelTerminal *)rac_newSelectedSegmentIndexChannelWithNilValue:(NSNumber *)nilValue { + return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.selectedSegmentIndex) nilValue:nilValue]; +} + +@end diff --git a/ReactiveObjC/UISlider+RACSignalSupport.m b/ReactiveObjC/UISlider+RACSignalSupport.m new file mode 100644 index 000000000..3583d843c --- /dev/null +++ b/ReactiveObjC/UISlider+RACSignalSupport.m @@ -0,0 +1,19 @@ +// +// UISlider+RACSignalSupport.m +// ReactiveObjC +// +// Created by Uri Baghin on 20/07/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UISlider+RACSignalSupport.h" +#import +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UISlider (RACSignalSupport) + +- (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue { + return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.value) nilValue:nilValue]; +} + +@end diff --git a/ReactiveObjC/UIStepper+RACSignalSupport.m b/ReactiveObjC/UIStepper+RACSignalSupport.m new file mode 100644 index 000000000..5eee8f853 --- /dev/null +++ b/ReactiveObjC/UIStepper+RACSignalSupport.m @@ -0,0 +1,19 @@ +// +// UIStepper+RACSignalSupport.m +// ReactiveObjC +// +// Created by Uri Baghin on 20/07/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UIStepper+RACSignalSupport.h" +#import +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UIStepper (RACSignalSupport) + +- (RACChannelTerminal *)rac_newValueChannelWithNilValue:(NSNumber *)nilValue { + return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.value) nilValue:nilValue]; +} + +@end diff --git a/ReactiveObjC/UISwitch+RACSignalSupport.m b/ReactiveObjC/UISwitch+RACSignalSupport.m new file mode 100644 index 000000000..a5f847d80 --- /dev/null +++ b/ReactiveObjC/UISwitch+RACSignalSupport.m @@ -0,0 +1,19 @@ +// +// UISwitch+RACSignalSupport.m +// ReactiveObjC +// +// Created by Uri Baghin on 20/07/2013. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UISwitch+RACSignalSupport.h" +#import +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UISwitch (RACSignalSupport) + +- (RACChannelTerminal *)rac_newOnChannel { + return [self rac_channelForControlEvents:UIControlEventValueChanged key:@keypath(self.on) nilValue:@NO]; +} + +@end diff --git a/ReactiveObjC/UITableViewCell+RACSignalSupport.m b/ReactiveObjC/UITableViewCell+RACSignalSupport.m new file mode 100644 index 000000000..5cf9dfa44 --- /dev/null +++ b/ReactiveObjC/UITableViewCell+RACSignalSupport.m @@ -0,0 +1,31 @@ +// +// UITableViewCell+RACSignalSupport.m +// ReactiveObjC +// +// Created by Justin Spahr-Summers on 2013-07-22. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UITableViewCell+RACSignalSupport.h" +#import "NSObject+RACDescription.h" +#import "NSObject+RACSelectorSignal.h" +#import "RACSignal+Operations.h" +#import "RACUnit.h" +#import + +@implementation UITableViewCell (RACSignalSupport) + +- (RACSignal *)rac_prepareForReuseSignal { + RACSignal *signal = objc_getAssociatedObject(self, _cmd); + if (signal != nil) return signal; + + signal = [[[self + rac_signalForSelector:@selector(prepareForReuse)] + mapReplace:RACUnit.defaultUnit] + setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; + + objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return signal; +} + +@end diff --git a/ReactiveObjC/UITableViewHeaderFooterView+RACSignalSupport.m b/ReactiveObjC/UITableViewHeaderFooterView+RACSignalSupport.m new file mode 100644 index 000000000..a0ffb436a --- /dev/null +++ b/ReactiveObjC/UITableViewHeaderFooterView+RACSignalSupport.m @@ -0,0 +1,31 @@ +// +// UITableViewHeaderFooterView+RACSignalSupport.m +// ReactiveObjC +// +// Created by Syo Ikeda on 12/30/13. +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// + +#import "UITableViewHeaderFooterView+RACSignalSupport.h" +#import "NSObject+RACDescription.h" +#import "NSObject+RACSelectorSignal.h" +#import "RACSignal+Operations.h" +#import "RACUnit.h" +#import + +@implementation UITableViewHeaderFooterView (RACSignalSupport) + +- (RACSignal *)rac_prepareForReuseSignal { + RACSignal *signal = objc_getAssociatedObject(self, _cmd); + if (signal != nil) return signal; + + signal = [[[self + rac_signalForSelector:@selector(prepareForReuse)] + mapReplace:RACUnit.defaultUnit] + setNameWithFormat:@"%@ -rac_prepareForReuseSignal", RACDescription(self)]; + + objc_setAssociatedObject(self, _cmd, signal, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + return signal; +} + +@end diff --git a/ReactiveObjC/UITextField+RACSignalSupport.m b/ReactiveObjC/UITextField+RACSignalSupport.m new file mode 100644 index 000000000..b02444858 --- /dev/null +++ b/ReactiveObjC/UITextField+RACSignalSupport.m @@ -0,0 +1,39 @@ +// +// UITextField+RACSignalSupport.m +// ReactiveObjC +// +// Created by Josh Abernathy on 4/17/12. +// Copyright (c) 2012 GitHub, Inc. All rights reserved. +// + +#import "UITextField+RACSignalSupport.h" +#import +#import +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import "RACSignal+Operations.h" +#import "UIControl+RACSignalSupport.h" +#import "UIControl+RACSignalSupportPrivate.h" + +@implementation UITextField (RACSignalSupport) + +- (RACSignal *)rac_textSignal { + @weakify(self); + return [[[[[RACSignal + defer:^{ + @strongify(self); + return [RACSignal return:self]; + }] + concat:[self rac_signalForControlEvents:UIControlEventAllEditingEvents]] + map:^(UITextField *x) { + return x.text; + }] + takeUntil:self.rac_willDeallocSignal] + setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; +} + +- (RACChannelTerminal *)rac_newTextChannel { + return [self rac_channelForControlEvents:UIControlEventAllEditingEvents key:@keypath(self.text) nilValue:@""]; +} + +@end diff --git a/ReactiveObjC/UITextView+RACSignalSupport.m b/ReactiveObjC/UITextView+RACSignalSupport.m new file mode 100644 index 000000000..d47f6e59c --- /dev/null +++ b/ReactiveObjC/UITextView+RACSignalSupport.m @@ -0,0 +1,56 @@ +// +// UITextView+RACSignalSupport.m +// ReactiveObjC +// +// Created by Cody Krieger on 5/18/12. +// Copyright (c) 2012 Cody Krieger. All rights reserved. +// + +#import "UITextView+RACSignalSupport.h" +#import +#import "NSObject+RACDeallocating.h" +#import "NSObject+RACDescription.h" +#import "RACDelegateProxy.h" +#import "RACSignal+Operations.h" +#import "RACTuple.h" +#import + +@implementation UITextView (RACSignalSupport) + +static void RACUseDelegateProxy(UITextView *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(UITextViewDelegate)]; + objc_setAssociatedObject(self, _cmd, proxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + + return proxy; +} + +- (RACSignal *)rac_textSignal { + @weakify(self); + RACSignal *signal = [[[[[RACSignal + defer:^{ + @strongify(self); + return [RACSignal return:RACTuplePack(self)]; + }] + concat:[self.rac_delegateProxy signalForSelector:@selector(textViewDidChange:)]] + reduceEach:^(UITextView *x) { + return x.text; + }] + takeUntil:self.rac_willDeallocSignal] + setNameWithFormat:@"%@ -rac_textSignal", RACDescription(self)]; + + RACUseDelegateProxy(self); + + return signal; +} + +@end diff --git a/ReactiveObjC/include/ReactiveObjC/ReactiveObjC.h b/ReactiveObjC/include/ReactiveObjC/ReactiveObjC.h index a26ba09ac..2a0e2bfab 100644 --- a/ReactiveObjC/include/ReactiveObjC/ReactiveObjC.h +++ b/ReactiveObjC/include/ReactiveObjC/ReactiveObjC.h @@ -69,35 +69,35 @@ FOUNDATION_EXPORT const unsigned char ReactiveObjCVersionString[]; #import #import -// #if TARGET_OS_WATCH -// #elif TARGET_OS_IOS || TARGET_OS_TV -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import +#if TARGET_OS_WATCH +#elif TARGET_OS_IOS || TARGET_OS_TV + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import -// #if TARGET_OS_IOS -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #import -// #endif -// #elif TARGET_OS_MAC -// #import -// #import -// #import -// #import -// #import -// #endif + #if TARGET_OS_IOS + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #endif +#elif TARGET_OS_MAC + #import + #import + #import + #import + #import +#endif