|
| 1 | +// |
| 2 | +// LPEventCallbackManager.m |
| 3 | +// Pods |
| 4 | +// |
| 5 | +// Created by Alexis Oyama on 7/11/17. |
| 6 | +// |
| 7 | +// |
| 8 | + |
| 9 | +#import "LPEventCallbackManager.h" |
| 10 | +#import "LeanplumRequest.h" |
| 11 | + |
| 12 | +@implementation LPEventCallback |
| 13 | + |
| 14 | +- (id)initWithResponseBlock:(LPNetworkResponseBlock)responseBlock |
| 15 | + errorBlock:(LPNetworkErrorBlock)errorBlock |
| 16 | +{ |
| 17 | + if (self = [super init]) { |
| 18 | + self.responseBlock = [responseBlock copy]; |
| 19 | + self.errorBlock = [errorBlock copy]; |
| 20 | + } |
| 21 | + return self; |
| 22 | +} |
| 23 | + |
| 24 | +- (void)invokeResponseWithOperation:(id<LPNetworkOperationProtocol>)operation |
| 25 | + response:(id)response |
| 26 | +{ |
| 27 | + if (self.responseBlock) { |
| 28 | + self.responseBlock(operation, response); |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +- (void)invokeError:(NSError *)error |
| 33 | +{ |
| 34 | + if (self.errorBlock) { |
| 35 | + self.errorBlock(error); |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +@end |
| 40 | + |
| 41 | +@implementation LPEventCallbackManager |
| 42 | + |
| 43 | ++ (NSMutableDictionary *)eventCallbackMap |
| 44 | +{ |
| 45 | + static NSMutableDictionary *_eventCallbackMap; |
| 46 | + static dispatch_once_t eventCallbackMapToken; |
| 47 | + dispatch_once(&eventCallbackMapToken, ^{ |
| 48 | + _eventCallbackMap = [NSMutableDictionary new]; |
| 49 | + }); |
| 50 | + return _eventCallbackMap; |
| 51 | +} |
| 52 | + |
| 53 | ++ (void)addEventCallbackAt:(NSInteger)index |
| 54 | + onSuccess:(LPNetworkResponseBlock)responseBlock |
| 55 | + onError:(LPNetworkErrorBlock)errorBlock |
| 56 | +{ |
| 57 | + if (!responseBlock && !errorBlock) { |
| 58 | + return; |
| 59 | + } |
| 60 | + |
| 61 | + NSMutableDictionary *callbackMap = [LPEventCallbackManager eventCallbackMap]; |
| 62 | + LPEventCallback *callback = [[LPEventCallback alloc] initWithResponseBlock:responseBlock |
| 63 | + errorBlock:errorBlock]; |
| 64 | + callbackMap[@(index)] = callback; |
| 65 | +} |
| 66 | + |
| 67 | ++ (void)invokeSuccessCallbacksOnResponses:(id)responses |
| 68 | + requests:(NSArray *)requests |
| 69 | + operation:(id<LPNetworkOperationProtocol>)operation |
| 70 | +{ |
| 71 | + // Invoke and remove the callbacks that have errors. |
| 72 | + [LPEventCallbackManager invokeErrorCallbacksOnResponses:responses]; |
| 73 | + |
| 74 | + NSMutableDictionary *callbackMap = [LPEventCallbackManager eventCallbackMap]; |
| 75 | + NSMutableDictionary *updatedCallbackMap = [NSMutableDictionary new]; |
| 76 | + NSMutableDictionary *activeResponseMap = [NSMutableDictionary new]; |
| 77 | + |
| 78 | + for (NSNumber *indexObject in callbackMap.allKeys) { |
| 79 | + NSInteger index = [indexObject integerValue]; |
| 80 | + LPEventCallback *eventCallback = callbackMap[indexObject]; |
| 81 | + |
| 82 | + // If index is in range, execute and remove it. |
| 83 | + // If not, requests are in the future. Update the index. |
| 84 | + [callbackMap removeObjectForKey:indexObject]; |
| 85 | + if (index >= requests.count) { |
| 86 | + index -= requests.count; |
| 87 | + updatedCallbackMap[@(index)] = eventCallback; |
| 88 | + } else if (eventCallback.responseBlock) { |
| 89 | + activeResponseMap[indexObject] = [eventCallback.responseBlock copy]; |
| 90 | + } |
| 91 | + } |
| 92 | + [callbackMap addEntriesFromDictionary:updatedCallbackMap]; |
| 93 | + |
| 94 | + // Execute responses afterwards to prevent index collision. |
| 95 | + [activeResponseMap enumerateKeysAndObjectsUsingBlock:^(NSNumber *indexObject, LPNetworkResponseBlock responseBlock, BOOL *stop) { |
| 96 | + NSInteger index = [indexObject integerValue]; |
| 97 | + id response = [LPResponse getResponseAt:index fromDictionary:responses]; |
| 98 | + responseBlock(operation, response); |
| 99 | + }]; |
| 100 | +} |
| 101 | + |
| 102 | ++ (void)invokeErrorCallbacksOnResponses:(id)responses |
| 103 | +{ |
| 104 | + // Handle errors that don't return an HTTP error code. |
| 105 | + NSMutableDictionary *callbackMap = [LPEventCallbackManager eventCallbackMap]; |
| 106 | + for (NSUInteger i = 0; i < [LPResponse numResponsesInDictionary:responses]; i++) { |
| 107 | + NSDictionary *response = [LPResponse getResponseAt:i fromDictionary:responses]; |
| 108 | + if ([LPResponse isResponseSuccess:response]) { |
| 109 | + continue; |
| 110 | + } |
| 111 | + |
| 112 | + NSString *errorMessage = @"API error"; |
| 113 | + NSString *responseError = [LPResponse getResponseError:response]; |
| 114 | + if (responseError) { |
| 115 | + errorMessage = [NSString stringWithFormat:@"API error: %@", errorMessage]; |
| 116 | + } |
| 117 | + NSLog(@"Leanplum: %@", errorMessage); |
| 118 | + |
| 119 | + LPEventCallback *callback = callbackMap[@(i)]; |
| 120 | + if (callback) { |
| 121 | + [callbackMap removeObjectForKey:@(i)]; |
| 122 | + NSError *error = [NSError errorWithDomain:@"Leanplum" code:2 |
| 123 | + userInfo:@{NSLocalizedDescriptionKey: errorMessage}]; |
| 124 | + [callback invokeError:error]; |
| 125 | + } |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | ++ (void)invokeErrorCallbacksWithError:(NSError *)error |
| 130 | +{ |
| 131 | + NSMutableDictionary *callbackMap = [LPEventCallbackManager eventCallbackMap]; |
| 132 | + for (LPEventCallback *callback in callbackMap) { |
| 133 | + [callback invokeError:error]; |
| 134 | + } |
| 135 | + [callbackMap removeAllObjects]; |
| 136 | +} |
| 137 | + |
| 138 | +@end |
0 commit comments