Skip to content

Instantly share code, notes, and snippets.

@mbaranowski
Created August 24, 2016 12:35
Show Gist options
  • Save mbaranowski/a7b962d3f4323506e5d95584e81bba7c to your computer and use it in GitHub Desktop.
Save mbaranowski/a7b962d3f4323506e5d95584e81bba7c to your computer and use it in GitHub Desktop.
#import "MinReact.h"
@implementation ActionStateInit
@end
@implementation Subscription
@end
@interface Store ()
@property (nonatomic) id<StateType> _Nullable state;
@property (nonatomic) NSMutableArray<Subscription *>* _Nonnull subscriptions;
@property (nonatomic) id<AnyReducer> _Nonnull reducer;
@property (nonatomic) BOOL isDispatching;
@end
@interface NSArray (Reduce)
-(id)reduceWithBlock:(id (^)(id memo, id element))block
startValue:(id)memo;
@end
@implementation NSArray (Reduce)
-(id)reduceWithBlock:(id (^)(id memo, id element))block
startValue:(id)memo
{
for (id obj in self) {
memo = block(memo, obj);
}
return memo;
}
@end
@implementation Store
-(void)setState:(id<StateType> _Nullable) state {
_state = state;
for (Subscription* sub in self.subscriptions) {
__strong id<AnyStoreSubscriber> subscriber = sub.subscriber;
if (subscriber != nil) {
[subscriber newState:state];
}
}
}
-(instancetype _Nonnull)initWithReducer:(id<AnyReducer> _Nonnull)reducer
state:(id<StateType> _Nullable)state
middleware:(NSArray<Middleware>* _Nullable)middleware;
{
self = [super init];
if (self) {
self.reducer = reducer;
self.state = state;
self.subscriptions = [NSMutableArray new];
if (self.state == nil) {
[self dispatch:[ActionStateInit new]];
}
}
return self;
}
-(id)dispatch:(id<Action>)action {
return [self _dispatch:action];
}
-(id)_dispatch:(id<Action>)action
{
guard(!self.isDispatching) else {
NSAssert(false, @"Reducers may not dispatch actions.");
return nil;
}
self.isDispatching = YES;
id<StateType> newState = [self.reducer handleAction:action state:self.state];
self.isDispatching = NO;
// set state and alert all subscribers
self.state = newState;
return action;
}
-(BOOL)isNewSubscriber:(id<AnyStoreSubscriber>)subscriber {
for (Subscription* sub in self.subscriptions) {
if (sub.subscriber == subscriber) {
return NO;
}
}
return YES;
}
-(void)subscribe:(id<AnyStoreSubscriber>)subscriber selector:(StateSelector)selector {
if (![self isNewSubscriber:subscriber]) {
NSLog(@"adding an existing subscriber %@ to store", subscriber);
return;
}
Subscription* sub = [Subscription new];
sub.subscriber = subscriber;
sub.selector = selector;
[self.subscriptions addObject:sub];
}
-(void)unscubscribe:(id<AnyStoreSubscriber>)subscriber {
NSInteger idx =
[self.subscriptions indexOfObjectPassingTest:^BOOL(Subscription * _Nonnull obj, NSUInteger i, BOOL * _Nonnull stop) {
if (obj.subscriber == subscriber) {
*stop = YES;
return YES;
}
return NO;
}];
if (idx != NSNotFound) {
[self.subscriptions removeObjectAtIndex:idx];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment