├── ZFPlotChart
├── preview.png
├── AppDelegate.h
├── ViewController.h
├── main.m
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.xib
├── Info.plist
├── ZFPlotChart.h
├── ViewController.m
├── AppDelegate.m
├── data.json
└── ZFPlotChart.m
├── ZFPlotChart.xcodeproj
├── xcuserdata
│ └── Francesco.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── ZFPlotChart.xcscheme
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── ZFPlotChart.xccheckout
└── project.pbxproj
├── README.md
└── ZFPlotChartTests
├── Info.plist
└── ZFPlotChartTests.m
/ZFPlotChart/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zerbfra/ZFPlotChart/HEAD/ZFPlotChart/preview.png
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/xcuserdata/Francesco.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ZFPlotChart/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ZFPlotChart
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/ZFPlotChart/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // ZFPlotChart
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ZFPlotChart.h"
11 |
12 | @interface ViewController : UIViewController
13 |
14 | @property (strong, nonatomic) IBOutlet ZFPlotChart *plotChart;
15 |
16 |
17 | @end
18 |
19 |
--------------------------------------------------------------------------------
/ZFPlotChart/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ZFPlotChart
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ZFPlotChart
2 | _Simple class to draw a line graph based on a JSON file, written in Objective-C_
3 |
4 | This class is used in PriceRadar, the app I wrote to track prices on Amazon, available [here](https://itunes.apple.com/us/app/priceradar-seguiprezzo-per/id790926556?mt=8)
5 |
6 | Inside the project you will find a sample JSON used to make the example.
7 |
8 | As you can see it comes handy when drawing price/stock values during time.
9 |
10 | Feel free to use this class, let me know if you find some bugs!
11 |
12 | ## Preview Image
13 |
14 | 
15 |
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/xcuserdata/Francesco.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ZFPlotChart.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 13899B3B1B36CF4B0060AD92
16 |
17 | primary
18 |
19 |
20 | 13899B541B36CF4B0060AD92
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ZFPlotChartTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | it.zerbinatifrancesco.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ZFPlotChartTests/ZFPlotChartTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZFPlotChartTests.m
3 | // ZFPlotChartTests
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface ZFPlotChartTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation ZFPlotChartTests
17 |
18 | - (void)setUp {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown {
24 | // Put teardown code here. This method is called after the invocation of each test method in the class.
25 | [super tearDown];
26 | }
27 |
28 | - (void)testExample {
29 | // This is an example of a functional test case.
30 | XCTAssert(YES, @"Pass");
31 | }
32 |
33 | - (void)testPerformanceExample {
34 | // This is an example of a performance test case.
35 | [self measureBlock:^{
36 | // Put the code you want to measure the time of here.
37 | }];
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/ZFPlotChart/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/ZFPlotChart/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/project.xcworkspace/xcshareddata/ZFPlotChart.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | C2A84B5D-487D-4925-8D32-6112C53FB1A7
9 | IDESourceControlProjectName
10 | ZFPlotChart
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | B333D55996A51EE13B7A99C43A031119C1C70BA4
14 | https://github.com/zerbfra/zfPlotChart.git
15 |
16 | IDESourceControlProjectPath
17 | ZFPlotChart.xcodeproj
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | B333D55996A51EE13B7A99C43A031119C1C70BA4
21 | ../..
22 |
23 | IDESourceControlProjectURL
24 | https://github.com/zerbfra/zfPlotChart.git
25 | IDESourceControlProjectVersion
26 | 111
27 | IDESourceControlProjectWCCIdentifier
28 | B333D55996A51EE13B7A99C43A031119C1C70BA4
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | B333D55996A51EE13B7A99C43A031119C1C70BA4
36 | IDESourceControlWCCName
37 | ZFPlotChart
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/ZFPlotChart/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | it.zerbinatifrancesco.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ZFPlotChart/ZFPlotChart.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZFPlotChart.h
3 | //
4 | // Created by Zerbinati Francesco
5 | // Copyright (c) 2014-2015
6 | //
7 |
8 | #import
9 | #import
10 |
11 | #define COLOR_WITH_RGB(r,g,b) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:1.0f] // Macro for colors
12 |
13 | // Dimension costants
14 | #define topMargin 20.0f // top margin
15 | #define vMargin 40.0f // vertical margin
16 | #define hMargin 10.0f // horizontal margin
17 | #define leftSpace 10.0f // left space
18 |
19 | // Graph grid color
20 | #define linesColor [UIColor lightGrayColor]
21 |
22 | // Colors for lines and background
23 | #define orangeColor COLOR_WITH_RGB(255, 150, 10)
24 | #define whiteColor [UIColor whiteColor]
25 |
26 | // Fonts
27 | #define systemFont [UIFont systemFontOfSize:10]
28 | #define boldFont [UIFont boldSystemFontOfSize:10]
29 |
30 | // definitions (as JSON)
31 | #define fzPoint @"Point"
32 | #define fzValue @"value"
33 | #define fzDate @"time"
34 | #define fzDateFormat @"yyyyMMdd"
35 |
36 | @interface ZFPlotChart : UIView
37 | {
38 | NSMutableOrderedSet *dictDispPoint;
39 | float chartWidth, chartHeight;
40 | CGPoint prevPoint, curPoint;
41 | float min, max;
42 | BOOL isMovement; // Default NO
43 | CGPoint currentLoc;
44 | }
45 |
46 | @property (nonatomic, retain) NSMutableOrderedSet *dictDispPoint;
47 |
48 | @property (nonatomic, readwrite) float chartWidth, chartHeight;
49 | @property (nonatomic, readwrite) CGFloat leftMargin;
50 |
51 | @property (nonatomic, readwrite) CGPoint prevPoint, curPoint, currentLoc;
52 | @property (nonatomic, readwrite) float min, max;
53 |
54 | @property (nonatomic, readwrite) float yMax,yMin;
55 |
56 | @property (strong) UIActivityIndicatorView *loadingSpinner;
57 |
58 | - (void)createChartWith:(NSOrderedSet *)data;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/ZFPlotChart/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // ZFPlotChart
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | @interface ViewController ()
12 |
13 | @end
14 |
15 | @implementation ViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 |
20 | /********** Creating an area for the graph ***********/
21 |
22 | CGRect screenRect = [[UIScreen mainScreen] bounds];
23 | CGFloat screenWidth = screenRect.size.width;
24 |
25 | CGRect frame = CGRectMake(0, 100, screenWidth, 190);
26 |
27 | // initialization
28 | self.plotChart = [[ZFPlotChart alloc] initWithFrame:frame];
29 | [self.view addSubview:self.plotChart];
30 |
31 |
32 | // get the data from the json file
33 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"];
34 | // string creation
35 | NSString *jsonString = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
36 | // json parsing
37 | NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
38 |
39 | if (!json) {
40 | NSLog(@"Error parsing JSON");
41 | } else {
42 | NSLog(@"%@",json);
43 | }
44 |
45 | // values are contained inside "values" in the JSON file
46 | NSArray *values = [json valueForKeyPath:@"values"];
47 | // create the nsorderedset from the array
48 | NSOrderedSet *result = [NSOrderedSet orderedSetWithArray:values];
49 |
50 | self.plotChart.alpha = 0;
51 | // draw data
52 | [self.plotChart createChartWith:result];
53 | [UIView animateWithDuration:0.5 animations:^{
54 | self.plotChart.alpha = 1.0;
55 | }];
56 |
57 |
58 | }
59 |
60 | - (void)didReceiveMemoryWarning {
61 | [super didReceiveMemoryWarning];
62 | // Dispose of any resources that can be recreated.
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/ZFPlotChart/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ZFPlotChart
4 | //
5 | // Created by Francesco Zerbinati on 21/06/15.
6 | // Copyright (c) 2015 Francesco Zerbinati. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/ZFPlotChart/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/xcuserdata/Francesco.xcuserdatad/xcschemes/ZFPlotChart.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/ZFPlotChart/data.json:
--------------------------------------------------------------------------------
1 | {"values": [
2 | {
3 | "time": "20141204",
4 | "value": "12499"
5 | },
6 | {
7 | "time": "20141205",
8 | "value": "12499"
9 | },
10 | {
11 | "time": "20141206",
12 | "value": "12499"
13 | },
14 | {
15 | "time": "20141207",
16 | "value": "12499"
17 | },
18 | {
19 | "time": "20141208",
20 | "value": "12499"
21 | },
22 | {
23 | "time": "20141209",
24 | "value": "12499"
25 | },
26 | {
27 | "time": "20141210",
28 | "value": "12370"
29 | },
30 | {
31 | "time": "20141211",
32 | "value": "12370"
33 | },
34 | {
35 | "time": "20141212",
36 | "value": "12370"
37 | },
38 | {
39 | "time": "20141213",
40 | "value": "12499"
41 | },
42 | {
43 | "time": "20141214",
44 | "value": "12499"
45 | },
46 | {
47 | "time": "20141215",
48 | "value": "12499"
49 | },
50 | {
51 | "time": "20141216",
52 | "value": "12499"
53 | },
54 | {
55 | "time": "20141217",
56 | "value": "12499"
57 | },
58 | {
59 | "time": "20141218",
60 | "value": "12374"
61 | },
62 | {
63 | "time": "20141219",
64 | "value": "12374"
65 | },
66 | {
67 | "time": "20141220",
68 | "value": "12374"
69 | },
70 | {
71 | "time": "20141221",
72 | "value": "12374"
73 | },
74 | {
75 | "time": "20141222",
76 | "value": "12374"
77 | },
78 | {
79 | "time": "20141223",
80 | "value": "12374"
81 | },
82 | {
83 | "time": "20141224",
84 | "value": "12374"
85 | },
86 | {
87 | "time": "20141228",
88 | "value": "12374"
89 | },
90 | {
91 | "time": "20141229",
92 | "value": "12374"
93 | },
94 | {
95 | "time": "20141230",
96 | "value": "12374"
97 | },
98 | {
99 | "time": "20141231",
100 | "value": "12374"
101 | },
102 | {
103 | "time": "20150101",
104 | "value": "12374"
105 | },
106 | {
107 | "time": "20150102",
108 | "value": "12374"
109 | },
110 | {
111 | "time": "20150103",
112 | "value": "12374"
113 | },
114 | {
115 | "time": "20150104",
116 | "value": "12374"
117 | },
118 | {
119 | "time": "20150105",
120 | "value": "12374"
121 | },
122 | {
123 | "time": "20150106",
124 | "value": "12374"
125 | },
126 | {
127 | "time": "20150107",
128 | "value": "12374"
129 | },
130 | {
131 | "time": "20150108",
132 | "value": "12374"
133 | },
134 | {
135 | "time": "20150109",
136 | "value": "12374"
137 | },
138 | {
139 | "time": "20150110",
140 | "value": "12374"
141 | },
142 | {
143 | "time": "20150111",
144 | "value": "12374"
145 | },
146 | {
147 | "time": "20150112",
148 | "value": "12374"
149 | },
150 | {
151 | "time": "20150113",
152 | "value": "12374"
153 | },
154 | {
155 | "time": "20150114",
156 | "value": "12374"
157 | },
158 | {
159 | "time": "20150115",
160 | "value": "12374"
161 | },
162 | {
163 | "time": "20150116",
164 | "value": "12374"
165 | },
166 | {
167 | "time": "20150117",
168 | "value": "12370"
169 | },
170 | {
171 | "time": "20150118",
172 | "value": "12370"
173 | },
174 | {
175 | "time": "20150119",
176 | "value": "12370"
177 | },
178 | {
179 | "time": "20150120",
180 | "value": "12370"
181 | },
182 | {
183 | "time": "20150121",
184 | "value": "12370"
185 | },
186 | {
187 | "time": "20150122",
188 | "value": "12370"
189 | },
190 | {
191 | "time": "20150202",
192 | "value": "12370"
193 | },
194 | {
195 | "time": "20150203",
196 | "value": "12370"
197 | },
198 | {
199 | "time": "20150204",
200 | "value": "12374"
201 | },
202 | {
203 | "time": "20150205",
204 | "value": "12374"
205 | },
206 | {
207 | "time": "20150206",
208 | "value": "12374"
209 | },
210 | {
211 | "time": "20150207",
212 | "value": "12374"
213 | },
214 | {
215 | "time": "20150208",
216 | "value": "12374"
217 | },
218 | {
219 | "time": "20150209",
220 | "value": "12374"
221 | },
222 | {
223 | "time": "20150210",
224 | "value": "12374"
225 | },
226 | {
227 | "time": "20150211",
228 | "value": "12374"
229 | },
230 | {
231 | "time": "20150212",
232 | "value": "12374"
233 | },
234 | {
235 | "time": "20150213",
236 | "value": "12374"
237 | },
238 | {
239 | "time": "20150214",
240 | "value": "12374"
241 | },
242 | {
243 | "time": "20150215",
244 | "value": "12374"
245 | },
246 | {
247 | "time": "20150216",
248 | "value": "11755"
249 | },
250 | {
251 | "time": "20150217",
252 | "value": "12374"
253 | },
254 | {
255 | "time": "20150218",
256 | "value": "12374"
257 | },
258 | {
259 | "time": "20150219",
260 | "value": "12374"
261 | },
262 | {
263 | "time": "20150220",
264 | "value": "12374"
265 | },
266 | {
267 | "time": "20150221",
268 | "value": "12374"
269 | },
270 | {
271 | "time": "20150222",
272 | "value": "12374"
273 | },
274 | {
275 | "time": "20150223",
276 | "value": "12374"
277 | },
278 | {
279 | "time": "20150224",
280 | "value": "12374"
281 | },
282 | {
283 | "time": "20150225",
284 | "value": "12374"
285 | },
286 | {
287 | "time": "20150226",
288 | "value": "12374"
289 | },
290 | {
291 | "time": "20150227",
292 | "value": "12374"
293 | },
294 | {
295 | "time": "20150228",
296 | "value": "12374"
297 | },
298 | {
299 | "time": "20150301",
300 | "value": "12374"
301 | },
302 | {
303 | "time": "20150302",
304 | "value": "12374"
305 | },
306 | {
307 | "time": "20150303",
308 | "value": "12374"
309 | },
310 | {
311 | "time": "20150304",
312 | "value": "12374"
313 | },
314 | {
315 | "time": "20150305",
316 | "value": "12374"
317 | },
318 | {
319 | "time": "20150306",
320 | "value": "12374"
321 | },
322 | {
323 | "time": "20150307",
324 | "value": "12374"
325 | },
326 | {
327 | "time": "20150308",
328 | "value": "12374"
329 | },
330 | {
331 | "time": "20150309",
332 | "value": "12374"
333 | },
334 | {
335 | "time": "20150310",
336 | "value": "12374"
337 | },
338 | {
339 | "time": "20150311",
340 | "value": "12374"
341 | },
342 | {
343 | "time": "20150312",
344 | "value": "12613"
345 | },
346 | {
347 | "time": "20150313",
348 | "value": "12374"
349 | },
350 | {
351 | "time": "20150314",
352 | "value": "12374"
353 | },
354 | {
355 | "time": "20150315",
356 | "value": "12374"
357 | },
358 | {
359 | "time": "20150316",
360 | "value": "12374"
361 | },
362 | {
363 | "time": "20150317",
364 | "value": "12374"
365 | },
366 | {
367 | "time": "20150318",
368 | "value": "13859"
369 | },
370 | {
371 | "time": "20150319",
372 | "value": "12863"
373 | },
374 | {
375 | "time": "20150320",
376 | "value": "11755"
377 | },
378 | {
379 | "time": "20150321",
380 | "value": "11755"
381 | },
382 | {
383 | "time": "20150322",
384 | "value": "11755"
385 | },
386 | {
387 | "time": "20150323",
388 | "value": "11755"
389 | },
390 | {
391 | "time": "20150324",
392 | "value": "11755"
393 | },
394 | {
395 | "time": "20150325",
396 | "value": "11755"
397 | },
398 | {
399 | "time": "20150326",
400 | "value": "11755"
401 | },
402 | {
403 | "time": "20150327",
404 | "value": "13999"
405 | },
406 | {
407 | "time": "20150328",
408 | "value": "13999"
409 | },
410 | {
411 | "time": "20150329",
412 | "value": "13999"
413 | },
414 | {
415 | "time": "20150330",
416 | "value": "12428"
417 | },
418 | {
419 | "time": "20150331",
420 | "value": "13724"
421 | },
422 | {
423 | "time": "20150401",
424 | "value": "12869"
425 | },
426 | {
427 | "time": "20150402",
428 | "value": "12869"
429 | },
430 | {
431 | "time": "20150403",
432 | "value": "12869"
433 | },
434 | {
435 | "time": "20150404",
436 | "value": "12869"
437 | },
438 | {
439 | "time": "20150405",
440 | "value": "12869"
441 | },
442 | {
443 | "time": "20150406",
444 | "value": "12869"
445 | },
446 | {
447 | "time": "20150407",
448 | "value": "12869"
449 | },
450 | {
451 | "time": "20150408",
452 | "value": "12869"
453 | },
454 | {
455 | "time": "20150409",
456 | "value": "12869"
457 | },
458 | {
459 | "time": "20150410",
460 | "value": "12869"
461 | },
462 | {
463 | "time": "20150411",
464 | "value": "12869"
465 | },
466 | {
467 | "time": "20150412",
468 | "value": "12869"
469 | },
470 | {
471 | "time": "20150413",
472 | "value": "13855"
473 | },
474 | {
475 | "time": "20150414",
476 | "value": "12869"
477 | },
478 | {
479 | "time": "20150415",
480 | "value": "12869"
481 | },
482 | {
483 | "time": "20150416",
484 | "value": "12869"
485 | },
486 | {
487 | "time": "20150417",
488 | "value": "12869"
489 | },
490 | {
491 | "time": "20150418",
492 | "value": "12869"
493 | },
494 | {
495 | "time": "20150419",
496 | "value": "12869"
497 | },
498 | {
499 | "time": "20150420",
500 | "value": "12869"
501 | },
502 | {
503 | "time": "20150421",
504 | "value": "13598"
505 | },
506 | {
507 | "time": "20150422",
508 | "value": "12869"
509 | },
510 | {
511 | "time": "20150423",
512 | "value": "13363"
513 | },
514 | {
515 | "time": "20150424",
516 | "value": "11879"
517 | },
518 | {
519 | "time": "20150425",
520 | "value": "11879"
521 | },
522 | {
523 | "time": "20150426",
524 | "value": "11879"
525 | },
526 | {
527 | "time": "20150427",
528 | "value": "12374"
529 | },
530 | {
531 | "time": "20150428",
532 | "value": "12374"
533 | },
534 | {
535 | "time": "20150429",
536 | "value": "12374"
537 | },
538 | {
539 | "time": "20150430",
540 | "value": "12621"
541 | },
542 | {
543 | "time": "20150501",
544 | "value": "12621"
545 | },
546 | {
547 | "time": "20150502",
548 | "value": "12869"
549 | },
550 | {
551 | "time": "20150503",
552 | "value": "12869"
553 | },
554 | {
555 | "time": "20150504",
556 | "value": "12869"
557 | },
558 | {
559 | "time": "20150505",
560 | "value": "12869"
561 | },
562 | {
563 | "time": "20150506",
564 | "value": "12869"
565 | },
566 | {
567 | "time": "20150507",
568 | "value": "12869"
569 | },
570 | {
571 | "time": "20150508",
572 | "value": "12869"
573 | },
574 | {
575 | "time": "20150509",
576 | "value": "12869"
577 | },
578 | {
579 | "time": "20150510",
580 | "value": "12869"
581 | },
582 | {
583 | "time": "20150511",
584 | "value": "12869"
585 | },
586 | {
587 | "time": "20150512",
588 | "value": "12869"
589 | },
590 | {
591 | "time": "20150513",
592 | "value": "12869"
593 | },
594 | {
595 | "time": "20150514",
596 | "value": "12869"
597 | },
598 | {
599 | "time": "20150515",
600 | "value": "12869"
601 | },
602 | {
603 | "time": "20150516",
604 | "value": "12869"
605 | },
606 | {
607 | "time": "20150517",
608 | "value": "12869"
609 | },
610 | {
611 | "time": "20150518",
612 | "value": "12349"
613 | },
614 | {
615 | "time": "20150519",
616 | "value": "12869"
617 | },
618 | {
619 | "time": "20150531",
620 | "value": "12869"
621 | },
622 | {
623 | "time": "20150601",
624 | "value": "12869"
625 | },
626 | {
627 | "time": "20150602",
628 | "value": "12869"
629 | },
630 | {
631 | "time": "20150603",
632 | "value": "12869"
633 | },
634 | {
635 | "time": "20150604",
636 | "value": "12999"
637 | },
638 | {
639 | "time": "20150605",
640 | "value": "13499"
641 | },
642 | {
643 | "time": "20150606",
644 | "value": "13499"
645 | },
646 | {
647 | "time": "20150607",
648 | "value": "13499"
649 | },
650 | {
651 | "time": "20150608",
652 | "value": "13499"
653 | },
654 | {
655 | "time": "20150609",
656 | "value": "13499"
657 | },
658 | {
659 | "time": "20150610",
660 | "value": "13499"
661 | },
662 | {
663 | "time": "20150611",
664 | "value": "13499"
665 | },
666 | {
667 | "time": "20150612",
668 | "value": "13499"
669 | },
670 | {
671 | "time": "20150613",
672 | "value": "13499"
673 | },
674 | {
675 | "time": "20150614",
676 | "value": "13499"
677 | },
678 | {
679 | "time": "20150615",
680 | "value": "13499"
681 | },
682 | {
683 | "time": "20150616",
684 | "value": "13498"
685 | },
686 | {
687 | "time": "20150617",
688 | "value": "12999"
689 | },
690 | {
691 | "time": "20150618",
692 | "value": "12999"
693 | },
694 | {
695 | "time": "20150619",
696 | "value": "12999"
697 | },
698 | {
699 | "time": "20150620",
700 | "value": "12999"
701 | },
702 | {
703 | "time": "20150621",
704 | "value": "12999"
705 | },
706 | {
707 | "time": "20150622",
708 | "value": "12999"
709 | },
710 | {
711 | "time": "20150623",
712 | "value": "12999"
713 | },
714 | {
715 | "time": "20150624",
716 | "value": "12999"
717 | },
718 | {
719 | "time": "20150625",
720 | "value": "12999"
721 | },
722 | {
723 | "time": "20150626",
724 | "value": "12999"
725 | },
726 | {
727 | "time": "20150627",
728 | "value": "12999"
729 | },
730 | {
731 | "time": "20150628",
732 | "value": "12999"
733 | },
734 | {
735 | "time": "20150629",
736 | "value": "12999"
737 | },
738 | {
739 | "time": "20150630",
740 | "value": "12999"
741 | },
742 | {
743 | "time": "20150701",
744 | "value": "12999"
745 | },
746 | {
747 | "time": "20150702",
748 | "value": "12999"
749 | },
750 | {
751 | "time": "20150703",
752 | "value": "12999"
753 | },
754 | {
755 | "time": "20150704",
756 | "value": "12999"
757 | },
758 | {
759 | "time": "20150705",
760 | "value": "12999"
761 | },
762 | {
763 | "time": "20150706",
764 | "value": "12999"
765 | },
766 | {
767 | "time": "20150707",
768 | "value": "12999"
769 | },
770 | {
771 | "time": "20150708",
772 | "value": "12999"
773 | },
774 | {
775 | "time": "20150709",
776 | "value": "12999"
777 | },
778 | {
779 | "time": "20150710",
780 | "value": "12999"
781 | },
782 | {
783 | "time": "20150711",
784 | "value": "12999"
785 | },
786 | {
787 | "time": "20150712",
788 | "value": "12999"
789 | },
790 | {
791 | "time": "20150713",
792 | "value": "12999"
793 | },
794 | {
795 | "time": "20150714",
796 | "value": "12999"
797 | },
798 | {
799 | "time": "20150715",
800 | "value": "12999"
801 | },
802 | {
803 | "time": "20150716",
804 | "value": "13999"
805 | },
806 | {
807 | "time": "20150717",
808 | "value": "12937"
809 | },
810 | {
811 | "time": "20150718",
812 | "value": "12937"
813 | },
814 | {
815 | "time": "20150719",
816 | "value": "12937"
817 | },
818 | {
819 | "time": "20150720",
820 | "value": "13999"
821 | },
822 | {
823 | "time": "20150721",
824 | "value": "13999"
825 | },
826 | {
827 | "time": "20150722",
828 | "value": "13999"
829 | },
830 | {
831 | "time": "20150723",
832 | "value": "13999"
833 | },
834 | {
835 | "time": "20150724",
836 | "value": "13999"
837 | },
838 | {
839 | "time": "20150804",
840 | "value": "13998"
841 | },
842 | {
843 | "time": "20150805",
844 | "value": "13998"
845 | },
846 | {
847 | "time": "20150806",
848 | "value": "13998"
849 | },
850 | {
851 | "time": "20150807",
852 | "value": "13998"
853 | },
854 | {
855 | "time": "20150808",
856 | "value": "13998"
857 | }
858 | ]
859 | }
860 |
--------------------------------------------------------------------------------
/ZFPlotChart.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 135A8D301B77A1E000CE017E /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 135A8D2F1B77A1E000CE017E /* data.json */; };
11 | 135A8D3A1B77AAF300CE017E /* preview.png in Resources */ = {isa = PBXBuildFile; fileRef = 135A8D391B77AAF300CE017E /* preview.png */; };
12 | 13899B421B36CF4B0060AD92 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13899B411B36CF4B0060AD92 /* main.m */; };
13 | 13899B451B36CF4B0060AD92 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13899B441B36CF4B0060AD92 /* AppDelegate.m */; };
14 | 13899B481B36CF4B0060AD92 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13899B471B36CF4B0060AD92 /* ViewController.m */; };
15 | 13899B4B1B36CF4B0060AD92 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 13899B491B36CF4B0060AD92 /* Main.storyboard */; };
16 | 13899B4D1B36CF4B0060AD92 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13899B4C1B36CF4B0060AD92 /* Images.xcassets */; };
17 | 13899B501B36CF4B0060AD92 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13899B4E1B36CF4B0060AD92 /* LaunchScreen.xib */; };
18 | 13899B5C1B36CF4C0060AD92 /* ZFPlotChartTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13899B5B1B36CF4C0060AD92 /* ZFPlotChartTests.m */; };
19 | 13899B6A1B36CF820060AD92 /* ZFPlotChart.m in Sources */ = {isa = PBXBuildFile; fileRef = 13899B691B36CF820060AD92 /* ZFPlotChart.m */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXContainerItemProxy section */
23 | 13899B561B36CF4B0060AD92 /* PBXContainerItemProxy */ = {
24 | isa = PBXContainerItemProxy;
25 | containerPortal = 13899B341B36CF4B0060AD92 /* Project object */;
26 | proxyType = 1;
27 | remoteGlobalIDString = 13899B3B1B36CF4B0060AD92;
28 | remoteInfo = ZFPlotChart;
29 | };
30 | /* End PBXContainerItemProxy section */
31 |
32 | /* Begin PBXFileReference section */
33 | 135A8D2F1B77A1E000CE017E /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; };
34 | 135A8D391B77AAF300CE017E /* preview.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = preview.png; sourceTree = ""; };
35 | 13899B3C1B36CF4B0060AD92 /* ZFPlotChart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZFPlotChart.app; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 13899B401B36CF4B0060AD92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
37 | 13899B411B36CF4B0060AD92 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
38 | 13899B431B36CF4B0060AD92 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
39 | 13899B441B36CF4B0060AD92 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
40 | 13899B461B36CF4B0060AD92 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
41 | 13899B471B36CF4B0060AD92 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
42 | 13899B4A1B36CF4B0060AD92 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
43 | 13899B4C1B36CF4B0060AD92 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
44 | 13899B4F1B36CF4B0060AD92 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
45 | 13899B551B36CF4B0060AD92 /* ZFPlotChartTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ZFPlotChartTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 13899B5A1B36CF4C0060AD92 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | 13899B5B1B36CF4C0060AD92 /* ZFPlotChartTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ZFPlotChartTests.m; sourceTree = ""; };
48 | 13899B681B36CF820060AD92 /* ZFPlotChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZFPlotChart.h; sourceTree = ""; };
49 | 13899B691B36CF820060AD92 /* ZFPlotChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZFPlotChart.m; sourceTree = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | 13899B391B36CF4B0060AD92 /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | );
58 | runOnlyForDeploymentPostprocessing = 0;
59 | };
60 | 13899B521B36CF4B0060AD92 /* Frameworks */ = {
61 | isa = PBXFrameworksBuildPhase;
62 | buildActionMask = 2147483647;
63 | files = (
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | /* End PBXFrameworksBuildPhase section */
68 |
69 | /* Begin PBXGroup section */
70 | 13899B331B36CF4B0060AD92 = {
71 | isa = PBXGroup;
72 | children = (
73 | 13899B3E1B36CF4B0060AD92 /* ZFPlotChart */,
74 | 13899B581B36CF4C0060AD92 /* ZFPlotChartTests */,
75 | 13899B3D1B36CF4B0060AD92 /* Products */,
76 | );
77 | sourceTree = "";
78 | };
79 | 13899B3D1B36CF4B0060AD92 /* Products */ = {
80 | isa = PBXGroup;
81 | children = (
82 | 13899B3C1B36CF4B0060AD92 /* ZFPlotChart.app */,
83 | 13899B551B36CF4B0060AD92 /* ZFPlotChartTests.xctest */,
84 | );
85 | name = Products;
86 | sourceTree = "";
87 | };
88 | 13899B3E1B36CF4B0060AD92 /* ZFPlotChart */ = {
89 | isa = PBXGroup;
90 | children = (
91 | 13899B431B36CF4B0060AD92 /* AppDelegate.h */,
92 | 13899B441B36CF4B0060AD92 /* AppDelegate.m */,
93 | 13899B461B36CF4B0060AD92 /* ViewController.h */,
94 | 13899B471B36CF4B0060AD92 /* ViewController.m */,
95 | 13899B681B36CF820060AD92 /* ZFPlotChart.h */,
96 | 13899B691B36CF820060AD92 /* ZFPlotChart.m */,
97 | 13899B491B36CF4B0060AD92 /* Main.storyboard */,
98 | 13899B4C1B36CF4B0060AD92 /* Images.xcassets */,
99 | 13899B4E1B36CF4B0060AD92 /* LaunchScreen.xib */,
100 | 13899B3F1B36CF4B0060AD92 /* Supporting Files */,
101 | );
102 | path = ZFPlotChart;
103 | sourceTree = "";
104 | };
105 | 13899B3F1B36CF4B0060AD92 /* Supporting Files */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 135A8D391B77AAF300CE017E /* preview.png */,
109 | 135A8D2F1B77A1E000CE017E /* data.json */,
110 | 13899B401B36CF4B0060AD92 /* Info.plist */,
111 | 13899B411B36CF4B0060AD92 /* main.m */,
112 | );
113 | name = "Supporting Files";
114 | sourceTree = "";
115 | };
116 | 13899B581B36CF4C0060AD92 /* ZFPlotChartTests */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 13899B5B1B36CF4C0060AD92 /* ZFPlotChartTests.m */,
120 | 13899B591B36CF4C0060AD92 /* Supporting Files */,
121 | );
122 | path = ZFPlotChartTests;
123 | sourceTree = "";
124 | };
125 | 13899B591B36CF4C0060AD92 /* Supporting Files */ = {
126 | isa = PBXGroup;
127 | children = (
128 | 13899B5A1B36CF4C0060AD92 /* Info.plist */,
129 | );
130 | name = "Supporting Files";
131 | sourceTree = "";
132 | };
133 | /* End PBXGroup section */
134 |
135 | /* Begin PBXNativeTarget section */
136 | 13899B3B1B36CF4B0060AD92 /* ZFPlotChart */ = {
137 | isa = PBXNativeTarget;
138 | buildConfigurationList = 13899B5F1B36CF4C0060AD92 /* Build configuration list for PBXNativeTarget "ZFPlotChart" */;
139 | buildPhases = (
140 | 13899B381B36CF4B0060AD92 /* Sources */,
141 | 13899B391B36CF4B0060AD92 /* Frameworks */,
142 | 13899B3A1B36CF4B0060AD92 /* Resources */,
143 | );
144 | buildRules = (
145 | );
146 | dependencies = (
147 | );
148 | name = ZFPlotChart;
149 | productName = ZFPlotChart;
150 | productReference = 13899B3C1B36CF4B0060AD92 /* ZFPlotChart.app */;
151 | productType = "com.apple.product-type.application";
152 | };
153 | 13899B541B36CF4B0060AD92 /* ZFPlotChartTests */ = {
154 | isa = PBXNativeTarget;
155 | buildConfigurationList = 13899B621B36CF4C0060AD92 /* Build configuration list for PBXNativeTarget "ZFPlotChartTests" */;
156 | buildPhases = (
157 | 13899B511B36CF4B0060AD92 /* Sources */,
158 | 13899B521B36CF4B0060AD92 /* Frameworks */,
159 | 13899B531B36CF4B0060AD92 /* Resources */,
160 | );
161 | buildRules = (
162 | );
163 | dependencies = (
164 | 13899B571B36CF4B0060AD92 /* PBXTargetDependency */,
165 | );
166 | name = ZFPlotChartTests;
167 | productName = ZFPlotChartTests;
168 | productReference = 13899B551B36CF4B0060AD92 /* ZFPlotChartTests.xctest */;
169 | productType = "com.apple.product-type.bundle.unit-test";
170 | };
171 | /* End PBXNativeTarget section */
172 |
173 | /* Begin PBXProject section */
174 | 13899B341B36CF4B0060AD92 /* Project object */ = {
175 | isa = PBXProject;
176 | attributes = {
177 | LastUpgradeCheck = 0630;
178 | ORGANIZATIONNAME = "Francesco Zerbinati";
179 | TargetAttributes = {
180 | 13899B3B1B36CF4B0060AD92 = {
181 | CreatedOnToolsVersion = 6.3.2;
182 | };
183 | 13899B541B36CF4B0060AD92 = {
184 | CreatedOnToolsVersion = 6.3.2;
185 | TestTargetID = 13899B3B1B36CF4B0060AD92;
186 | };
187 | };
188 | };
189 | buildConfigurationList = 13899B371B36CF4B0060AD92 /* Build configuration list for PBXProject "ZFPlotChart" */;
190 | compatibilityVersion = "Xcode 3.2";
191 | developmentRegion = English;
192 | hasScannedForEncodings = 0;
193 | knownRegions = (
194 | en,
195 | Base,
196 | );
197 | mainGroup = 13899B331B36CF4B0060AD92;
198 | productRefGroup = 13899B3D1B36CF4B0060AD92 /* Products */;
199 | projectDirPath = "";
200 | projectRoot = "";
201 | targets = (
202 | 13899B3B1B36CF4B0060AD92 /* ZFPlotChart */,
203 | 13899B541B36CF4B0060AD92 /* ZFPlotChartTests */,
204 | );
205 | };
206 | /* End PBXProject section */
207 |
208 | /* Begin PBXResourcesBuildPhase section */
209 | 13899B3A1B36CF4B0060AD92 /* Resources */ = {
210 | isa = PBXResourcesBuildPhase;
211 | buildActionMask = 2147483647;
212 | files = (
213 | 13899B4B1B36CF4B0060AD92 /* Main.storyboard in Resources */,
214 | 13899B501B36CF4B0060AD92 /* LaunchScreen.xib in Resources */,
215 | 13899B4D1B36CF4B0060AD92 /* Images.xcassets in Resources */,
216 | 135A8D301B77A1E000CE017E /* data.json in Resources */,
217 | 135A8D3A1B77AAF300CE017E /* preview.png in Resources */,
218 | );
219 | runOnlyForDeploymentPostprocessing = 0;
220 | };
221 | 13899B531B36CF4B0060AD92 /* Resources */ = {
222 | isa = PBXResourcesBuildPhase;
223 | buildActionMask = 2147483647;
224 | files = (
225 | );
226 | runOnlyForDeploymentPostprocessing = 0;
227 | };
228 | /* End PBXResourcesBuildPhase section */
229 |
230 | /* Begin PBXSourcesBuildPhase section */
231 | 13899B381B36CF4B0060AD92 /* Sources */ = {
232 | isa = PBXSourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | 13899B481B36CF4B0060AD92 /* ViewController.m in Sources */,
236 | 13899B6A1B36CF820060AD92 /* ZFPlotChart.m in Sources */,
237 | 13899B451B36CF4B0060AD92 /* AppDelegate.m in Sources */,
238 | 13899B421B36CF4B0060AD92 /* main.m in Sources */,
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | };
242 | 13899B511B36CF4B0060AD92 /* Sources */ = {
243 | isa = PBXSourcesBuildPhase;
244 | buildActionMask = 2147483647;
245 | files = (
246 | 13899B5C1B36CF4C0060AD92 /* ZFPlotChartTests.m in Sources */,
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | };
250 | /* End PBXSourcesBuildPhase section */
251 |
252 | /* Begin PBXTargetDependency section */
253 | 13899B571B36CF4B0060AD92 /* PBXTargetDependency */ = {
254 | isa = PBXTargetDependency;
255 | target = 13899B3B1B36CF4B0060AD92 /* ZFPlotChart */;
256 | targetProxy = 13899B561B36CF4B0060AD92 /* PBXContainerItemProxy */;
257 | };
258 | /* End PBXTargetDependency section */
259 |
260 | /* Begin PBXVariantGroup section */
261 | 13899B491B36CF4B0060AD92 /* Main.storyboard */ = {
262 | isa = PBXVariantGroup;
263 | children = (
264 | 13899B4A1B36CF4B0060AD92 /* Base */,
265 | );
266 | name = Main.storyboard;
267 | sourceTree = "";
268 | };
269 | 13899B4E1B36CF4B0060AD92 /* LaunchScreen.xib */ = {
270 | isa = PBXVariantGroup;
271 | children = (
272 | 13899B4F1B36CF4B0060AD92 /* Base */,
273 | );
274 | name = LaunchScreen.xib;
275 | sourceTree = "";
276 | };
277 | /* End PBXVariantGroup section */
278 |
279 | /* Begin XCBuildConfiguration section */
280 | 13899B5D1B36CF4C0060AD92 /* Debug */ = {
281 | isa = XCBuildConfiguration;
282 | buildSettings = {
283 | ALWAYS_SEARCH_USER_PATHS = NO;
284 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
285 | CLANG_CXX_LIBRARY = "libc++";
286 | CLANG_ENABLE_MODULES = YES;
287 | CLANG_ENABLE_OBJC_ARC = YES;
288 | CLANG_WARN_BOOL_CONVERSION = YES;
289 | CLANG_WARN_CONSTANT_CONVERSION = YES;
290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
291 | CLANG_WARN_EMPTY_BODY = YES;
292 | CLANG_WARN_ENUM_CONVERSION = YES;
293 | CLANG_WARN_INT_CONVERSION = YES;
294 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
295 | CLANG_WARN_UNREACHABLE_CODE = YES;
296 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
297 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
298 | COPY_PHASE_STRIP = NO;
299 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
300 | ENABLE_STRICT_OBJC_MSGSEND = YES;
301 | GCC_C_LANGUAGE_STANDARD = gnu99;
302 | GCC_DYNAMIC_NO_PIC = NO;
303 | GCC_NO_COMMON_BLOCKS = YES;
304 | GCC_OPTIMIZATION_LEVEL = 0;
305 | GCC_PREPROCESSOR_DEFINITIONS = (
306 | "DEBUG=1",
307 | "$(inherited)",
308 | );
309 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
310 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
311 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
312 | GCC_WARN_UNDECLARED_SELECTOR = YES;
313 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
314 | GCC_WARN_UNUSED_FUNCTION = YES;
315 | GCC_WARN_UNUSED_VARIABLE = YES;
316 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
317 | MTL_ENABLE_DEBUG_INFO = YES;
318 | ONLY_ACTIVE_ARCH = YES;
319 | SDKROOT = iphoneos;
320 | TARGETED_DEVICE_FAMILY = "1,2";
321 | };
322 | name = Debug;
323 | };
324 | 13899B5E1B36CF4C0060AD92 /* Release */ = {
325 | isa = XCBuildConfiguration;
326 | buildSettings = {
327 | ALWAYS_SEARCH_USER_PATHS = NO;
328 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
329 | CLANG_CXX_LIBRARY = "libc++";
330 | CLANG_ENABLE_MODULES = YES;
331 | CLANG_ENABLE_OBJC_ARC = YES;
332 | CLANG_WARN_BOOL_CONVERSION = YES;
333 | CLANG_WARN_CONSTANT_CONVERSION = YES;
334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
335 | CLANG_WARN_EMPTY_BODY = YES;
336 | CLANG_WARN_ENUM_CONVERSION = YES;
337 | CLANG_WARN_INT_CONVERSION = YES;
338 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
339 | CLANG_WARN_UNREACHABLE_CODE = YES;
340 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
341 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
342 | COPY_PHASE_STRIP = NO;
343 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
344 | ENABLE_NS_ASSERTIONS = NO;
345 | ENABLE_STRICT_OBJC_MSGSEND = YES;
346 | GCC_C_LANGUAGE_STANDARD = gnu99;
347 | GCC_NO_COMMON_BLOCKS = YES;
348 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
349 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
350 | GCC_WARN_UNDECLARED_SELECTOR = YES;
351 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
352 | GCC_WARN_UNUSED_FUNCTION = YES;
353 | GCC_WARN_UNUSED_VARIABLE = YES;
354 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
355 | MTL_ENABLE_DEBUG_INFO = NO;
356 | SDKROOT = iphoneos;
357 | TARGETED_DEVICE_FAMILY = "1,2";
358 | VALIDATE_PRODUCT = YES;
359 | };
360 | name = Release;
361 | };
362 | 13899B601B36CF4C0060AD92 /* Debug */ = {
363 | isa = XCBuildConfiguration;
364 | buildSettings = {
365 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
366 | INFOPLIST_FILE = ZFPlotChart/Info.plist;
367 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
368 | PRODUCT_NAME = "$(TARGET_NAME)";
369 | };
370 | name = Debug;
371 | };
372 | 13899B611B36CF4C0060AD92 /* Release */ = {
373 | isa = XCBuildConfiguration;
374 | buildSettings = {
375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
376 | INFOPLIST_FILE = ZFPlotChart/Info.plist;
377 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
378 | PRODUCT_NAME = "$(TARGET_NAME)";
379 | };
380 | name = Release;
381 | };
382 | 13899B631B36CF4C0060AD92 /* Debug */ = {
383 | isa = XCBuildConfiguration;
384 | buildSettings = {
385 | BUNDLE_LOADER = "$(TEST_HOST)";
386 | FRAMEWORK_SEARCH_PATHS = (
387 | "$(SDKROOT)/Developer/Library/Frameworks",
388 | "$(inherited)",
389 | );
390 | GCC_PREPROCESSOR_DEFINITIONS = (
391 | "DEBUG=1",
392 | "$(inherited)",
393 | );
394 | INFOPLIST_FILE = ZFPlotChartTests/Info.plist;
395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
396 | PRODUCT_NAME = "$(TARGET_NAME)";
397 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZFPlotChart.app/ZFPlotChart";
398 | };
399 | name = Debug;
400 | };
401 | 13899B641B36CF4C0060AD92 /* Release */ = {
402 | isa = XCBuildConfiguration;
403 | buildSettings = {
404 | BUNDLE_LOADER = "$(TEST_HOST)";
405 | FRAMEWORK_SEARCH_PATHS = (
406 | "$(SDKROOT)/Developer/Library/Frameworks",
407 | "$(inherited)",
408 | );
409 | INFOPLIST_FILE = ZFPlotChartTests/Info.plist;
410 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
411 | PRODUCT_NAME = "$(TARGET_NAME)";
412 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ZFPlotChart.app/ZFPlotChart";
413 | };
414 | name = Release;
415 | };
416 | /* End XCBuildConfiguration section */
417 |
418 | /* Begin XCConfigurationList section */
419 | 13899B371B36CF4B0060AD92 /* Build configuration list for PBXProject "ZFPlotChart" */ = {
420 | isa = XCConfigurationList;
421 | buildConfigurations = (
422 | 13899B5D1B36CF4C0060AD92 /* Debug */,
423 | 13899B5E1B36CF4C0060AD92 /* Release */,
424 | );
425 | defaultConfigurationIsVisible = 0;
426 | defaultConfigurationName = Release;
427 | };
428 | 13899B5F1B36CF4C0060AD92 /* Build configuration list for PBXNativeTarget "ZFPlotChart" */ = {
429 | isa = XCConfigurationList;
430 | buildConfigurations = (
431 | 13899B601B36CF4C0060AD92 /* Debug */,
432 | 13899B611B36CF4C0060AD92 /* Release */,
433 | );
434 | defaultConfigurationIsVisible = 0;
435 | defaultConfigurationName = Release;
436 | };
437 | 13899B621B36CF4C0060AD92 /* Build configuration list for PBXNativeTarget "ZFPlotChartTests" */ = {
438 | isa = XCConfigurationList;
439 | buildConfigurations = (
440 | 13899B631B36CF4C0060AD92 /* Debug */,
441 | 13899B641B36CF4C0060AD92 /* Release */,
442 | );
443 | defaultConfigurationIsVisible = 0;
444 | defaultConfigurationName = Release;
445 | };
446 | /* End XCConfigurationList section */
447 | };
448 | rootObject = 13899B341B36CF4B0060AD92 /* Project object */;
449 | }
450 |
--------------------------------------------------------------------------------
/ZFPlotChart/ZFPlotChart.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZFPlotChart.m
3 | //
4 | // Created by Zerbinati Francesco
5 | // Copyright (c) 2014-2015
6 | //
7 |
8 | #import "ZFPlotChart.h"
9 |
10 | @implementation ZFPlotChart
11 |
12 | @synthesize dictDispPoint;
13 | @synthesize chartWidth, chartHeight;
14 |
15 | @synthesize prevPoint, curPoint, currentLoc;
16 | @synthesize min, max;
17 |
18 |
19 | #pragma mark - Initialization/LifeCycle Method
20 | - (id)initWithFrame:(CGRect)frame
21 | {
22 |
23 | self = [super initWithFrame:frame];
24 | if (self) {
25 | // Initialization code
26 | @try {
27 |
28 | [self setAutoresizingMask: UIViewAutoresizingFlexibleWidth];
29 | [self setAutoresizesSubviews:YES];
30 |
31 | self.backgroundColor = whiteColor;
32 |
33 |
34 |
35 | self.chartHeight = frame.size.height - vMargin;
36 | self.chartWidth = frame.size.width - hMargin;
37 |
38 |
39 | isMovement = NO;
40 |
41 | self.dictDispPoint = [[NSMutableOrderedSet alloc] initWithCapacity:0];
42 |
43 |
44 |
45 | }
46 | @catch (NSException *exception) {
47 | NSLog(@"%@",[exception debugDescription]);
48 | }
49 | @finally {
50 |
51 | }
52 | }
53 | return self;
54 | }
55 |
56 | #pragma mark - Chart Creation Method
57 | - (void)createChartWith:(NSOrderedSet *)data
58 | {
59 |
60 | [self.dictDispPoint removeAllObjects];
61 |
62 | NSMutableOrderedSet *orderSet = [[NSMutableOrderedSet alloc] initWithCapacity:0];
63 |
64 | // Add data to the orderSet
65 | [data enumerateObjectsUsingBlock:^(id obj, NSUInteger ind, BOOL *stop){
66 | [orderSet addObject:obj];
67 |
68 | }];
69 |
70 | // Find Min & Max of Chart
71 | self.max = [[[orderSet valueForKey:fzValue] valueForKeyPath:@"@max.floatValue"] floatValue];
72 | self.min = [[[orderSet valueForKey:fzValue] valueForKeyPath:@"@min.floatValue"] floatValue];
73 |
74 |
75 | // Enhance Upper & Lower Limit for Flexible Display, based on average of min and max
76 | self.max = ceilf((self.max+10 )/ 1000)*1000;
77 | self.min = floor((self.min-10)/1000)*1000;
78 |
79 | // Calculate left space given by the lenght of the string on the axis
80 | self.leftMargin = [self sizeOfString:[self formatNumberAsCurrency:self.max/100 withFractionDigits:0] withFont:systemFont].width + leftSpace;
81 |
82 | self.chartWidth-= self.leftMargin;
83 | float range = self.max-self.min;
84 |
85 | // Calculate deploying points for chart according to values
86 | float xGapBetweenTwoPoints = self.chartWidth/[orderSet count];
87 | float x , y;
88 |
89 |
90 | x = self.leftMargin;
91 | y = topMargin;
92 |
93 | self.yMax = 0;
94 |
95 | // assing points to values
96 | for(NSDictionary *dictionary in orderSet)
97 | {
98 | float priceValue = [[dictionary valueForKey:fzValue] floatValue];
99 |
100 | float diff = (self.max-priceValue);
101 |
102 | y = ((self.chartHeight)*diff)/range + topMargin;
103 |
104 | // calculate maximum y
105 | if(y > self.yMax) self.yMax = y;
106 |
107 | CGPoint point = CGPointMake(x,y);
108 |
109 | NSDictionary *dictPoint = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithCGPoint:point], fzPoint,
110 | [dictionary valueForKey:fzValue], fzValue,
111 | [dictionary valueForKey:fzDate], fzDate, nil];
112 |
113 | [self.dictDispPoint addObject:dictPoint];
114 |
115 | x+= xGapBetweenTwoPoints;
116 | }
117 |
118 | [self setNeedsDisplay];
119 |
120 | }
121 |
122 | #pragma mark - Drawing
123 | - (void)drawRect:(CGRect)rect
124 | {
125 | // Drawing code
126 | @try
127 | {
128 | if([self.dictDispPoint count] > 0)
129 | {
130 | // remove loading animation
131 | [self stopLoading];
132 |
133 | float range = self.max-self.min;
134 | float intervalHlines = (self.chartHeight)/5.0f;
135 | float intervalValues = range/5.0f;
136 |
137 | // horizontal lines
138 | for(int i=5;i>0;i--)
139 | {
140 | [self setContextWidth:0.5f andColor:linesColor];
141 |
142 | CGPoint start = CGPointMake(self.leftMargin, self.chartHeight+topMargin-i*intervalHlines);
143 | CGPoint end = CGPointMake(self.chartWidth+self.leftMargin, self.chartHeight+topMargin-i*intervalHlines);
144 |
145 | // draw the line
146 | [self drawLineFrom:start to:end];
147 |
148 | // draw prices on the axis
149 | NSString *prezzoAsse = [self formatNumberAsCurrency:(self.min+i*intervalValues)/100 withFractionDigits:0];
150 | CGPoint prezzoAssePoint = CGPointMake(self.leftMargin - [self sizeOfString:prezzoAsse withFont:systemFont].width - 5,(self.chartHeight+topMargin-i*intervalHlines-6));
151 |
152 | [self drawString:prezzoAsse at:prezzoAssePoint withFont:systemFont andColor:linesColor];
153 |
154 | [self endContext];
155 |
156 | }
157 |
158 | /*** Draw points ***/
159 | [self.dictDispPoint enumerateObjectsUsingBlock:^(id obj, NSUInteger ind, BOOL *stop){
160 | if(ind > 0)
161 | {
162 | self.prevPoint = [[[self.dictDispPoint objectAtIndex:ind-1] valueForKey:fzPoint] CGPointValue];
163 | self.curPoint = [[[self.dictDispPoint objectAtIndex:ind] valueForKey:fzPoint] CGPointValue];
164 | }
165 | else
166 | {
167 | // first point
168 | self.prevPoint = [[[self.dictDispPoint objectAtIndex:ind] valueForKey:fzPoint] CGPointValue];
169 | self.curPoint = self.prevPoint;
170 | }
171 |
172 | // line style
173 | [self setContextWidth:1.5f andColor:orangeColor];
174 |
175 | // draw the curve
176 | [self drawCurveFrom:self.prevPoint to:self.curPoint];
177 |
178 | [self endContext];
179 |
180 |
181 | long linesRatio;
182 |
183 | if([self.dictDispPoint count] < 4)
184 | linesRatio = [self.dictDispPoint count]/([self.dictDispPoint count]-1);
185 | else linesRatio = [self.dictDispPoint count]/4 ;
186 |
187 |
188 | if(ind%linesRatio == 0) {
189 |
190 | [self setContextWidth:0.5f andColor:linesColor];
191 |
192 | // Vertical Lines
193 | if(ind!=0) {
194 | CGPoint lower = CGPointMake(self.curPoint.x, topMargin+self.chartHeight);
195 | CGPoint higher = CGPointMake(self.curPoint.x, topMargin);
196 | [self drawLineFrom:lower to: higher];
197 |
198 | }
199 |
200 | [self endContext];
201 |
202 | // draw dates on the x axys
203 | NSString* date = [self dateFromString: [[self.dictDispPoint objectAtIndex:ind] valueForKey:fzDate]];
204 | CGPoint datePoint = CGPointMake(self.curPoint.x-15, topMargin + self.chartHeight + 2);
205 | [self drawString:date at:datePoint withFont:systemFont andColor:linesColor];
206 |
207 | [self endContext];
208 |
209 |
210 | }
211 |
212 | }];
213 |
214 | // gradient's path
215 | CGMutablePathRef path = CGPathCreateMutable();
216 |
217 | CGPoint origin = CGPointMake(self.leftMargin, topMargin+self.chartHeight);
218 | if (self.dictDispPoint && self.dictDispPoint.count > 0) {
219 |
220 | //origin
221 | CGPathMoveToPoint(path, nil, origin.x, origin.y);
222 | CGPoint p;
223 | for (int i = 0; i < self.dictDispPoint.count; i++) {
224 | p = [[[self.dictDispPoint objectAtIndex:i] valueForKey:fzPoint] CGPointValue];
225 | CGPathAddLineToPoint(path, nil, p.x, p.y);
226 | }
227 | }
228 | CGPathAddLineToPoint(path, nil, self.curPoint.x, topMargin+self.chartHeight);
229 | CGPathAddLineToPoint(path, nil, origin.x,origin.y);
230 |
231 | // gradient
232 | [self gradientizefromPoint:CGPointMake(0, self.yMax) toPoint:CGPointMake(0, topMargin+self.chartWidth) forPath:path];
233 |
234 | CGPathRelease(path);
235 |
236 |
237 | // X and Y axys
238 |
239 | [self setContextWidth:1.0f andColor:linesColor];
240 |
241 | // y
242 | [self drawLineFrom:CGPointMake(self.leftMargin, topMargin) to:CGPointMake(self.leftMargin, self.chartHeight+topMargin)];
243 | // x
244 | [self drawLineFrom:CGPointMake(self.leftMargin, topMargin+self.chartHeight) to:CGPointMake(self.leftMargin+self.chartWidth, self.chartHeight+topMargin)];
245 |
246 | // vertical closure
247 | CGPoint startLine = CGPointMake(self.leftMargin+self.chartWidth, topMargin);
248 | CGPoint endLine = CGPointMake(self.leftMargin+self.chartWidth, topMargin+self.chartHeight);
249 | [self drawLineFrom:startLine to:endLine];
250 |
251 | // horizontal closure
252 | [self drawLineFrom:CGPointMake(self.leftMargin, topMargin) to:CGPointMake(self.chartWidth+self.leftMargin, topMargin)];
253 |
254 |
255 | [self endContext];
256 |
257 |
258 | CGContextRef context = UIGraphicsGetCurrentContext();
259 |
260 |
261 | // popup when moving
262 | if(isMovement)
263 | {
264 | float xGapBetweenTwoPoints = self.chartWidth/[self.dictDispPoint count];
265 | int pointSlot = currentLoc.x/xGapBetweenTwoPoints;
266 |
267 | if(pointSlot >= 0 && pointSlot < [self.dictDispPoint count])
268 | {
269 | NSDictionary *dict = [self.dictDispPoint objectAtIndex:pointSlot];
270 |
271 | // Calculate Point to draw Circle
272 | CGPoint point = CGPointMake([[dict valueForKey:fzPoint] CGPointValue].x,[[dict valueForKey:fzPoint] CGPointValue].y);
273 |
274 |
275 | [self setContextWidth:1.0f andColor:orangeColor];
276 |
277 | // Line at current Point
278 | [self drawLineFrom:CGPointMake(point.x, topMargin-10) to:CGPointMake(point.x, self.chartHeight+topMargin)];
279 | [self endContext];
280 |
281 | // Circle at point
282 | [self setContextWidth:1.0f andColor:orangeColor];
283 | [self drawCircleAt:point ofRadius:8];
284 |
285 | [self endContext];
286 |
287 |
288 | // draw the dynamic value
289 |
290 | float value = [[dict objectForKey:fzValue] floatValue]/100;
291 | NSString *price = [self formatNumberAsCurrency:value withFractionDigits:2];
292 |
293 | CGSize priceSize = [self sizeOfString:price withFont:boldFont];
294 |
295 | CGRect priceRect = {point.x-priceSize.width/2, 2, priceSize.width + 10, priceSize.height +3};
296 |
297 | // if goes out on right
298 | if(point.x+-priceSize.width/2+priceSize.width+12 > self.chartWidth+self.leftMargin)
299 | priceRect.origin.x = self.chartWidth+self.leftMargin-priceSize.width-2;
300 | // if goes out on left
301 | if(priceRect.origin.x < self.leftMargin)
302 | priceRect.origin.x = self.leftMargin-(self.leftMargin/2);
303 |
304 | // rectangle for the label
305 | [self drawRoundedRect:context rect:priceRect radius:5 color:orangeColor];
306 | // value string
307 | [self drawString:price at:CGPointMake(priceRect.origin.x+(priceRect.size.width-priceSize.width)/2,priceRect.origin.y+1.0f) withFont:boldFont andColor:whiteColor];
308 |
309 |
310 |
311 | }
312 | }
313 | }
314 | else
315 | {
316 | // draw a loding spinner while loading the data
317 | [self drawLoading];
318 | }
319 | }
320 | @catch (NSException *exception) {
321 | NSLog(@"%@",[exception debugDescription]);
322 | }
323 | @finally {
324 |
325 | }
326 | }
327 |
328 |
329 |
330 |
331 | #pragma mark - Graphic Utilities
332 |
333 | -(void)drawLoading {
334 | self.loadingSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
335 | [self.loadingSpinner startAnimating];
336 |
337 | CGRect screenRect = [[UIScreen mainScreen] bounds];
338 | CGFloat screenWidth = screenRect.size.width;
339 |
340 | self.loadingSpinner.center = CGPointMake(screenWidth/2, self.frame.size.height/2);
341 | self.loadingSpinner.hidesWhenStopped = YES;
342 | [self addSubview:self.loadingSpinner];
343 | }
344 |
345 | -(void)stopLoading {
346 | [self.loadingSpinner stopAnimating];
347 | }
348 |
349 | -(void)gradientizefromPoint:(CGPoint) startPoint toPoint:(CGPoint) endPoint forPath:(CGMutablePathRef) path{
350 |
351 | CGContextRef context = UIGraphicsGetCurrentContext();
352 |
353 | CGFloat colors [] = {
354 | 245.0/255.0, 150.0/255.0, 10.0/255, 0.9, // orange
355 | 255.0/255.0,255.0/255.0,255.0/255.0, 0.0 // white clear
356 | };
357 |
358 |
359 |
360 | CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB(); // gray colors want gray color space
361 | CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
362 | CGColorSpaceRelease(baseSpace), baseSpace = NULL;
363 |
364 | CGContextSaveGState(context);
365 | CGContextAddPath(context, path);
366 | CGContextClip(context);
367 |
368 | CGRect boundingBox = CGPathGetBoundingBox(path);
369 | CGPoint gradientStart = CGPointMake(0, CGRectGetMinY(boundingBox));
370 | CGPoint gradientEnd = CGPointMake(0, CGRectGetMaxY(boundingBox));
371 |
372 | CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, 0);
373 | CGGradientRelease(gradient), gradient = NULL;
374 | CGContextRestoreGState(context);
375 |
376 |
377 |
378 |
379 | }
380 |
381 | -(void)drawMessage:(NSString*)string {
382 |
383 | float stringWidth = [self sizeOfString:string withFont:boldFont].width;
384 | [self drawString:string at:CGPointMake(self.center.x-stringWidth/2, self.center.y) withFont:boldFont andColor:linesColor];
385 | }
386 |
387 |
388 | // set the context with a specified widht and color
389 | -(void) setContextWidth:(float)width andColor:(UIColor*)color {
390 |
391 | CGContextRef context = UIGraphicsGetCurrentContext();
392 | CGContextSetLineWidth(context, width);
393 | CGContextSetFillColorWithColor(context, color.CGColor);
394 | CGContextSetStrokeColorWithColor(context, color.CGColor);
395 | }
396 | // end context
397 | -(void)endContext {
398 | CGContextRef context = UIGraphicsGetCurrentContext();
399 | CGContextStrokePath(context);
400 | }
401 | // line between two points
402 | -(void) drawLineFrom:(CGPoint) start to: (CGPoint)end {
403 | CGContextRef context = UIGraphicsGetCurrentContext();
404 | CGContextMoveToPoint(context, start.x, start.y);
405 | CGContextAddLineToPoint(context,end.x,end.y);
406 |
407 | }
408 | // curve between two points
409 | -(void) drawCurveFrom:(CGPoint)start to:(CGPoint)end {
410 | CGContextRef context = UIGraphicsGetCurrentContext();
411 | CGContextMoveToPoint(context, start.x, start.y);
412 | CGContextAddQuadCurveToPoint(context, start.x, start.y, end.x, end.y);
413 | CGContextSetLineCap(context, kCGLineCapRound);
414 | }
415 | // draws a string given a point, font and color
416 | -(void) drawString:(NSString*)string at:(CGPoint)point withFont:(UIFont*)font andColor:(UIColor*)color{
417 |
418 | NSDictionary *attributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: color};
419 |
420 | [string drawAtPoint:point withAttributes:attributes];
421 | }
422 | // draw a circle given center and radius
423 | -(void) drawCircleAt:(CGPoint)point ofRadius:(int)radius {
424 | CGContextRef context = UIGraphicsGetCurrentContext();
425 | CGRect myOval = {point.x-radius/2, point.y-radius/2, radius, radius};
426 | CGContextAddEllipseInRect(context, myOval);
427 | CGContextFillPath(context);
428 | }
429 | // rounded corners rectangle
430 | - (void) drawRoundedRect:(CGContextRef)c rect:(CGRect)rect radius:(int)corner_radius color:(UIColor *)color
431 | {
432 | int x_left = rect.origin.x;
433 | int x_left_center = rect.origin.x + corner_radius;
434 | int x_right_center = rect.origin.x + rect.size.width - corner_radius;
435 | int x_right = rect.origin.x + rect.size.width;
436 |
437 | int y_top = rect.origin.y;
438 | int y_top_center = rect.origin.y + corner_radius;
439 | int y_bottom_center = rect.origin.y + rect.size.height - corner_radius;
440 | int y_bottom = rect.origin.y + rect.size.height;
441 |
442 | /* Begin! */
443 | CGContextBeginPath(c);
444 | CGContextMoveToPoint(c, x_left, y_top_center);
445 |
446 | /* First corner */
447 | CGContextAddArcToPoint(c, x_left, y_top, x_left_center, y_top, corner_radius);
448 | CGContextAddLineToPoint(c, x_right_center, y_top);
449 |
450 | /* Second corner */
451 | CGContextAddArcToPoint(c, x_right, y_top, x_right, y_top_center, corner_radius);
452 | CGContextAddLineToPoint(c, x_right, y_bottom_center);
453 |
454 | /* Third corner */
455 | CGContextAddArcToPoint(c, x_right, y_bottom, x_right_center, y_bottom, corner_radius);
456 | CGContextAddLineToPoint(c, x_left_center, y_bottom);
457 |
458 | /* Fourth corner */
459 | CGContextAddArcToPoint(c, x_left, y_bottom, x_left, y_bottom_center, corner_radius);
460 | CGContextAddLineToPoint(c, x_left, y_top_center);
461 |
462 | /* Done */
463 | CGContextClosePath(c);
464 |
465 | CGContextSetFillColorWithColor(c, color.CGColor);
466 |
467 | CGContextFillPath(c);
468 | }
469 | // size of a string given a specific font
470 | -(CGSize) sizeOfString:(NSString *)string withFont:(UIFont *)font {
471 | NSDictionary *attributes = @{ NSFontAttributeName: font};
472 | return [string sizeWithAttributes:attributes];
473 | }
474 |
475 | #pragma mark - String utilities
476 |
477 | // format a string as a date (italian convention)
478 | -(NSString*) dateFromString:(NSString*) string {
479 |
480 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
481 | [dateFormatter setDateFormat:fzDateFormat];
482 | NSDate *dateFromString = [dateFormatter dateFromString:string];
483 |
484 |
485 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
486 | [formatter setDateStyle:NSDateFormatterShortStyle];
487 | [formatter setTimeStyle:NSDateFormatterNoStyle];
488 | [formatter setLocale:[NSLocale currentLocale]];
489 | NSString *format = [formatter dateFormat];
490 | format = [format stringByReplacingOccurrencesOfString:@"/y" withString:@""];
491 | format = [format stringByReplacingOccurrencesOfString:@"y/" withString:@""];
492 | format = [format stringByReplacingOccurrencesOfString:@"y" withString:@""];
493 |
494 | [formatter setDateFormat:format];
495 |
496 | NSString *printDate = [formatter stringFromDate:dateFromString];
497 |
498 | return printDate;
499 | }
500 |
501 |
502 | #pragma mark - Handle Touch Events
503 |
504 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
505 | {
506 | [[NSNotificationCenter defaultCenter] postNotificationName:@"disableScrolling" object:nil];
507 |
508 | UITouch *touch = [touches anyObject];
509 | currentLoc = [touch locationInView:self];
510 | currentLoc.x -= self.leftMargin;
511 | isMovement = YES;
512 |
513 | [self setNeedsDisplay];
514 | }
515 |
516 | -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
517 | {
518 | UITouch *touch = [touches anyObject];
519 | currentLoc = [touch locationInView:self];
520 | currentLoc.x -= self.leftMargin;
521 | [self setNeedsDisplay];
522 | }
523 |
524 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
525 | {
526 | [[NSNotificationCenter defaultCenter] postNotificationName:@"enableScrolling" object:nil];
527 |
528 | UITouch *touch = [touches anyObject];
529 | currentLoc = [touch locationInView:self];
530 | currentLoc.x -= self.leftMargin;
531 |
532 | isMovement = NO;
533 | [self setNeedsDisplay];
534 | }
535 |
536 |
537 | -(NSString*)formatNumberAsCurrency:(float)number withFractionDigits: (int)digits {
538 |
539 | NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
540 | [currencyFormatter setCurrencyCode:@"EUR"];
541 | [currencyFormatter setLocale: [[NSLocale alloc] initWithLocaleIdentifier:@"EUR"]];
542 | [currencyFormatter setMaximumFractionDigits:digits];
543 | [currencyFormatter setMinimumFractionDigits:digits];
544 | //[currencyFormatter setAlwaysShowsDecimalSeparator:YES];
545 | [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
546 | NSString *numberAsString = [currencyFormatter stringFromNumber:[NSNumber numberWithFloat:number]];
547 |
548 | return numberAsString;
549 | }
550 |
551 |
552 | @end
--------------------------------------------------------------------------------