From adaab5c7c6d400e2cfb002a103586ccd6b26cdf9 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 13:05:44 +0800 Subject: [PATCH 01/23] Support iOS6 and AFNetwork1.3.x --- Classes/JCStockPriceStore.m | 4 ++-- JCStockGraph.podspec | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 5ae2bd8..10837bc 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -69,9 +69,9 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre //Create Request: AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - AFHTTPResponseSerializer *serializer = [AFHTTPResponseSerializer serializer]; + /* AFHTTPResponseSerializer *serializer = [AFHTTPResponseSerializer serializer]; serializer.acceptableContentTypes = [serializer.acceptableContentTypes setByAddingObject:@"text/csv"]; - operation.responseSerializer = serializer; + operation.responseSerializer = serializer;*/ [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; diff --git a/JCStockGraph.podspec b/JCStockGraph.podspec index 245015e..432fb1d 100644 --- a/JCStockGraph.podspec +++ b/JCStockGraph.podspec @@ -8,15 +8,15 @@ Pod::Spec.new do |s| s.author = { "Joseph Constantakis" => "jcon5294@gmail.com" } s.source = { :git => "https://github.com/jconst/JCStockGraph.git", :tag => s.version.to_s } - s.platform = :ios, '7.0' - s.ios.deployment_target = '7.0' + s.platform = :ios, '6.0' + s.ios.deployment_target = '6.0' s.requires_arc = true s.source_files = 'Classes' s.public_header_files = 'Classes/*.h' s.dependency 'CorePlot', '~> 1.5' - s.dependency 'AFNetworking', '~> 2.0' + s.dependency 'AFNetworking', '~> 1.3.0' s.dependency 'MBProgressHUD', '~> 0.8' s.dependency 'MTDates', '~> 0.12' s.dependency 'FontasticIcons', '~> 0.5' From 3671201e7d47d287ef1218fbf342dd671eaba7cd Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 14:40:06 +0800 Subject: [PATCH 02/23] Remove currency symbol and reverse the graph order. --- Classes/JCStockGraphController.h | 8 ++++---- Classes/JCStockGraphView.m | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Classes/JCStockGraphController.h b/Classes/JCStockGraphController.h index 9ca931b..f196ae4 100755 --- a/Classes/JCStockGraphController.h +++ b/Classes/JCStockGraphController.h @@ -10,11 +10,11 @@ #import "CorePlot-CocoaTouch.h" typedef enum { - kGraphRange5Year = 0, - kGraphRange1Year, - kGraphRange3Month, + kGraphRange1Week = 0, kGraphRange1Month, - kGraphRange1Week, + kGraphRange3Month, + kGraphRange1Year, + kGraphRange5Year, kGraphRangeCount } JCStockGraphRange; diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index 7b848e8..3c562a5 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -115,6 +115,7 @@ - (void)configureYAxisWithPoints:(NSArray *)points priceFormatter.numberStyle = kCFNumberFormatterCurrencyStyle; priceFormatter.maximumSignificantDigits = 3; priceFormatter.usesSignificantDigits = YES; + priceFormatter.currencySymbol = @"$"; CPTXYAxis *y = axisSet.yAxis; y.axisConstraints = [CPTConstraints constraintWithLowerOffset:0]; From 36538d570d47d5f66bcf664aff0010fc060f11f4 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 17:19:49 +0800 Subject: [PATCH 03/23] 1. Added the TODAY stock price. 2. Disable the Cache. --- Classes/JCStockPriceStore.m | 71 +++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 10837bc..af36727 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -63,30 +63,62 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre } //Build URL: - NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", - ticker, [startDate yqlStartString], [endDate yqlEndString]]; + NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; NSURL *url = [NSURL URLWithString:urlString]; //Create Request: AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - /* AFHTTPResponseSerializer *serializer = [AFHTTPResponseSerializer serializer]; - serializer.acceptableContentTypes = [serializer.acceptableContentTypes setByAddingObject:@"text/csv"]; - operation.responseSerializer = serializer;*/ - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { - + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [points addObjectsFromArray:newPoints]; - if (comp) comp(points); + // Request current price.. + // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 + NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; + NSURL *url = [NSURL URLWithString:urlString]; + AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + NSMutableDictionary *passInfo = [[NSMutableDictionary alloc] init]; + [passInfo setValue:csvString forKey:@"oldString"]; + [operation2 setUserInfo:[passInfo copy]]; - [self cachePoints:points forTicker:ticker]; + [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + + NSString *csvString = [[operation userInfo] objectForKey:@"oldString"]; + NSString *todayString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + + // reformat the date string + NSMutableString *todayString2 = [todayString mutableCopy]; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; + [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"$3-$1-$2"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; + [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1-"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; + [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1"]; + todayString = [todayString2 copy]; + + + csvString=[csvString stringByAppendingString:todayString]; + + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [points addObjectsFromArray:newPoints]; + + if (comp) comp(points); + + [self cachePoints:points forTicker:ticker]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (comp) comp(nil); + NSLog(@"CSV request failure: %@", error); + }]; + [operation2 start]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (comp) comp(nil); NSLog(@"CSV request failure: %@", error); }]; + // Dowload Progress [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { long long expected = totalBytesExpectedToRead; if (expected == -1) @@ -96,6 +128,9 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre }]; [operation start]; + + + return NO; } @@ -117,16 +152,22 @@ - (NSArray *)dataPointsForCSVString:(NSString *)csvString NSMutableArray *points = [[NSMutableArray alloc] initWithCapacity:data.count]; NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; - for (NSString *rowString in [data reverseObjectEnumerator]) { + data = [data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + + NSDate *lastDate=nil; + for (NSString *rowString in data) { NSArray *row = [rowString componentsSeparatedByString:@","]; JCPriceDataPoint *point = [[JCPriceDataPoint alloc] init]; point.date = [NSDate mt_dateFromString:row[dateIndex] usingFormat:kDateFormatYahooAPI]; - + if ([point.date isEqual:lastDate]) continue; + NSString *closeString = row[closeIndex]; point.closePrice = [[nf numberFromString:closeString] doubleValue]; [points addObject:point]; + + lastDate = point.date; } return points; } @@ -180,8 +221,8 @@ - (id)init { self = [super init]; if (self) { - self.memoryCachingEnabled = YES; - self.diskCachingEnabled = YES; + self.memoryCachingEnabled = NO; + self.diskCachingEnabled = NO; inMemCache = [[NSMutableDictionary alloc] init]; } return self; From 60226f2f3165d20a6bad163c7dc800915cada200 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 20:33:50 +0800 Subject: [PATCH 04/23] Turn on the disk cache after separating history prices and today price caches. --- Classes/JCStockPriceStore.m | 193 +++++++++++++++++++++++------------- 1 file changed, 123 insertions(+), 70 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index af36727..cf015f0 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -37,99 +37,140 @@ + (JCStockPriceStore *)sharedInstance return sharedInstance; } +- (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points completion:(void (^)(NSArray *points))comp +{ + if (!comp) return; + + NSMutableArray *newArray = [[NSMutableArray alloc] init]; + [newArray addObjectsFromArray:points]; + JCPriceDataPoint *point = [newArray lastObject]; + JCPriceDataPoint *tPoint = [today_points objectAtIndex:0]; + if ([point.date isEqual:tPoint.date]==NO) + [newArray addObjectsFromArray:today_points]; + comp(newArray); + +} + +- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points completion:(void (^)(NSArray *points))comp +{ + // Request current price.. + // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 + NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; + + // escape for ^IXIC, ^INX + NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + NSMutableArray *today_points = [[NSMutableArray alloc] init]; + + NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + + // reformat the date string + NSMutableString *csvString_tmp = [csvString mutableCopy]; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"$3-$1-$2"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1-"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1"]; + csvString = [NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; + + + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [today_points addObjectsFromArray:newPoints]; + + [self cacheTodayPoints:today_points forTicker:ticker]; + + [self mergePoints:points todayPoints:today_points completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + NSLog(@"CSV request failure: %@", error); + }]; + [operation2 start]; +} + - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { NSAssert(ticker, @"tried to get historical data for null ticker"); if (!ticker && comp) comp(nil); __block NSMutableArray *points = [[NSMutableArray alloc] init]; + __block NSMutableArray *today_points = [[NSMutableArray alloc] init]; //Set time period: NSDate *endDate = [NSDate date]; NSDate *startDate = [endDate mt_dateYearsBefore:5]; //Check for previously cached data: + BOOL needUpdateLong = NO; + BOOL needUpdateTotday = NO; NSDictionary *cacheDict = [self loadCacheForTicker:ticker]; - if (cacheDict) { + if (cacheDict) + { //Found a cache; load it into our points array - [points addObjectsFromArray:cacheDict[@"data"]]; + [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... NSDate *cacheDate = cacheDict[@"cacheDate"]; - if ([cacheDate mt_isWithinSameDay:endDate]) { - if (comp) comp(points); - return YES; - } else { + if ([cacheDate mt_isWithinSameDay:endDate]==NO) + { startDate = cacheDate; + needUpdateTotday = YES; + needUpdateLong = YES; + } else { + // check short term data.. + [today_points addObjectsFromArray:cacheDict[@"today_data"]]; + cacheDate = cacheDict[@"cacheTodayDate"]; + if ([cacheDate mt_isWithinSameHour:endDate]==NO) + { + needUpdateTotday = YES; + } } + } else { + needUpdateLong = YES; + needUpdateTotday = YES; } - //Build URL: - NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; - NSURL *url = [NSURL URLWithString:urlString]; - - //Create Request: - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + if (needUpdateLong) { - NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + //Build URL: + NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; + // escape characters, ex. ^IXIC, ^INX + NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - // Request current price.. - // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 - NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; - NSURL *url = [NSURL URLWithString:urlString]; - AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - NSMutableDictionary *passInfo = [[NSMutableDictionary alloc] init]; - [passInfo setValue:csvString forKey:@"oldString"]; - [operation2 setUserInfo:[passInfo copy]]; + //Create Request: + AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [points addObjectsFromArray:newPoints]; + [self cachePoints:points forTicker:ticker]; + + [self getTodayStockPrice:ticker longPoints:points completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (comp) comp(nil); + NSLog(@"CSV request failure: %@", error); + }]; - [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) - { - - NSString *csvString = [[operation userInfo] objectForKey:@"oldString"]; - NSString *todayString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - - // reformat the date string - NSMutableString *todayString2 = [todayString mutableCopy]; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"$3-$1-$2"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1-"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1"]; - todayString = [todayString2 copy]; - - - csvString=[csvString stringByAppendingString:todayString]; - - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [points addObjectsFromArray:newPoints]; - - if (comp) comp(points); - - [self cachePoints:points forTicker:ticker]; - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (comp) comp(nil); - NSLog(@"CSV request failure: %@", error); + // Dowload Progress + [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double)totalBytesRead/(double)expected, 1.0); + if (progBlock) progBlock(prog); }]; - [operation2 start]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (comp) comp(nil); - NSLog(@"CSV request failure: %@", error); - }]; - - // Dowload Progress - [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { - long long expected = totalBytesExpectedToRead; - if (expected == -1) - expected = 75000; //A bit more than average - double prog = MIN((double)totalBytesRead/(double)expected, 1.0); - if (progBlock) progBlock(prog); - }]; - - [operation start]; - + [operation start]; + } + else if (needUpdateTotday) + { + [self getTodayStockPrice:ticker longPoints:points completion:comp]; + } else { + [self mergePoints:points todayPoints:today_points completion:comp]; + } return NO; } @@ -210,6 +251,18 @@ - (BOOL)cachePoints:(NSArray *)points forTicker:(NSString *)ticker return NO; } +- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker +{ + NSDictionary *cacheDict = @{@"cacheTodayDate": [NSDate date], @"today_data": points}; + inMemCache[ticker] = cacheDict; + + if (self.diskCachingEnabled) { + NSString *cachePath = [self cachePathForTicker:ticker]; + return [NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; + } + return NO; +} + - (void)setMemoryCachingEnabled:(BOOL)inMemoryCachingEnabled { inMemCache = nil; @@ -221,8 +274,8 @@ - (id)init { self = [super init]; if (self) { - self.memoryCachingEnabled = NO; - self.diskCachingEnabled = NO; + self.memoryCachingEnabled = YES; + self.diskCachingEnabled = YES; inMemCache = [[NSMutableDictionary alloc] init]; } return self; From 05f05ab62a3249294ebf3772ecff9730de8562b5 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 20:46:53 +0800 Subject: [PATCH 05/23] Turn on the disk cache after separating history prices and today price caches. --- Classes/JCStockPriceStore.m | 187 ++++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 72 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index af36727..b432b1e 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -37,99 +37,142 @@ + (JCStockPriceStore *)sharedInstance return sharedInstance; } +- (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points completion:(void (^)(NSArray *points))comp +{ + if (!comp) return; + + NSMutableArray *newArray = [[NSMutableArray alloc] init]; + [newArray addObjectsFromArray:points]; + JCPriceDataPoint *point = [newArray lastObject]; + JCPriceDataPoint *tPoint = [today_points objectAtIndex:0]; + if ([point.date isEqual:tPoint.date]==NO) + [newArray addObjectsFromArray:today_points]; + comp(newArray); + +} + +- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points completion:(void (^)(NSArray *points))comp +{ + // Request current price.. + // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 + NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; + + // escape for ^IXIC, ^INX + NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + NSMutableArray *today_points = [[NSMutableArray alloc] init]; + + NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + + // reformat the date string + NSMutableString *csvString_tmp = [csvString mutableCopy]; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"$3-$1-$2"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1-"]; + regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1"]; + csvString = [NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; + + + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [today_points addObjectsFromArray:newPoints]; + + [self cachePoints:points todayPoints:today_points forTicker:ticker]; + [self mergePoints:points todayPoints:today_points completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + NSLog(@"CSV request failure: %@", error); + }]; + [operation2 start]; +} + - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { NSAssert(ticker, @"tried to get historical data for null ticker"); if (!ticker && comp) comp(nil); __block NSMutableArray *points = [[NSMutableArray alloc] init]; + __block NSMutableArray *today_points = [[NSMutableArray alloc] init]; //Set time period: NSDate *endDate = [NSDate date]; NSDate *startDate = [endDate mt_dateYearsBefore:5]; //Check for previously cached data: + BOOL needUpdateLong = NO; + BOOL needUpdateTotday = NO; NSDictionary *cacheDict = [self loadCacheForTicker:ticker]; - if (cacheDict) { + if (cacheDict) + { //Found a cache; load it into our points array - [points addObjectsFromArray:cacheDict[@"data"]]; + [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... NSDate *cacheDate = cacheDict[@"cacheDate"]; - if ([cacheDate mt_isWithinSameDay:endDate]) { - if (comp) comp(points); - return YES; - } else { + if ([cacheDate mt_isWithinSameDay:endDate]==NO) + { startDate = cacheDate; + needUpdateTotday = YES; + needUpdateLong = YES; + } else { + // check short term data.. + [today_points addObjectsFromArray:cacheDict[@"today_data"]]; + cacheDate = cacheDict[@"cacheTodayDate"]; + if ( + [cacheDate mt_isWithinSameHour:endDate]==NO + || [today_points count]>1 + ) + { + needUpdateTotday = YES; + } } + } else { + needUpdateLong = YES; + needUpdateTotday = YES; } - //Build URL: - NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; - NSURL *url = [NSURL URLWithString:urlString]; - - //Create Request: - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + if (needUpdateLong) { - NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + //Build URL: + NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; + // escape characters, ex. ^IXIC, ^INX + NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - // Request current price.. - // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 - NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; - NSURL *url = [NSURL URLWithString:urlString]; - AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - NSMutableDictionary *passInfo = [[NSMutableDictionary alloc] init]; - [passInfo setValue:csvString forKey:@"oldString"]; - [operation2 setUserInfo:[passInfo copy]]; + //Create Request: + AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [points addObjectsFromArray:newPoints]; + + + [self getTodayStockPrice:ticker longPoints:points completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (comp) comp(nil); + NSLog(@"CSV request failure: %@", error); + }]; - [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) - { - - NSString *csvString = [[operation userInfo] objectForKey:@"oldString"]; - NSString *todayString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - - // reformat the date string - NSMutableString *todayString2 = [todayString mutableCopy]; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"$3-$1-$2"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1-"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; - [regex replaceMatchesInString:todayString2 options:0 range:NSMakeRange(0, [todayString2 length]) withTemplate:@"-0$1"]; - todayString = [todayString2 copy]; - - - csvString=[csvString stringByAppendingString:todayString]; - - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [points addObjectsFromArray:newPoints]; - - if (comp) comp(points); - - [self cachePoints:points forTicker:ticker]; - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (comp) comp(nil); - NSLog(@"CSV request failure: %@", error); + // Dowload Progress + [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double)totalBytesRead/(double)expected, 1.0); + if (progBlock) progBlock(prog); }]; - [operation2 start]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (comp) comp(nil); - NSLog(@"CSV request failure: %@", error); - }]; - - // Dowload Progress - [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { - long long expected = totalBytesExpectedToRead; - if (expected == -1) - expected = 75000; //A bit more than average - double prog = MIN((double)totalBytesRead/(double)expected, 1.0); - if (progBlock) progBlock(prog); - }]; - - [operation start]; - + [operation start]; + } + else if (needUpdateTotday) + { + [self getTodayStockPrice:ticker longPoints:points completion:comp]; + } else { + [self mergePoints:points todayPoints:today_points completion:comp]; + } return NO; } @@ -198,9 +241,9 @@ - (NSDictionary *)loadCacheForTicker:(NSString *)ticker return ret; } -- (BOOL)cachePoints:(NSArray *)points forTicker:(NSString *)ticker +- (BOOL)cachePoints:(NSArray *)points todayPoints:(NSArray *)today_points forTicker:(NSString *)ticker { - NSDictionary *cacheDict = @{@"cacheDate": [NSDate date], @"data": points}; + NSDictionary *cacheDict = @{@"cacheDate": [NSDate date], @"data": points, @"cacheTodayDate": [NSDate date], @"today_data": today_points}; inMemCache[ticker] = cacheDict; if (self.diskCachingEnabled) { @@ -221,8 +264,8 @@ - (id)init { self = [super init]; if (self) { - self.memoryCachingEnabled = NO; - self.diskCachingEnabled = NO; + self.memoryCachingEnabled = YES; + self.diskCachingEnabled = YES; inMemCache = [[NSMutableDictionary alloc] init]; } return self; From 330ce515f3f7e548438a0d67aa5a8aefe667e718 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 13 Aug 2014 23:46:00 +0800 Subject: [PATCH 06/23] add progress for current stock price. --- Classes/JCStockPriceStore.m | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index b432b1e..8777e1a 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -51,7 +51,7 @@ - (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points comple } -- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points completion:(void (^)(NSArray *points))comp +- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { // Request current price.. // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 @@ -86,6 +86,15 @@ - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points compl } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"CSV request failure: %@", error); }]; + + // Dowload Progress + [operation2 setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double)totalBytesRead/(double)expected, 1.0); + if (progBlock) progBlock(prog); + }]; [operation2 start]; } @@ -148,7 +157,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre [points addObjectsFromArray:newPoints]; - [self getTodayStockPrice:ticker longPoints:points completion:comp]; + [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (comp) comp(nil); @@ -169,7 +178,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre } else if (needUpdateTotday) { - [self getTodayStockPrice:ticker longPoints:points completion:comp]; + [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; } else { [self mergePoints:points todayPoints:today_points completion:comp]; } From 2725ddaa48ccac6dc2703210e9797e334d549fdb Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Thu, 14 Aug 2014 00:33:01 +0800 Subject: [PATCH 07/23] Fix the issue that Graph will be not loaded while the yahoo page is 404 Error. --- Classes/JCStockPriceStore.m | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 0b50b56..f7b95f9 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -40,13 +40,17 @@ + (JCStockPriceStore *)sharedInstance - (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points completion:(void (^)(NSArray *points))comp { if (!comp) return; + if (!points) return; NSMutableArray *newArray = [[NSMutableArray alloc] init]; [newArray addObjectsFromArray:points]; JCPriceDataPoint *point = [newArray lastObject]; - JCPriceDataPoint *tPoint = [today_points objectAtIndex:0]; - if ([point.date isEqual:tPoint.date]==NO) - [newArray addObjectsFromArray:today_points]; + if (today_points && [today_points count]>0) + { + JCPriceDataPoint *tPoint = [today_points objectAtIndex:0]; + if ([point.date isEqual:tPoint.date]==NO) + [newArray addObjectsFromArray:today_points]; + } comp(newArray); } @@ -86,6 +90,7 @@ - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points withP [self mergePoints:points todayPoints:today_points completion:comp]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + [self mergePoints:points todayPoints:nil completion:comp]; NSLog(@"CSV request failure: %@", error); }]; @@ -164,7 +169,8 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (comp) comp(nil); + // still try today stock price... + [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; NSLog(@"CSV request failure: %@", error); }]; From 0c0797d3a2f6e4d299c6aa494d0a5e1bddf8a290 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Thu, 14 Aug 2014 16:43:53 +0800 Subject: [PATCH 08/23] 1. Fix some case that will not show today stock price. 2. Adjust the position of "1 week" labels inside Graph. --- Classes/JCStockGraphView.m | 2 +- Classes/JCStockPriceStore.m | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index 3c562a5..540b970 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -195,7 +195,7 @@ - (void)addRangeLabel rangeLabel.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.4]; [rangeLabel sizeToFit]; rangeLabel.width += 8; - rangeLabel.y = self.height - rangeLabel.height; + rangeLabel.y = self.height; // - rangeLabel.height; rangeLabel.right = self.right; rangeLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin; [self addSubview:rangeLabel]; diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index f7b95f9..00b212b 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -56,7 +56,7 @@ - (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points comple } -- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp +- (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points todayPoints:(NSArray *)today_points withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { // Request current price.. // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 @@ -90,7 +90,7 @@ - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points withP [self mergePoints:points todayPoints:today_points completion:comp]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - [self mergePoints:points todayPoints:nil completion:comp]; + [self mergePoints:points todayPoints:today_points completion:comp]; NSLog(@"CSV request failure: %@", error); }]; @@ -166,11 +166,11 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre [points addObjectsFromArray:newPoints]; - [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // still try today stock price... - [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; NSLog(@"CSV request failure: %@", error); }]; @@ -188,7 +188,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre } else if (needUpdateTotday) { - [self getTodayStockPrice:ticker longPoints:points withProgress:progBlock completion:comp]; + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; } else { [self mergePoints:points todayPoints:today_points completion:comp]; From 1698f60c241c636945ac0504197df63eb9b9298a Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Fri, 15 Aug 2014 09:54:54 +0800 Subject: [PATCH 09/23] minor modification. --- Classes/JCStockPriceStore.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 00b212b..e0d638f 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -127,7 +127,10 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre //Found a cache; load it into our points array [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... NSDate *cacheDate = cacheDict[@"cacheDate"]; - if ([cacheDate mt_isWithinSameDay:endDate]==NO) + if ([cacheDate mt_isWithinSameDay:endDate]==NO + || [points count]<50 + || [points count]>5000 + ) { startDate = cacheDate; needUpdateTotday = YES; @@ -138,6 +141,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre cacheDate = cacheDict[@"cacheTodayDate"]; if ( [cacheDate mt_isWithinSameHour:endDate]==NO + || [cacheDate mt_isWithinSameDay:endDate]==NO || [today_points count]>1 ) @@ -150,6 +154,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre needUpdateTotday = YES; } + if (needUpdateLong) { //Build URL: @@ -163,6 +168,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre { NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [points removeAllObjects]; [points addObjectsFromArray:newPoints]; From a42e33309e5266103f83a4850ac4915bd9cca063 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Fri, 15 Aug 2014 12:53:03 +0800 Subject: [PATCH 10/23] Fix a abnormal long cache case. --- Classes/JCStockPriceStore.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index e0d638f..96e8b68 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -128,11 +128,10 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... NSDate *cacheDate = cacheDict[@"cacheDate"]; if ([cacheDate mt_isWithinSameDay:endDate]==NO - || [points count]<50 - || [points count]>5000 + || [points count]<50 // abnormal case.. ) { - startDate = cacheDate; +// startDate = cacheDate; needUpdateTotday = YES; needUpdateLong = YES; } else { @@ -159,6 +158,7 @@ - (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progre { //Build URL: NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; + // escape characters, ex. ^IXIC, ^INX NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; From a91d70ba698b5b55708b94ff4af220689cc8d6f2 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Sun, 17 Aug 2014 20:55:56 +0800 Subject: [PATCH 11/23] add paddingRight for the right label at x-Axis --- Classes/JCStockGraphView.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index 540b970..febdac8 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -84,6 +84,7 @@ - (void)configureXAxisWithPoints:(NSArray *)points delegate:(id { // 0 - increase padding to make room for axis labels self.hostView.hostedGraph.plotAreaFrame.paddingBottom = 24; + self.hostView.hostedGraph.plotAreaFrame.paddingRight = 12; // 1 - Get axis set CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostView.hostedGraph.axisSet; From 76a2565adfd34e31aa5f46a44438c2356583d8ac Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Mon, 18 Aug 2014 19:03:25 +0800 Subject: [PATCH 12/23] Add mutex lock (@synchronized) at getDataForTicker for preventing 5 graphs getData at the same time. --- Classes/JCStockGraphController.h | 3 +- Classes/JCStockGraphController.m | 9 +- Classes/JCStockGraphPageController.m | 2 +- Classes/JCStockGraphView.m | 5 +- Classes/JCStockPriceStore.h | 2 +- Classes/JCStockPriceStore.m | 169 +++++++++++++-------------- 6 files changed, 94 insertions(+), 96 deletions(-) diff --git a/Classes/JCStockGraphController.h b/Classes/JCStockGraphController.h index f196ae4..aa8f3fa 100755 --- a/Classes/JCStockGraphController.h +++ b/Classes/JCStockGraphController.h @@ -38,11 +38,12 @@ typedef NSInteger JCStockGraphOptionMask; @property (nonatomic) JCStockGraphRange range; @property (nonatomic) CGPoint graphOffset; @property (nonatomic) CGSize graphSize; +@property (nonatomic) id parentPage; @property (strong, nonatomic) NSString *ticker; @property (strong, nonatomic) JCStockGraphView *graphView; -- (id)initWithTicker:(NSString *)ticker; +- (id)initWithTicker:(NSString *)ticker parent:(id)qParent; - (void)loadDataWithCompletion:(void (^)())completion; - (void)reloadGraph; diff --git a/Classes/JCStockGraphController.m b/Classes/JCStockGraphController.m index 125ff5b..a5e6372 100755 --- a/Classes/JCStockGraphController.m +++ b/Classes/JCStockGraphController.m @@ -21,14 +21,14 @@ @interface JCStockGraphController () { NSArray *points; BOOL loaded; BOOL hasSetSize; - UITapGestureRecognizer *tapRecognizer; +// UITapGestureRecognizer *tapRecognizer; } @end @implementation JCStockGraphController -- (id)initWithTicker:(NSString *)ticker +- (id)initWithTicker:(NSString *)ticker parent:(id)qParent { self = [super init]; if (self) { @@ -37,6 +37,7 @@ - (id)initWithTicker:(NSString *)ticker self.range = kGraphRange5Year; self.graphOffset = CGPointZero; self.graphSize = CGSizeZero; + self.parentPage = qParent; } return self; } @@ -71,7 +72,7 @@ - (void)loadDataWithCompletion:(void (^)())completion dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [[JCStockPriceStore sharedInstance] getDataForTicker:self.ticker withProgress:^(double progress) { + [[JCStockPriceStore sharedInstance] getDataForTicker:self.ticker parentPage:self.parentPage withProgress:^(double progress) { hud.progress = progress; } completion:^(NSArray *newPoints) { @@ -105,7 +106,7 @@ -(void)loadGraph (self.graphOptions & kGraphOptionHideYAxis) ? [self.graphView hideYAxis] : [self.graphView configureYAxisWithPoints:points]; if (!(self.graphOptions & kGraphOptionHideGrid)) [self.graphView configureGridLines]; if (!(self.graphOptions & kGraphOptionHideRangeLabel)) [self.graphView addRangeLabel]; - self.graphView.userInteractionEnabled = (self.graphOptions & kGraphOptionInteractive); + self.graphView.userInteractionEnabled = (BOOL) (self.graphOptions & kGraphOptionInteractive); [self.view addSubview:self.graphView]; } diff --git a/Classes/JCStockGraphPageController.m b/Classes/JCStockGraphPageController.m index ad8b9eb..222c306 100755 --- a/Classes/JCStockGraphPageController.m +++ b/Classes/JCStockGraphPageController.m @@ -76,7 +76,7 @@ - (void)loadRemainingPages return; } - JCStockGraphController *graphController = [[JCStockGraphController alloc] initWithTicker:self.ticker]; + JCStockGraphController *graphController = [[JCStockGraphController alloc] initWithTicker:self.ticker parent:self]; //graphController.view.frame = self.view.bounds; graphController.graphOffset = self.graphOffset; graphController.graphSize = self.graphSize; diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index febdac8..78554cb 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -83,8 +83,9 @@ -(void)configurePlotWithDataSource:(id)dataSource - (void)configureXAxisWithPoints:(NSArray *)points delegate:(id)delegate { // 0 - increase padding to make room for axis labels - self.hostView.hostedGraph.plotAreaFrame.paddingBottom = 24; - self.hostView.hostedGraph.plotAreaFrame.paddingRight = 12; + self.hostView.hostedGraph.plotAreaFrame.paddingBottom = 20; + self.hostView.hostedGraph.plotAreaFrame.paddingRight = 20; + self.hostView.hostedGraph.plotAreaFrame.paddingTop = 6; // 1 - Get axis set CPTXYAxisSet *axisSet = (CPTXYAxisSet *) self.hostView.hostedGraph.axisSet; diff --git a/Classes/JCStockPriceStore.h b/Classes/JCStockPriceStore.h index c5259bc..4786c26 100755 --- a/Classes/JCStockPriceStore.h +++ b/Classes/JCStockPriceStore.h @@ -13,7 +13,7 @@ + (JCStockPriceStore *)sharedInstance; ///@return YES if we loaded data from the cache/memory, NO if we made a request for the data -- (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))block; +- (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))block; @property (nonatomic) BOOL diskCachingEnabled; @property (nonatomic) BOOL memoryCachingEnabled; diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 96e8b68..39c2014 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -106,100 +106,95 @@ - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points today [operation2 start]; } -- (BOOL)getDataForTicker:(NSString *)ticker withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp +- (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { - NSAssert(ticker, @"tried to get historical data for null ticker"); - if (!ticker && comp) comp(nil); - - __block NSMutableArray *points = [[NSMutableArray alloc] init]; - __block NSMutableArray *today_points = [[NSMutableArray alloc] init]; - - //Set time period: - NSDate *endDate = [NSDate date]; - NSDate *startDate = [endDate mt_dateYearsBefore:5]; - - //Check for previously cached data: - BOOL needUpdateLong = NO; - BOOL needUpdateTotday = NO; - NSDictionary *cacheDict = [self loadCacheForTicker:ticker]; - if (cacheDict) + @synchronized (qParent) { - //Found a cache; load it into our points array - [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... - NSDate *cacheDate = cacheDict[@"cacheDate"]; - if ([cacheDate mt_isWithinSameDay:endDate]==NO - || [points count]<50 // abnormal case.. - ) - { + NSAssert(ticker, @"tried to get historical data for null ticker"); + if (!ticker && comp) comp(nil); + + __block NSMutableArray *points = [[NSMutableArray alloc] init]; + __block NSMutableArray *today_points = [[NSMutableArray alloc] init]; + + //Set time period: + NSDate *endDate = [NSDate date]; + NSDate *startDate = [endDate mt_dateYearsBefore:5]; + + //Check for previously cached data: + BOOL needUpdateLong = NO; + BOOL needUpdateTotday = NO; + NSDictionary *cacheDict = [self loadCacheForTicker:ticker]; + if (cacheDict) { + //Found a cache; load it into our points array + [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... + NSDate *cacheDate = cacheDict[@"cacheDate"]; + if (![cacheDate mt_isWithinSameDay:endDate] + || [points count] < 50 // abnormal case.. + ) { // startDate = cacheDate; - needUpdateTotday = YES; - needUpdateLong = YES; - } else { - // check short term data.. - [today_points addObjectsFromArray:cacheDict[@"today_data"]]; - cacheDate = cacheDict[@"cacheTodayDate"]; - if ( - [cacheDate mt_isWithinSameHour:endDate]==NO - || [cacheDate mt_isWithinSameDay:endDate]==NO - || [today_points count]>1 - ) - - { needUpdateTotday = YES; + needUpdateLong = YES; + } else { + // check short term data.. + [today_points addObjectsFromArray:cacheDict[@"today_data"]]; + cacheDate = cacheDict[@"cacheTodayDate"]; + if ( + ![cacheDate mt_isWithinSameHour:endDate] + || ![cacheDate mt_isWithinSameDay:endDate] + || [today_points count] > 1 + ) { + needUpdateTotday = YES; + } } + } else { + needUpdateLong = YES; + needUpdateTotday = YES; } - } else { - needUpdateLong = YES; - needUpdateTotday = YES; - } - - - if (needUpdateLong) - { - //Build URL: - NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; - - // escape characters, ex. ^IXIC, ^INX - NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - - //Create Request: - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) - { - NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [points removeAllObjects]; - [points addObjectsFromArray:newPoints]; - - - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - // still try today stock price... - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - NSLog(@"CSV request failure: %@", error); - }]; - - // Dowload Progress - [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { - long long expected = totalBytesExpectedToRead; - if (expected == -1) - expected = 75000; //A bit more than average - double prog = MIN((double)totalBytesRead/(double)expected, 1.0); - if (progBlock) progBlock(prog); - }]; - - [operation start]; - } - else if (needUpdateTotday) - { - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - } else { - [self mergePoints:points todayPoints:today_points completion:comp]; + if (needUpdateLong) { + //Build URL: + NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; + + // escape characters, ex. ^IXIC, ^INX + NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + + //Create Request: + AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + NSArray *newPoints = [self dataPointsForCSVString:csvString]; + [points removeAllObjects]; + [points addObjectsFromArray:newPoints]; + + + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + // still try today stock price... + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + NSLog(@"CSV request failure: %@", error); + }]; + + // Dowload Progress + [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double) totalBytesRead / (double) expected, 1.0); + if (progBlock) progBlock(prog); + }]; + + [operation start]; + + } + else if (needUpdateTotday) { + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + + } else { + [self mergePoints:points todayPoints:today_points completion:comp]; + } } - return NO; } @@ -279,7 +274,7 @@ - (BOOL)cachePoints:(NSArray *)points todayPoints:(NSArray *)today_points forTic return NO; } -- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker +/*- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker { NSDictionary *cacheDict = @{@"cacheTodayDate": [NSDate date], @"today_data": points}; inMemCache[ticker] = cacheDict; @@ -289,7 +284,7 @@ - (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker return [NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; } return NO; -} +} */ - (void)setMemoryCachingEnabled:(BOOL)inMemoryCachingEnabled { From 10d5b8a8946ff33b34d322fca651452b1f7320f6 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 20 Aug 2014 10:54:30 +0800 Subject: [PATCH 13/23] Add example that draw the same graph with axis and grid. --- Example/JCStockGraphExample/JCViewController.m | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Example/JCStockGraphExample/JCViewController.m b/Example/JCStockGraphExample/JCViewController.m index 2db2bf1..a37c99b 100644 --- a/Example/JCStockGraphExample/JCViewController.m +++ b/Example/JCStockGraphExample/JCViewController.m @@ -32,6 +32,17 @@ - (void)viewDidLoad self.graphPageController.shouldShowRotateHint = NO; [self.view addSubview:self.graphPageController.view]; + + // draw the same graph with axis and grid. + self.graphPageController = [[JCStockGraphPageController alloc] initWithTicker:@"AAPL"]; + self.graphPageController.view.frame = CGRectMake(0, 250, 320, 100); + self.graphPageController.graphOffset = CGPointMake(8, 0); + self.graphPageController.graphSize = CGSizeMake(290, 90); + self.graphPageController.graphOptions = kGraphOptionSmoothGraph /*| kGraphOptionHideXAxis | kGraphOptionHideGrid*/; + self.graphPageController.shouldAutoscroll = YES; + self.graphPageController.shouldShowRotateHint = NO; + + [self.view addSubview:self.graphPageController.view]; } @end From 548f9ad2e9b20eda63a17ac5bcc9faab06f350bd Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 3 Sep 2014 10:17:24 +0800 Subject: [PATCH 14/23] Backup. --- Classes/JCStockPriceStore.m | 464 ++++++++++++++++++------------------ 1 file changed, 236 insertions(+), 228 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 39c2014..a7260e9 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -11,17 +11,23 @@ // Copyright (c) 2012 komorka technology, llc. All rights reserved. // -#import "JCStockPriceStore.h" +#import + "JCStockPriceStore.h" -#import "AFNetworking.h" -#import "NSDate+MTDates.h" +#import + "AFNetworking.h" +#import + "NSDate+MTDates.h" -#import "JCStockGraphController.h" -#import "JCPriceDataPoint.h" -#import "NSDate+YQL.h" +#import + "JCStockGraphController.h" +#import + "JCPriceDataPoint.h" +#import + "NSDate+YQL.h" @interface JCStockPriceStore () { - NSMutableDictionary *inMemCache; +NSMutableDictionary *inMemCache; } @end @@ -31,247 +37,249 @@ @implementation JCStockPriceStore static JCStockPriceStore *sharedInstance; + (JCStockPriceStore *)sharedInstance { - if (!sharedInstance) { - sharedInstance = [[JCStockPriceStore alloc] init]; - } - return sharedInstance; +if (!sharedInstance) { +sharedInstance =[[JCStockPriceStore alloc] init]; +} +return sharedInstance; } - (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points completion:(void (^)(NSArray *points))comp { - if (!comp) return; - if (!points) return; - - NSMutableArray *newArray = [[NSMutableArray alloc] init]; - [newArray addObjectsFromArray:points]; - JCPriceDataPoint *point = [newArray lastObject]; - if (today_points && [today_points count]>0) - { - JCPriceDataPoint *tPoint = [today_points objectAtIndex:0]; - if ([point.date isEqual:tPoint.date]==NO) - [newArray addObjectsFromArray:today_points]; - } - comp(newArray); - +if (!comp) return; +if (!points) return; + +NSMutableArray *newArray =[[NSMutableArray alloc] init]; +[newArray addObjectsFromArray:points]; +JCPriceDataPoint *point =[newArray lastObject]; +if (today_points &&[today_points count]>0) +{ +JCPriceDataPoint *tPoint =[today_points objectAtIndex:0]; +if ([point.date isEqual:tPoint.date]==NO) +[newArray addObjectsFromArray:today_points]; +} +comp(newArray); + } - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points todayPoints:(NSArray *)today_points withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { - // Request current price.. - // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 - NSString *urlString = [NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; - - // escape for ^IXIC, ^INX - NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - AFHTTPRequestOperation *operation2 = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) - { - NSMutableArray *today_points = [[NSMutableArray alloc] init]; - - NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - - // reformat the date string - NSMutableString *csvString_tmp = [csvString mutableCopy]; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; - [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"$3-$1-$2"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; - [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1-"]; - regex = [NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; - [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0, [csvString_tmp length]) withTemplate:@"-0$1"]; - csvString = [NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; - - - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [today_points addObjectsFromArray:newPoints]; - - - [self cachePoints:points todayPoints:today_points forTicker:ticker]; - [self mergePoints:points todayPoints:today_points completion:comp]; - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - [self mergePoints:points todayPoints:today_points completion:comp]; - NSLog(@"CSV request failure: %@", error); - }]; - - // Dowload Progress - [operation2 setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { - long long expected = totalBytesExpectedToRead; - if (expected == -1) - expected = 75000; //A bit more than average - double prog = MIN((double)totalBytesRead/(double)expected, 1.0); - if (progBlock) progBlock(prog); - }]; - - [operation2 start]; +// Request current price.. +// http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 +NSString *urlString =[NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; + +// escape for ^IXIC, ^INX +NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; +AFHTTPRequestOperation *operation2 =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; +[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) +{ +NSMutableArray *today_points =[[NSMutableArray alloc] init]; + +NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + +// reformat the date string +NSMutableString *csvString_tmp =[csvString mutableCopy]; +NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; +[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"$3-$1-$2"]; +regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; +[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1-"]; +regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; +[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1"]; +csvString =[NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; + + +NSArray *newPoints =[self dataPointsForCSVString:csvString]; +[today_points addObjectsFromArray:newPoints]; + + +[self cachePoints:points todayPoints:today_points forTicker:ticker]; +[self mergePoints:points todayPoints:today_points completion:comp]; + +} failure:^(AFHTTPRequestOperation *operation, NSError *error) { +[self mergePoints:points todayPoints:today_points completion:comp]; +NSLog(@"CSV request failure: %@", error); +}]; + +// Dowload Progress +[operation2 setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { +long long expected = totalBytesExpectedToRead; +if (expected == -1) +expected = 75000; //A bit more than average +double prog = MIN((double)totalBytesRead/(double)expected, 1.0); +if (progBlock) progBlock(prog); +}]; + +[operation2 start]; } - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { - @synchronized (qParent) - { - NSAssert(ticker, @"tried to get historical data for null ticker"); - if (!ticker && comp) comp(nil); - - __block NSMutableArray *points = [[NSMutableArray alloc] init]; - __block NSMutableArray *today_points = [[NSMutableArray alloc] init]; - - //Set time period: - NSDate *endDate = [NSDate date]; - NSDate *startDate = [endDate mt_dateYearsBefore:5]; - - //Check for previously cached data: - BOOL needUpdateLong = NO; - BOOL needUpdateTotday = NO; - NSDictionary *cacheDict = [self loadCacheForTicker:ticker]; - if (cacheDict) { - //Found a cache; load it into our points array - [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... - NSDate *cacheDate = cacheDict[@"cacheDate"]; - if (![cacheDate mt_isWithinSameDay:endDate] - || [points count] < 50 // abnormal case.. - ) { -// startDate = cacheDate; - needUpdateTotday = YES; - needUpdateLong = YES; - } else { - // check short term data.. - [today_points addObjectsFromArray:cacheDict[@"today_data"]]; - cacheDate = cacheDict[@"cacheTodayDate"]; - if ( - ![cacheDate mt_isWithinSameHour:endDate] - || ![cacheDate mt_isWithinSameDay:endDate] - || [today_points count] > 1 - ) { - needUpdateTotday = YES; - } - } - } else { - needUpdateLong = YES; - needUpdateTotday = YES; - } - - - if (needUpdateLong) { - //Build URL: - NSString *urlString = [NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker, [startDate yqlStartString], [endDate yqlEndString]]; - - // escape characters, ex. ^IXIC, ^INX - NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - - //Create Request: - AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { - NSString *csvString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - NSArray *newPoints = [self dataPointsForCSVString:csvString]; - [points removeAllObjects]; - [points addObjectsFromArray:newPoints]; - - - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - // still try today stock price... - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - NSLog(@"CSV request failure: %@", error); - }]; - - // Dowload Progress - [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { - long long expected = totalBytesExpectedToRead; - if (expected == -1) - expected = 75000; //A bit more than average - double prog = MIN((double) totalBytesRead / (double) expected, 1.0); - if (progBlock) progBlock(prog); - }]; - - [operation start]; - - } - else if (needUpdateTotday) { - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - - } else { - [self mergePoints:points todayPoints:today_points completion:comp]; - } - } - return NO; +@synchronized (qParent) +{ +NSAssert(ticker, @"tried to get historical data for null ticker"); +if (!ticker && comp) comp(nil); + +__block NSMutableArray *points =[[NSMutableArray alloc] init]; +__block NSMutableArray *today_points =[[NSMutableArray alloc] init]; + +//Set time period: +NSDate *endDate =[NSDate date]; +NSDate *startDate =[endDate mt_dateYearsBefore:5]; + +//Check for previously cached data: +BOOL needUpdateLong = NO; +BOOL needUpdateTotday = NO; +NSDictionary *cacheDict =[self loadCacheForTicker:ticker]; +if (cacheDict) { +//Found a cache; load it into our points array +[points addObjectsFromArray:cacheDict[@"data"]]; // long term data... +NSDate *cacheDate = cacheDict[@"cacheDate"]; +if (![cacheDate mt_isWithinSameDay:endDate] +||[points count] < 50 // abnormal case.. +) { +needUpdateTotday = YES; +needUpdateLong = YES; +} else { +// check short term data.. +[today_points addObjectsFromArray:cacheDict[@"today_data"]]; +cacheDate = cacheDict[@"cacheTodayDate"]; +if ( +![cacheDate mt_isWithinSameHour:endDate] +|| ![cacheDate mt_isWithinSameDay:endDate] +||[today_points count] > 1 +) { +needUpdateTotday = YES; +} +} +} else { +needUpdateLong = YES; +needUpdateTotday = YES; +} + + +if (needUpdateLong) { +//Build URL: +NSString *urlString =[NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker,[startDate yqlStartString],[endDate yqlEndString]]; + +// escape characters, ex. ^IXIC, ^INX +NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + +//Create Request: +AFHTTPRequestOperation *operation =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; +[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { +NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; +NSArray *newPoints =[self dataPointsForCSVString:csvString]; +[points removeAllObjects]; +[points addObjectsFromArray:newPoints]; + + +[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + +} failure:^(AFHTTPRequestOperation *operation, NSError *error) { +// still try today stock price... +[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; +NSLog(@"CSV request failure: %@", error); +}]; + +// Dowload Progress +[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { +long long expected = totalBytesExpectedToRead; +if (expected == -1) +expected = 75000; //A bit more than average +double prog = MIN((double) totalBytesRead / (double) expected, 1.0); +if (progBlock) progBlock(prog); +}]; + +[operation start]; + +} +else if (needUpdateTotday) { +[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + +} else { +[self mergePoints:points todayPoints:today_points completion:comp]; +} +} +return NO; } - (NSArray *)dataPointsForCSVString:(NSString *)csvString { - NSArray *lines = [csvString componentsSeparatedByString:@"\n"]; - NSArray *columnNames = [lines[0] componentsSeparatedByString:@","]; - NSArray *data = [lines subarrayWithRange:NSMakeRange(1, [lines count]-2)]; - NSUInteger dateIndex = 0; - NSUInteger closeIndex = 4; - - for (int i = 0; i < columnNames.count; ++i) { - if ([columnNames[i] isEqualToString:@"Close"]) - closeIndex = i; - else if ([columnNames[i] isEqualToString:@"Date"]) - dateIndex = i; - } - - NSMutableArray *points = [[NSMutableArray alloc] initWithCapacity:data.count]; - NSNumberFormatter *nf = [[NSNumberFormatter alloc] init]; - - data = [data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; - - NSDate *lastDate=nil; - for (NSString *rowString in data) { - - NSArray *row = [rowString componentsSeparatedByString:@","]; - - JCPriceDataPoint *point = [[JCPriceDataPoint alloc] init]; - point.date = [NSDate mt_dateFromString:row[dateIndex] usingFormat:kDateFormatYahooAPI]; - if ([point.date isEqual:lastDate]) continue; - - NSString *closeString = row[closeIndex]; - point.closePrice = [[nf numberFromString:closeString] doubleValue]; - [points addObject:point]; - - lastDate = point.date; - } - return points; +NSArray *lines =[csvString componentsSeparatedByString:@"\n"]; +NSArray *columnNames =[lines[0] componentsSeparatedByString:@","]; +NSArray *data =[lines subarrayWithRange:NSMakeRange(1,[lines count]-2)]; +NSUInteger dateIndex = 0; +NSUInteger closeIndex = 4; + +for (int i = 0; i < columnNames.count; ++i) { +if ([columnNames[i] isEqualToString:@"Close"]) +closeIndex = i; +else if ([columnNames[i] isEqualToString:@"Date"]) +dateIndex = i; } -#pragma mark - Caching +NSMutableArray *points =[[NSMutableArray alloc] initWithCapacity:data.count]; +NSNumberFormatter *nf =[[NSNumberFormatter alloc] init]; + +data =[data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + +NSDate *lastDate=nil; +for (NSString *rowString in data) { + +NSArray *row =[rowString componentsSeparatedByString:@","]; + +JCPriceDataPoint *point =[[JCPriceDataPoint alloc] init]; +point.date =[NSDate mt_dateFromString:row[dateIndex] usingFormat:kDateFormatYahooAPI]; +if ([point.date isEqual:lastDate]) continue; + +NSString *closeString = row[closeIndex]; +point.closePrice =[[nf numberFromString:closeString] doubleValue]; +[points addObject:point]; + +lastDate = point.date; +} +return points; +} + +#pragma + mark - Caching - (NSString *)cachePathForTicker:(NSString *)ticker { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - NSString *cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"GraphData"]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:cacheDirectory]) - [[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil]; - return [cacheDirectory stringByAppendingPathComponent:ticker]; +NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); +NSString *cacheDirectory =[[paths objectAtIndex:0] stringByAppendingPathComponent:@"GraphData"]; + +if (![[NSFileManager defaultManager] fileExistsAtPath:cacheDirectory]) +[[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil]; +return[cacheDirectory stringByAppendingPathComponent:ticker]; } - (NSDictionary *)loadCacheForTicker:(NSString *)ticker { - NSDictionary *ret = inMemCache[ticker]; - if (!ret && self.diskCachingEnabled) { - NSString *cachePath = [self cachePathForTicker:ticker]; - @try { - ret = [NSKeyedUnarchiver unarchiveObjectWithFile:cachePath]; - } @catch (...) { - ret = nil; - } - } - return ret; +NSDictionary *ret = inMemCache[ticker]; +if (!ret && self.diskCachingEnabled) { +NSString *cachePath =[self cachePathForTicker:ticker]; +@try { +ret =[NSKeyedUnarchiver unarchiveObjectWithFile:cachePath]; +} @catch (...) { +ret = nil; +} +} +return ret; } - (BOOL)cachePoints:(NSArray *)points todayPoints:(NSArray *)today_points forTicker:(NSString *)ticker { - NSDictionary *cacheDict = @{@"cacheDate": [NSDate date], @"data": points, @"cacheTodayDate": [NSDate date], @"today_data": today_points}; - inMemCache[ticker] = cacheDict; - - if (self.diskCachingEnabled) { - NSString *cachePath = [self cachePathForTicker:ticker]; - return [NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; - } - return NO; +NSDictionary *cacheDict = @{ +@"cacheDate":[NSDate date], @"data": points, @"cacheTodayDate":[NSDate date], @"today_data": today_points +}; +inMemCache[ticker] = cacheDict; + +if (self.diskCachingEnabled) { +NSString *cachePath =[self cachePathForTicker:ticker]; +return[NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; +} +return NO; } /*- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker @@ -288,20 +296,20 @@ - (BOOL)cachePoints:(NSArray *)points todayPoints:(NSArray *)today_points forTic - (void)setMemoryCachingEnabled:(BOOL)inMemoryCachingEnabled { - inMemCache = nil; - if (inMemoryCachingEnabled) - inMemCache = [[NSMutableDictionary alloc] init]; +inMemCache = nil; +if (inMemoryCachingEnabled) +inMemCache =[[NSMutableDictionary alloc] init]; } - (id)init { - self = [super init]; - if (self) { - self.memoryCachingEnabled = YES; - self.diskCachingEnabled = YES; - inMemCache = [[NSMutableDictionary alloc] init]; - } - return self; +self =[super init]; +if (self) { +self.memoryCachingEnabled = YES; +self.diskCachingEnabled = YES; +inMemCache =[[NSMutableDictionary alloc] init]; +} +return self; } @end From 5b11b307a445186ec29f8adb750a383159da082a Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 3 Sep 2014 12:06:21 +0800 Subject: [PATCH 15/23] Backup. --- Classes/JCStockPriceStore.m | 482 ++++++++++++++++++------------------ 1 file changed, 237 insertions(+), 245 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index a7260e9..8e55f75 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -11,23 +11,17 @@ // Copyright (c) 2012 komorka technology, llc. All rights reserved. // -#import - "JCStockPriceStore.h" +#import "JCStockPriceStore.h" -#import - "AFNetworking.h" -#import - "NSDate+MTDates.h" +#import "AFNetworking.h" +#import "NSDate+MTDates.h" -#import - "JCStockGraphController.h" -#import - "JCPriceDataPoint.h" -#import - "NSDate+YQL.h" +#import "JCStockGraphController.h" +#import "JCPriceDataPoint.h" +#import "NSDate+YQL.h" @interface JCStockPriceStore () { -NSMutableDictionary *inMemCache; + NSMutableDictionary *inMemCache; } @end @@ -37,279 +31,277 @@ @implementation JCStockPriceStore static JCStockPriceStore *sharedInstance; + (JCStockPriceStore *)sharedInstance { -if (!sharedInstance) { -sharedInstance =[[JCStockPriceStore alloc] init]; -} -return sharedInstance; + if (!sharedInstance) { + sharedInstance =[[JCStockPriceStore alloc] init]; + } + return sharedInstance; } - (void)mergePoints:(NSArray *)points todayPoints:(NSArray *)today_points completion:(void (^)(NSArray *points))comp { -if (!comp) return; -if (!points) return; - -NSMutableArray *newArray =[[NSMutableArray alloc] init]; -[newArray addObjectsFromArray:points]; -JCPriceDataPoint *point =[newArray lastObject]; -if (today_points &&[today_points count]>0) -{ -JCPriceDataPoint *tPoint =[today_points objectAtIndex:0]; -if ([point.date isEqual:tPoint.date]==NO) -[newArray addObjectsFromArray:today_points]; -} -comp(newArray); - + if (!comp) return; + if (!points) return; + + NSMutableArray *newArray =[[NSMutableArray alloc] init]; + [newArray addObjectsFromArray:points]; + JCPriceDataPoint *point =[newArray lastObject]; + if (today_points &&[today_points count]>0) + { + JCPriceDataPoint *tPoint =[today_points objectAtIndex:0]; + if ([point.date isEqual:tPoint.date]==NO) + [newArray addObjectsFromArray:today_points]; + } + comp(newArray); + } - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points todayPoints:(NSArray *)today_points withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { -// Request current price.. -// http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 -NSString *urlString =[NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; - -// escape for ^IXIC, ^INX -NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; -AFHTTPRequestOperation *operation2 =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; -[operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) -{ -NSMutableArray *today_points =[[NSMutableArray alloc] init]; - -NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - -// reformat the date string -NSMutableString *csvString_tmp =[csvString mutableCopy]; -NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; -[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"$3-$1-$2"]; -regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; -[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1-"]; -regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; -[regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1"]; -csvString =[NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; - - -NSArray *newPoints =[self dataPointsForCSVString:csvString]; -[today_points addObjectsFromArray:newPoints]; - - -[self cachePoints:points todayPoints:today_points forTicker:ticker]; -[self mergePoints:points todayPoints:today_points completion:comp]; - -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { -[self mergePoints:points todayPoints:today_points completion:comp]; -NSLog(@"CSV request failure: %@", error); -}]; - -// Dowload Progress -[operation2 setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { -long long expected = totalBytesExpectedToRead; -if (expected == -1) -expected = 75000; //A bit more than average -double prog = MIN((double)totalBytesRead/(double)expected, 1.0); -if (progBlock) progBlock(prog); -}]; - -[operation2 start]; + // Request current price.. + // http://download.finance.yahoo.com/d/quotes.csv?s=AAPL&f=d1o0h0g0l1v0l1 + NSString *urlString =[NSString stringWithFormat:@"http://download.finance.yahoo.com/d/quotes.csv?s=%@&f=d1o0h0g0l1v0l1", ticker]; + + // escape for ^IXIC, ^INX + NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + AFHTTPRequestOperation *operation2 =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation2 setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { + NSMutableArray *today_points =[[NSMutableArray alloc] init]; + + NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + + // reformat the date string + NSMutableString *csvString_tmp =[csvString mutableCopy]; + NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"$3-$1-$2"]; + regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1-"]; + regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})$" options:0 error:nil]; + [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"-0$1"]; + csvString =[NSString stringWithFormat:@"FIRST_LINE_FOR_SKIPED\n%@", csvString_tmp]; + + + NSArray *newPoints =[self dataPointsForCSVString:csvString]; + [today_points addObjectsFromArray:newPoints]; + + + [self cachePoints:points todayPoints:today_points forTicker:ticker]; + [self mergePoints:points todayPoints:today_points completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + [self mergePoints:points todayPoints:today_points completion:comp]; + NSLog(@"CSV request failure: %@", error); + }]; + + // Dowload Progress + [operation2 setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double)totalBytesRead/(double)expected, 1.0); + if (progBlock) progBlock(prog); + }]; + + [operation2 start]; } - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress:(void (^)(double progress))progBlock completion:(void (^)(NSArray *points))comp { -@synchronized (qParent) -{ -NSAssert(ticker, @"tried to get historical data for null ticker"); -if (!ticker && comp) comp(nil); - -__block NSMutableArray *points =[[NSMutableArray alloc] init]; -__block NSMutableArray *today_points =[[NSMutableArray alloc] init]; - -//Set time period: -NSDate *endDate =[NSDate date]; -NSDate *startDate =[endDate mt_dateYearsBefore:5]; - -//Check for previously cached data: -BOOL needUpdateLong = NO; -BOOL needUpdateTotday = NO; -NSDictionary *cacheDict =[self loadCacheForTicker:ticker]; -if (cacheDict) { -//Found a cache; load it into our points array -[points addObjectsFromArray:cacheDict[@"data"]]; // long term data... -NSDate *cacheDate = cacheDict[@"cacheDate"]; -if (![cacheDate mt_isWithinSameDay:endDate] -||[points count] < 50 // abnormal case.. -) { -needUpdateTotday = YES; -needUpdateLong = YES; -} else { -// check short term data.. -[today_points addObjectsFromArray:cacheDict[@"today_data"]]; -cacheDate = cacheDict[@"cacheTodayDate"]; -if ( -![cacheDate mt_isWithinSameHour:endDate] -|| ![cacheDate mt_isWithinSameDay:endDate] -||[today_points count] > 1 -) { -needUpdateTotday = YES; -} -} -} else { -needUpdateLong = YES; -needUpdateTotday = YES; -} - - -if (needUpdateLong) { -//Build URL: -NSString *urlString =[NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker,[startDate yqlStartString],[endDate yqlEndString]]; - -// escape characters, ex. ^IXIC, ^INX -NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; - -//Create Request: -AFHTTPRequestOperation *operation =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; -[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { -NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; -NSArray *newPoints =[self dataPointsForCSVString:csvString]; -[points removeAllObjects]; -[points addObjectsFromArray:newPoints]; - - -[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { -// still try today stock price... -[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; -NSLog(@"CSV request failure: %@", error); -}]; - -// Dowload Progress -[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { -long long expected = totalBytesExpectedToRead; -if (expected == -1) -expected = 75000; //A bit more than average -double prog = MIN((double) totalBytesRead / (double) expected, 1.0); -if (progBlock) progBlock(prog); -}]; - -[operation start]; - -} -else if (needUpdateTotday) { -[self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - -} else { -[self mergePoints:points todayPoints:today_points completion:comp]; -} -} -return NO; + @synchronized (qParent) + { + NSAssert(ticker, @"tried to get historical data for null ticker"); + if (!ticker && comp) comp(nil); + + __block NSMutableArray *points =[[NSMutableArray alloc] init]; + __block NSMutableArray *today_points =[[NSMutableArray alloc] init]; + + //Set time period: + NSDate *endDate =[NSDate date]; + NSDate *startDate =[endDate mt_dateYearsBefore:5]; + + //Check for previously cached data: + BOOL needUpdateLong = NO; + BOOL needUpdateTotday = NO; + NSDictionary *cacheDict =[self loadCacheForTicker:ticker]; + if (cacheDict) { + //Found a cache; load it into our points array + [points addObjectsFromArray:cacheDict[@"data"]]; // long term data... + NSDate *cacheDate = cacheDict[@"cacheDate"]; + if (![cacheDate mt_isWithinSameDay:endDate] + ||[points count] < 50 // abnormal case.. + ) { + needUpdateTotday = YES; + needUpdateLong = YES; + } else { + // check short term data.. + [today_points addObjectsFromArray:cacheDict[@"today_data"]]; + cacheDate = cacheDict[@"cacheTodayDate"]; + if ( + ![cacheDate mt_isWithinSameHour:endDate] + || ![cacheDate mt_isWithinSameDay:endDate] + ||[today_points count] > 1 + ) { + needUpdateTotday = YES; + } + } + } else { + needUpdateLong = YES; + needUpdateTotday = YES; + } + + + if (needUpdateLong) { + //Build URL: + NSString *urlString =[NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker,[startDate yqlStartString],[endDate yqlEndString]]; + + // escape characters, ex. ^IXIC, ^INX + NSURL *url =[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + + //Create Request: + AFHTTPRequestOperation *operation =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; + NSArray *newPoints =[self dataPointsForCSVString:csvString]; + [points removeAllObjects]; + [points addObjectsFromArray:newPoints]; + + + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + // still try today stock price... + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + NSLog(@"CSV request failure: %@", error); + }]; + + // Dowload Progress + [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + long long expected = totalBytesExpectedToRead; + if (expected == -1) + expected = 75000; //A bit more than average + double prog = MIN((double) totalBytesRead / (double) expected, 1.0); + if (progBlock) progBlock(prog); + }]; + + [operation start]; + + } + else if (needUpdateTotday) { + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + + } else { + [self mergePoints:points todayPoints:today_points completion:comp]; + } + } + return NO; } - (NSArray *)dataPointsForCSVString:(NSString *)csvString { -NSArray *lines =[csvString componentsSeparatedByString:@"\n"]; -NSArray *columnNames =[lines[0] componentsSeparatedByString:@","]; -NSArray *data =[lines subarrayWithRange:NSMakeRange(1,[lines count]-2)]; -NSUInteger dateIndex = 0; -NSUInteger closeIndex = 4; - -for (int i = 0; i < columnNames.count; ++i) { -if ([columnNames[i] isEqualToString:@"Close"]) -closeIndex = i; -else if ([columnNames[i] isEqualToString:@"Date"]) -dateIndex = i; -} - -NSMutableArray *points =[[NSMutableArray alloc] initWithCapacity:data.count]; -NSNumberFormatter *nf =[[NSNumberFormatter alloc] init]; - -data =[data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; - -NSDate *lastDate=nil; -for (NSString *rowString in data) { - -NSArray *row =[rowString componentsSeparatedByString:@","]; - -JCPriceDataPoint *point =[[JCPriceDataPoint alloc] init]; -point.date =[NSDate mt_dateFromString:row[dateIndex] usingFormat:kDateFormatYahooAPI]; -if ([point.date isEqual:lastDate]) continue; - -NSString *closeString = row[closeIndex]; -point.closePrice =[[nf numberFromString:closeString] doubleValue]; -[points addObject:point]; - -lastDate = point.date; -} -return points; + NSArray *lines =[csvString componentsSeparatedByString:@"\n"]; + NSArray *columnNames =[lines[0] componentsSeparatedByString:@","]; + NSArray *data =[lines subarrayWithRange:NSMakeRange(1,[lines count]-2)]; + NSUInteger dateIndex = 0; + NSUInteger closeIndex = 4; + + for (int i = 0; i < columnNames.count; ++i) { + if ([columnNames[i] isEqualToString:@"Close"]) + closeIndex = i; + else if ([columnNames[i] isEqualToString:@"Date"]) + dateIndex = i; + } + + NSMutableArray *points =[[NSMutableArray alloc] initWithCapacity:data.count]; + NSNumberFormatter *nf =[[NSNumberFormatter alloc] init]; + + data =[data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + + NSDate *lastDate=nil; + for (NSString *rowString in data) { + + NSArray *row =[rowString componentsSeparatedByString:@","]; + + JCPriceDataPoint *point =[[JCPriceDataPoint alloc] init]; + point.date =[NSDate mt_dateFromString:row[dateIndex] usingFormat:kDateFormatYahooAPI]; + if ([point.date isEqual:lastDate]) continue; + + NSString *closeString = row[closeIndex]; + point.closePrice =[[nf numberFromString:closeString] doubleValue]; + [points addObject:point]; + + lastDate = point.date; + } + return points; } -#pragma - mark - Caching - +#pragma mark - Caching - (NSString *)cachePathForTicker:(NSString *)ticker { -NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); -NSString *cacheDirectory =[[paths objectAtIndex:0] stringByAppendingPathComponent:@"GraphData"]; - -if (![[NSFileManager defaultManager] fileExistsAtPath:cacheDirectory]) -[[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil]; -return[cacheDirectory stringByAppendingPathComponent:ticker]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *cacheDirectory =[[paths objectAtIndex:0] stringByAppendingPathComponent:@"GraphData"]; + + if (![[NSFileManager defaultManager] fileExistsAtPath:cacheDirectory]) + [[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil]; + return[cacheDirectory stringByAppendingPathComponent:ticker]; } - (NSDictionary *)loadCacheForTicker:(NSString *)ticker { -NSDictionary *ret = inMemCache[ticker]; -if (!ret && self.diskCachingEnabled) { -NSString *cachePath =[self cachePathForTicker:ticker]; -@try { -ret =[NSKeyedUnarchiver unarchiveObjectWithFile:cachePath]; -} @catch (...) { -ret = nil; -} -} -return ret; + NSDictionary *ret = inMemCache[ticker]; + if (!ret && self.diskCachingEnabled) { + NSString *cachePath =[self cachePathForTicker:ticker]; + @try { + ret =[NSKeyedUnarchiver unarchiveObjectWithFile:cachePath]; + } @catch (...) { + ret = nil; + } + } + return ret; } - (BOOL)cachePoints:(NSArray *)points todayPoints:(NSArray *)today_points forTicker:(NSString *)ticker { -NSDictionary *cacheDict = @{ -@"cacheDate":[NSDate date], @"data": points, @"cacheTodayDate":[NSDate date], @"today_data": today_points -}; -inMemCache[ticker] = cacheDict; - -if (self.diskCachingEnabled) { -NSString *cachePath =[self cachePathForTicker:ticker]; -return[NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; -} -return NO; -} - -/*- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker -{ - NSDictionary *cacheDict = @{@"cacheTodayDate": [NSDate date], @"today_data": points}; + NSDictionary *cacheDict = @{ + @"cacheDate":[NSDate date], @"data": points, @"cacheTodayDate":[NSDate date], @"today_data": today_points + }; inMemCache[ticker] = cacheDict; if (self.diskCachingEnabled) { - NSString *cachePath = [self cachePathForTicker:ticker]; - return [NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; + NSString *cachePath =[self cachePathForTicker:ticker]; + return[NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; } return NO; -} */ +} + +/*- (BOOL)cacheTodayPoints:(NSArray *)points forTicker:(NSString *)ticker + { + NSDictionary *cacheDict = @{@"cacheTodayDate": [NSDate date], @"today_data": points}; + inMemCache[ticker] = cacheDict; + + if (self.diskCachingEnabled) { + NSString *cachePath = [self cachePathForTicker:ticker]; + return [NSKeyedArchiver archiveRootObject:cacheDict toFile:cachePath]; + } + return NO; + } */ - (void)setMemoryCachingEnabled:(BOOL)inMemoryCachingEnabled { -inMemCache = nil; -if (inMemoryCachingEnabled) -inMemCache =[[NSMutableDictionary alloc] init]; + inMemCache = nil; + if (inMemoryCachingEnabled) + inMemCache =[[NSMutableDictionary alloc] init]; } - (id)init { -self =[super init]; -if (self) { -self.memoryCachingEnabled = YES; -self.diskCachingEnabled = YES; -inMemCache =[[NSMutableDictionary alloc] init]; -} -return self; + self =[super init]; + if (self) { + self.memoryCachingEnabled = YES; + self.diskCachingEnabled = YES; + inMemCache =[[NSMutableDictionary alloc] init]; + } + return self; } @end From 9eb4a24b5831e781c7ff3a5620de0b815e477f1a Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Tue, 14 Oct 2014 11:43:05 +0800 Subject: [PATCH 16/23] backup before UI change. --- JCStockGraph.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JCStockGraph.podspec b/JCStockGraph.podspec index 432fb1d..c162d08 100644 --- a/JCStockGraph.podspec +++ b/JCStockGraph.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.dependency 'CorePlot', '~> 1.5' s.dependency 'AFNetworking', '~> 1.3.0' s.dependency 'MBProgressHUD', '~> 0.8' - s.dependency 'MTDates', '~> 0.12' + s.dependency 'MTDates', '~> 0.13.0' s.dependency 'FontasticIcons', '~> 0.5' end From 16f22468b66dfa38e90add3b513cc0c22b1d7eb8 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Thu, 27 Nov 2014 12:17:41 +0800 Subject: [PATCH 17/23] Fixed some issues that might cause crash. --- Classes/JCStockPriceStore.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index 8e55f75..e3817b6 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -73,6 +73,12 @@ - (void)getTodayStockPrice:(NSString *)ticker longPoints:(NSArray *)points today // reformat the date string NSMutableString *csvString_tmp =[csvString mutableCopy]; + if ([csvString_tmp hasPrefix:@"Missing Symbols List"]) // 找不到代號的情形.. + { + [self mergePoints:points todayPoints:today_points completion:comp]; + return; + } + NSRegularExpression *regex =[NSRegularExpression regularExpressionWithPattern: @"\"([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\"" options:0 error:nil]; [regex replaceMatchesInString:csvString_tmp options:0 range:NSMakeRange(0,[csvString_tmp length]) withTemplate:@"$3-$1-$2"]; regex =[NSRegularExpression regularExpressionWithPattern: @"-([0-9]{1})-" options:0 error:nil]; @@ -218,8 +224,8 @@ - (NSArray *)dataPointsForCSVString:(NSString *)csvString data =[data sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; NSDate *lastDate=nil; - for (NSString *rowString in data) { - + for (NSString *rowString in data) + { NSArray *row =[rowString componentsSeparatedByString:@","]; JCPriceDataPoint *point =[[JCPriceDataPoint alloc] init]; From a84a8b98a6c6503af49af4df29ee8a0cdd7a08f3 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 31 Dec 2014 20:23:42 +0800 Subject: [PATCH 18/23] DJCurrencyGraph class inited. --- Classes/MBProgressHUD+Customizations.h | 5 +++++ Classes/MHPagingScrollView.h | 4 ++++ Classes/NSDate+YQL.h | 4 ++++ Classes/UIView+FrameAccessor.h | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/Classes/MBProgressHUD+Customizations.h b/Classes/MBProgressHUD+Customizations.h index 29e3dd1..1ba5942 100755 --- a/Classes/MBProgressHUD+Customizations.h +++ b/Classes/MBProgressHUD+Customizations.h @@ -6,6 +6,9 @@ // Copyright (c) 2013 Benzinga. All rights reserved. // +#ifndef MBProgressHUD_Customizations_h +#define MBProgressHUD_Customizations_h + #import "MBProgressHUD.h" @interface MBProgressHUD (Cusomizations) @@ -17,3 +20,5 @@ - (UIView *)indicator; @end + +#endif \ No newline at end of file diff --git a/Classes/MHPagingScrollView.h b/Classes/MHPagingScrollView.h index 0b35eb1..04ee4e1 100755 --- a/Classes/MHPagingScrollView.h +++ b/Classes/MHPagingScrollView.h @@ -1,3 +1,5 @@ +#ifndef MHPagingScrollView_h +#define MHPagingScrollView_h @class MHPagingScrollView; @@ -79,3 +81,5 @@ - (void)didReceiveMemoryWarning; @end + +#endif \ No newline at end of file diff --git a/Classes/NSDate+YQL.h b/Classes/NSDate+YQL.h index 7850435..ec927a9 100644 --- a/Classes/NSDate+YQL.h +++ b/Classes/NSDate+YQL.h @@ -5,6 +5,8 @@ // Created by Joseph Constantakis on 5/4/14. // // +#ifndef NSDate_YQL_h +#define NSDate_YQL_h #import @@ -17,3 +19,5 @@ - (NSString *)yqlEndString; @end + +#endif \ No newline at end of file diff --git a/Classes/UIView+FrameAccessor.h b/Classes/UIView+FrameAccessor.h index 308b2a6..05f9824 100755 --- a/Classes/UIView+FrameAccessor.h +++ b/Classes/UIView+FrameAccessor.h @@ -5,6 +5,8 @@ // Created by Alex Denisov on 18.03.12. // Copyright (c) 2012 CoreInvader. All rights reserved. // +#ifndef UIView_FrameAccessor_h +#define UIView_FrameAccessor_h #import @@ -31,3 +33,5 @@ - (void)setRight:(CGFloat)newRight; @end + +#endif \ No newline at end of file From 7bf5ce5ee4430dee005cd45dad1093b97b073629 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Tue, 6 Jan 2015 09:48:13 +0800 Subject: [PATCH 19/23] backup. --- Classes/JCStockGraphView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index 78554cb..778f8c4 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -197,7 +197,7 @@ - (void)addRangeLabel rangeLabel.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.4]; [rangeLabel sizeToFit]; rangeLabel.width += 8; - rangeLabel.y = self.height; // - rangeLabel.height; + rangeLabel.y = self.height + 4; // - rangeLabel.height; rangeLabel.right = self.right; rangeLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin; [self addSubview:rangeLabel]; From 925d4ccc241dc23909903709edece748516c0ec1 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Wed, 7 Jan 2015 23:31:32 +0800 Subject: [PATCH 20/23] Fix VM:CoreAnimation memory leak issue. --- Classes/JCStockGraphController.h | 2 ++ Classes/JCStockGraphController.m | 6 ++++++ Classes/JCStockGraphPageController.m | 13 +++++++++++++ Classes/JCStockGraphView.h | 2 ++ Classes/JCStockGraphView.m | 15 +++++++++++++++ 5 files changed, 38 insertions(+) diff --git a/Classes/JCStockGraphController.h b/Classes/JCStockGraphController.h index aa8f3fa..5d54dd1 100755 --- a/Classes/JCStockGraphController.h +++ b/Classes/JCStockGraphController.h @@ -47,4 +47,6 @@ typedef NSInteger JCStockGraphOptionMask; - (void)loadDataWithCompletion:(void (^)())completion; - (void)reloadGraph; +- (void)releaseGraph; + @end diff --git a/Classes/JCStockGraphController.m b/Classes/JCStockGraphController.m index a5e6372..b179279 100755 --- a/Classes/JCStockGraphController.m +++ b/Classes/JCStockGraphController.m @@ -118,6 +118,12 @@ - (void)reloadGraph [self.graphView reloadGraph]; } +- (void)releaseGraph +{ + [self.graphView removePlots]; + self.graphView = nil; +} + - (NSArray *)thinPoints:(NSArray *)fullPoints { //Make graph look smoother by thinning out the number of data points diff --git a/Classes/JCStockGraphPageController.m b/Classes/JCStockGraphPageController.m index 222c306..c7a451e 100755 --- a/Classes/JCStockGraphPageController.m +++ b/Classes/JCStockGraphPageController.m @@ -45,6 +45,19 @@ - (void)viewWillAppear:(BOOL)animated [self reloadViews]; } +- (void)viewDidDisappear:(BOOL)animated +{ + [super viewDidDisappear:animated]; + if (graphControllers!=nil) + { + for (JCStockGraphController *gc in graphControllers) + { + [gc releaseGraph]; + [gc removeFromParentViewController]; + } + } +} + - (void)reloadViews { if (pagingScrollView) { diff --git a/Classes/JCStockGraphView.h b/Classes/JCStockGraphView.h index 916f951..23dffc3 100755 --- a/Classes/JCStockGraphView.h +++ b/Classes/JCStockGraphView.h @@ -30,4 +30,6 @@ - (void)hideYAxis; - (void)addRangeLabel; +-(void)removePlots; + @end diff --git a/Classes/JCStockGraphView.m b/Classes/JCStockGraphView.m index 778f8c4..8859b8e 100755 --- a/Classes/JCStockGraphView.m +++ b/Classes/JCStockGraphView.m @@ -23,6 +23,21 @@ - (void)reloadGraph [self.hostView.hostedGraph reloadData]; } +#pragma mark - some release handle +-(void)removePlots +{ + for (CPTPlot* plot in [self.hostView.hostedGraph allPlots]) + { + plot.dataSource = nil; + plot.delegate = nil; + [plot deleteDataInIndexRange:NSMakeRange(0, plot.cachedDataCount)]; + [self.hostView.hostedGraph removePlot:plot]; + } + [self.hostView removeFromSuperview]; + self.hostView = nil; +} + + #pragma mark - Chart behavior -(void)configureHost From 19a5fb2313e433621e79a377f0cfb33c9e7e53f8 Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Tue, 27 Jan 2015 17:10:24 +0800 Subject: [PATCH 21/23] Added OTC case. --- Classes/JCStockPriceStore.m | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index e3817b6..e799cb3 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -157,7 +157,8 @@ - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress: } - if (needUpdateLong) { + if (needUpdateLong) + { //Build URL: NSString *urlString =[NSString stringWithFormat:@"http://ichart.finance.yahoo.com/table.csv?s=%@&%@&%@", ticker,[startDate yqlStartString],[endDate yqlEndString]]; @@ -166,7 +167,8 @@ - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress: //Create Request: AFHTTPRequestOperation *operation =[[AFHTTPRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:url]]; - [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { + [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) + { NSString *csvString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; NSArray *newPoints =[self dataPointsForCSVString:csvString]; [points removeAllObjects]; @@ -175,10 +177,20 @@ - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress: [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - // still try today stock price... - [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; - NSLog(@"CSV request failure: %@", error); + } + failure:^(AFHTTPRequestOperation *operation, NSError *error) + { + // 201501. maybe TPO of Taiwan.. + if ([ticker hasSuffix:@".TW"]) + { + // change .TW to .TWO + NSString *qNewTicker = [NSString stringWithFormat:@"%@O", ticker]; + [self getDataForTicker:qNewTicker parentPage:qParent withProgress:progBlock completion:comp]; + } else { + // still try today stock price... + [self getTodayStockPrice:ticker longPoints:points todayPoints:today_points withProgress:progBlock completion:comp]; + NSLog(@"CSV request failure: %@", error); + } }]; // Dowload Progress From 29fb6bdc9e47fc60916a38329ee3fcbc3ac765fe Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Sun, 8 Mar 2015 01:08:05 +0800 Subject: [PATCH 22/23] Added UISplitViewControllerCustom for iNews123 --- Classes/JCStockPriceStore.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/JCStockPriceStore.m b/Classes/JCStockPriceStore.m index e799cb3..bfd0e9b 100755 --- a/Classes/JCStockPriceStore.m +++ b/Classes/JCStockPriceStore.m @@ -136,7 +136,8 @@ - (BOOL)getDataForTicker:(NSString *)ticker parentPage:(id)qParent withProgress: NSDate *cacheDate = cacheDict[@"cacheDate"]; if (![cacheDate mt_isWithinSameDay:endDate] ||[points count] < 50 // abnormal case.. - ) { + ) + { needUpdateTotday = YES; needUpdateLong = YES; } else { From 038b190595509edb4be7341d10a659cc8dcd411b Mon Sep 17 00:00:00 2001 From: Der-Johng Sun Date: Thu, 10 Sep 2015 10:44:50 +0800 Subject: [PATCH 23/23] Backup. --- Classes/JCStockGraphView.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/JCStockGraphView.h b/Classes/JCStockGraphView.h index 23dffc3..65f227f 100755 --- a/Classes/JCStockGraphView.h +++ b/Classes/JCStockGraphView.h @@ -7,7 +7,8 @@ // #import -#import "CorePlot/CorePlot-CocoaTouch.h" +//#import "CorePlot/CorePlot-CocoaTouch.h" +#import "CorePlot-CocoaTouch.h" #import "JCStockGraphController.h" @class JCStockPriceStore;