forked from ReactiveCocoa/ReactiveObjC
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
96af78a
commit 241b0b8
Showing
27 changed files
with
1,155 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <objc/runtime.h> | ||
|
||
@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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <objc/runtime.h> | ||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <ReactiveObjC/EXTScope.h> | ||
#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<RACSubscriber> 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <ReactiveObjC/EXTKeyPathCoding.h> | ||
#import <ReactiveObjC/EXTScope.h> | ||
#import "NSObject+RACDeallocating.h" | ||
#import "RACChannel.h" | ||
#import "RACCompoundDisposable.h" | ||
#import "RACDisposable.h" | ||
#import "RACKVOChannel.h" | ||
#import "RACValueTransformer.h" | ||
#import <objc/runtime.h> | ||
|
||
// 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 <NSKeyValueObserving> 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <ReactiveObjC/EXTScope.h> | ||
#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<RACSubscriber> 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 |
Oops, something went wrong.