Created
August 24, 2016 12:35
-
-
Save mbaranowski/a7b962d3f4323506e5d95584e81bba7c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#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