Skip to content

Instantly share code, notes, and snippets.

View jspahrsummers's full-sized avatar

Justin Spahr-Summers jspahrsummers

View GitHub Profile
RACSequence *views = [RACSequence concat:@[
self.buttons.rac_sequence,
self.buttonLabels.rac_sequence,
self.informationLabels.rac_sequence
]];
for (NSView *view in views) {
[view.layer rac_liftSelector:@selector(addAnimation:forKey:) withObjects:refreshingAnimation, @"opacity"];
}
- (id)initWithFrame:(CGRect)rect {
self = [super initWithFrame:rect];
if (self == nil) return nil;
[self initializeComponent];
RAC(self.title.text) = RACAble(self.viewModel.model.title);
RAC(self.userAndOrgTiles.itemSource) = RACAble(self.viewModel.userAndOrgTiles);
self.loginButton.rac_command = self.viewModel.showLoginCommand;
- (RACSignal*)friendsId
{
return [self enqueueWithCursor:-1];
}
- (RACSignal*)enqueueWithCursor:(NSInteger)cursor
{
@weakify(self);
return [[self idsAtCursor:cursor]
// Map each `next` (there should only be one) to a new signal.
@jspahrsummers
jspahrsummers / RACSocketReader.h
Last active December 14, 2015 04:59
An example of emulating an asynchronous pull-driven stream with lazy signals. The idea is that the producer (in this case, a socket) should be throttled to a speed that the consumer (the signal subscribers) can handle – accomplished here by using multiple individual signals which only read data when subscribed to.
@interface RACSocketReader : NSObject
// Sends a RACSignal whenever there's new data ready to be read. Each signal
// will send an NSData upon subscription.
//
// If you only want the NSData objects as fast as possible, simply -concat
// this signal to get a eager signal of NSData values.
@property (nonatomic, strong, readonly) RACSignal *signalOfDataSignals;
- (id)initWithSocketDescriptor:(int)fildes;
@jspahrsummers
jspahrsummers / gist:5490301
Last active December 16, 2015 20:09
Demonstrating the semantics of __weak objects in Objective-C. See http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics for more information.
// The weak pointer is read, and retained until the message send completes its synchronous work.
[weakValue doAThing];
@jspahrsummers
jspahrsummers / gist:5676550
Last active December 17, 2015 21:39
More complex RAC form validation
// Check name validity
RACSignal *nameValid = [RACAbleWithStart(self.name) map:^(NSString *name) {
return @(name.length > 0);
}];
RACSignal *nameValidationMessage = [nameValid map:^ id (NSNumber *valid) {
return valid.boolValue ? nil : @"Please enter a name that matches our bullshit rules";
}];
// Check email validity
@jspahrsummers
jspahrsummers / gist:5780224
Last active September 26, 2019 05:24
Untested proof of concept for a better @weakify macro.
#define $(...) \
({ \
__weak __typeof__(self) weakSelf = self; \
\
^(__VA_ARGS__) { \
__strong __typeof__(weakSelf) self = weakSelf; \
$_body_
#define $_body_(...) \
__VA_ARGS__ \
@jspahrsummers
jspahrsummers / gist:5812222
Last active December 18, 2015 16:29
Make "self" cause a compilation error only within blocks.
#define self \
( \
_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-value\"") self, \
/* Depends on _cmd being a const copy, like other captured variables. */ \
_Pragma("clang diagnostic pop") (*(_cmd = _cmd, &self)) \
)
// Replace libextobjc's @weakify with one that's aware of the "self" macro.
#undef ext_weakify_
#define ext_weakify_(INDEX, CONTEXT, VAR) \
@jspahrsummers
jspahrsummers / gist:6400596
Created August 31, 2013 20:57
Error installing ResourceT using Cabal and GHC 7.6.3.
Control/Monad/Trans/Resource.hs:613:24:
Could not deduce (m ~ IO)
from the context (MonadBaseControl IO m)
bound by the type signature for
resourceForkIO :: MonadBaseControl IO m =>
ResourceT m () -> ResourceT m ThreadId
at Control/Monad/Trans/Resource.hs:601:19-81
`m' is a rigid type variable bound by
the type signature for
resourceForkIO :: MonadBaseControl IO m =>
@jspahrsummers
jspahrsummers / gist:6940184
Last active December 25, 2015 07:38
lol recursive blocks
__block void (^myRecursiveBlock)(int);
id myBlock = ^(int x) {
if (x > 5) {
// Release the block from its own implicit retain cycle.
myRecursiveBlock = nil;
} else {
myRecursiveBlock(x + 1);
}
};