Commit cedcb87d8a4e170d8cb99ebeea59e5b739d6a220
1 parent
2bab9a9ab1
Exists in
master
and in
1 other branch
update MAP screen and update api get new token, api create log step
Showing 6 changed files with 433 additions and 29 deletions Side-by-side Diff
LifeLog/LifeLog/HomeViewController.m
... | ... | @@ -235,20 +235,23 @@ |
235 | 235 | // NSLog(@"%@", activityExtra.activity.startDate); |
236 | 236 | [weakSelf.pedometer queryPedometerDataFromDate:activityExtra.activity.startDate toDate:activityExtra.endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { |
237 | 237 | NSInteger numberStep = [pedometerData.numberOfSteps integerValue]; |
238 | - | |
238 | + int mode = 1; | |
239 | 239 | if (activityExtra.activity.cycling) { |
240 | 240 | // self.bike |
241 | 241 | weakSelf.bike += numberStep; |
242 | 242 | //NSLog(@"Step cycling"); |
243 | + mode = 3; | |
243 | 244 | } |
244 | 245 | else if (activityExtra.activity.walking) { |
245 | 246 | // self.walking |
246 | 247 | weakSelf.walking += numberStep; |
247 | 248 | //NSLog(@"Step walking"); |
249 | + mode = 1; | |
248 | 250 | } |
249 | 251 | else if (activityExtra.activity.running) { |
250 | 252 | weakSelf.running += numberStep; |
251 | 253 | //NSLog(@"Step running"); |
254 | + mode = 2; | |
252 | 255 | } |
253 | 256 | else { |
254 | 257 | // unknown |
... | ... | @@ -256,6 +259,19 @@ |
256 | 259 | } |
257 | 260 | // NSLog(@"Number of step--> %ld", numberStep); |
258 | 261 | weakSelf.countComplete += 1; |
262 | + | |
263 | + // save step to server | |
264 | + if (numberStep > 0) { | |
265 | + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; | |
266 | + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; | |
267 | + NSString *dateBegin = [dateFormatter stringFromDate:activityExtra.activity.startDate]; | |
268 | + NSString *dateEnd = [dateFormatter stringFromDate:activityExtra.endDate]; | |
269 | + [[ServerAPI server] requestCreateLog:mode withStep:(int)numberStep startDate:dateBegin endDate:dateEnd CompletionHandler:^(NSError *error) { | |
270 | + if (error) { | |
271 | + NSLog(@"Error: %@", error); | |
272 | + } | |
273 | + }]; | |
274 | + } | |
259 | 275 | dispatch_async(dispatch_get_main_queue(), ^{ |
260 | 276 | [weakSelf updateStepUI]; |
261 | 277 | }); |
LifeLog/LifeLog/Info.plist
... | ... | @@ -60,6 +60,10 @@ |
60 | 60 | </array> |
61 | 61 | <key>UIViewControllerBasedStatusBarAppearance</key> |
62 | 62 | <false/> |
63 | + <key>NSLocationWhenInUseUsageDescription</key> | |
64 | + <string>This application requires location services to work</string> | |
65 | + <key>NSLocationAlwaysUsageDescription</key> | |
66 | + <string>This application requires location services to work</string> | |
63 | 67 | </dict> |
64 | 68 | </plist> |
LifeLog/LifeLog/MapViewController.m
... | ... | @@ -7,9 +7,33 @@ |
7 | 7 | // |
8 | 8 | |
9 | 9 | #import "MapViewController.h" |
10 | +#import <MapKit/MapKit.h> | |
11 | +#import<CoreLocation/CoreLocation.h> | |
12 | +#import <CoreMotion/CoreMotion.h> | |
13 | +#import "NSDate+helper.h" | |
14 | +#import "Utilities.h" | |
10 | 15 | |
11 | -@interface MapViewController () | |
16 | +@interface MapViewController ()<CLLocationManagerDelegate, MKMapViewDelegate> | |
17 | +{ | |
18 | + CLGeocoder *geocoder; | |
19 | + CLPlacemark *placemark; | |
20 | + CLLocation *previousLocation; | |
21 | +} | |
22 | +@property (weak, nonatomic) IBOutlet MKMapView *mapView; | |
23 | +@property (weak, nonatomic) IBOutlet UILabel *lblTime; | |
24 | +@property (weak, nonatomic) IBOutlet UISlider *slider; | |
12 | 25 | |
26 | +@property (nonatomic, weak) IBOutlet UILabel *lblValueStep; | |
27 | +@property (nonatomic, weak) IBOutlet UILabel *lblUnitStep; | |
28 | + | |
29 | +@property (strong, nonatomic) CLLocationManager *locationManager; | |
30 | + | |
31 | +@property (nonatomic, strong) CMPedometer *pedometer; | |
32 | +@property (nonatomic, strong) CMMotionActivityManager *motionActivityManager; | |
33 | +@property (nonatomic, strong) NSOperationQueue *operationQueue; | |
34 | +@property (nonatomic, strong) NSTimer *timer; | |
35 | +@property (nonatomic) int countTime; | |
36 | +@property (nonatomic, assign) BOOL isRequesting; | |
13 | 37 | @end |
14 | 38 | |
15 | 39 | @implementation MapViewController |
16 | 40 | |
... | ... | @@ -18,11 +42,153 @@ |
18 | 42 | [super viewDidLoad]; |
19 | 43 | // Do any additional setup after loading the view from its nib. |
20 | 44 | self.title = NSLocalizedString(@"lifelog.tapbar.map", nil); |
45 | + [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.mapView attribute:NSLayoutAttributeTop multiplier:1 constant:0]]; | |
46 | + geocoder = [[CLGeocoder alloc] init]; | |
47 | + [self setupLocation]; | |
48 | + [self setupMapView]; | |
49 | + previousLocation = nil; | |
50 | + | |
51 | + if ([CMPedometer isStepCountingAvailable]) { | |
52 | + _pedometer = [[CMPedometer alloc] init]; | |
53 | + } | |
54 | + if ([CMMotionActivityManager isActivityAvailable]) { | |
55 | + _motionActivityManager = [[CMMotionActivityManager alloc] init]; | |
56 | + } | |
57 | + self.isRequesting = NO; | |
58 | + _countTime = 0; | |
59 | + self.lblUnitStep.text = NSLocalizedString(@"lifelog.home.unit.step", nil); | |
21 | 60 | } |
22 | 61 | |
23 | 62 | - (void)didReceiveMemoryWarning { |
24 | 63 | [super didReceiveMemoryWarning]; |
25 | 64 | // Dispose of any resources that can be recreated. |
65 | +} | |
66 | + | |
67 | +- (void)viewWillAppear:(BOOL)animated { | |
68 | + [super viewWillAppear:animated]; | |
69 | + _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(countStep) userInfo:nil repeats:YES]; | |
70 | + [_timer fire]; | |
71 | +} | |
72 | + | |
73 | +- (void)viewWillDisappear:(BOOL)animated { | |
74 | + [super viewWillDisappear:animated]; | |
75 | + [_timer invalidate]; | |
76 | +} | |
77 | + | |
78 | +#pragma mark - CLLocationManagerDelegate | |
79 | +-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { | |
80 | + | |
81 | + CLLocation *newLocation = [locations lastObject]; | |
82 | + if (previousLocation == nil) { | |
83 | + [self addAnnotationsOnMap:newLocation]; | |
84 | + } | |
85 | + else { | |
86 | + CLLocationCoordinate2D area[2]; | |
87 | + area[0] = previousLocation.coordinate; | |
88 | + area[1] = newLocation.coordinate; | |
89 | + MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:area count:2]; | |
90 | + [_mapView addOverlay:polyLine]; | |
91 | + } | |
92 | + | |
93 | + previousLocation = newLocation; | |
94 | +} | |
95 | + | |
96 | +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error | |
97 | +{ | |
98 | + NSLog(@"Cannot find the location."); | |
99 | +} | |
100 | + | |
101 | +#pragma mark - MKMapViewDelegate | |
102 | +- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay | |
103 | +{ | |
104 | + if ([overlay isKindOfClass:[MKPolyline class]]) { | |
105 | + MKPolylineRenderer *pr = [[MKPolylineRenderer alloc] initWithOverlay:overlay]; | |
106 | + pr.strokeColor = [UIColor redColor]; | |
107 | + pr.lineWidth = 5; | |
108 | + return pr; | |
109 | + } | |
110 | + return nil; | |
111 | +} | |
112 | + | |
113 | +#pragma mark - Functions Private | |
114 | + | |
115 | +- (void)addAnnotationsOnMap:(CLLocation *)locationToPoint { | |
116 | + MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; | |
117 | + annotation.coordinate = locationToPoint.coordinate; | |
118 | + [geocoder reverseGeocodeLocation:locationToPoint completionHandler:^(NSArray *placemarks, NSError *error) { | |
119 | + if (error == nil && [placemarks count] >0) { | |
120 | + placemark = [placemarks firstObject]; | |
121 | + NSDictionary *addressDict = placemark.addressDictionary; | |
122 | + annotation.title = [NSString stringWithFormat:@"%@", addressDict[@"Name"]]; | |
123 | + [_mapView addAnnotation:annotation]; | |
124 | + } | |
125 | + }]; | |
126 | +} | |
127 | + | |
128 | +- (void)setupLocation { | |
129 | + _locationManager = [[CLLocationManager alloc] init]; | |
130 | + _locationManager.desiredAccuracy = kCLLocationAccuracyBest; | |
131 | + _locationManager.delegate = self; | |
132 | + CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; | |
133 | + if (status == kCLAuthorizationStatusNotDetermined || status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusAuthorizedWhenInUse) { | |
134 | + [_locationManager requestWhenInUseAuthorization]; | |
135 | + [_locationManager requestAlwaysAuthorization]; | |
136 | + } | |
137 | + [_locationManager startUpdatingLocation]; | |
138 | + [_locationManager startUpdatingHeading]; | |
139 | +} | |
140 | + | |
141 | +- (void)setupMapView { | |
142 | + _mapView.delegate = self; | |
143 | + _mapView.showsUserLocation = YES; | |
144 | + _mapView.mapType = MKMapTypeStandard; | |
145 | + _mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading; | |
146 | +} | |
147 | + | |
148 | +#pragma mark - Functions Private | |
149 | +- (void)countStep | |
150 | +{ | |
151 | + _countTime++; | |
152 | + _lblTime.text = [self convertTime:_countTime]; | |
153 | + _slider.value = _countTime; | |
154 | + if (self.isRequesting == YES) { | |
155 | + return; | |
156 | + } | |
157 | + if ([CMMotionActivityManager isActivityAvailable]) { | |
158 | + self.isRequesting = YES; | |
159 | + NSDate *endDate = [NSDate date]; | |
160 | + NSDate *startDate = [endDate beginningAtMidnightOfDay]; | |
161 | + MapViewController __weak *weakSelf = self; | |
162 | + dispatch_queue_t myQueue = dispatch_queue_create("mobileworld.jp.lifelog", NULL); | |
163 | + dispatch_async(myQueue, ^{ | |
164 | + if (weakSelf == nil) { | |
165 | + return ; | |
166 | + } | |
167 | + [weakSelf.pedometer queryPedometerDataFromDate:startDate toDate:endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { | |
168 | + NSInteger numberStep = [pedometerData.numberOfSteps integerValue]; | |
169 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
170 | + [weakSelf updateStepUI:numberStep]; | |
171 | + }); | |
172 | + }]; | |
173 | + }); | |
174 | + } | |
175 | +} | |
176 | + | |
177 | +- (NSString *)convertTime:(int)time | |
178 | +{ | |
179 | + NSString *result = @""; | |
180 | + int hour = time/3600; | |
181 | + int minute = time/60; | |
182 | + int second = time % 60; | |
183 | + result = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second]; | |
184 | + return result; | |
185 | +} | |
186 | + | |
187 | +- (void)updateStepUI:(NSInteger)numberStep | |
188 | +{ | |
189 | + // NSLog(@"Number of step: %ld", numberStep); | |
190 | + self.isRequesting = NO; | |
191 | + self.lblValueStep.text = [Utilities addCommaFromNumber:numberStep]; | |
26 | 192 | } |
27 | 193 | |
28 | 194 | @end |
LifeLog/LifeLog/MapViewController.xib
1 | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> | |
2 | +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> | |
3 | 3 | <device id="retina4_7" orientation="portrait"> |
4 | 4 | <adaptation id="fullscreen"/> |
5 | 5 | </device> |
6 | 6 | <dependencies> |
7 | - <deployment identifier="iOS"/> | |
8 | 7 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> |
9 | 8 | <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
10 | 9 | </dependencies> |
11 | 10 | <objects> |
12 | 11 | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MapViewController"> |
13 | 12 | <connections> |
13 | + <outlet property="lblTime" destination="EMF-vR-v3k" id="nRs-ga-YjW"/> | |
14 | + <outlet property="lblUnitStep" destination="bSt-HN-qcq" id="opK-5F-PG8"/> | |
15 | + <outlet property="lblValueStep" destination="qLg-XF-Dyf" id="lvl-yi-U7d"/> | |
16 | + <outlet property="mapView" destination="GCl-mf-CD8" id="SpU-ML-EIf"/> | |
17 | + <outlet property="slider" destination="79Q-XB-cW2" id="NXm-rp-Ycy"/> | |
14 | 18 | <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> |
15 | 19 | </connections> |
16 | 20 | </placeholder> |
... | ... | @@ -18,7 +22,89 @@ |
18 | 22 | <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> |
19 | 23 | <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> |
20 | 24 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
21 | - <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |
25 | + <subviews> | |
26 | + <mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="GCl-mf-CD8"> | |
27 | + <rect key="frame" x="0.0" y="0.0" width="375" height="579"/> | |
28 | + <connections> | |
29 | + <outlet property="delegate" destination="-1" id="fjQ-MR-pO8"/> | |
30 | + </connections> | |
31 | + </mapView> | |
32 | + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qLg-XF-Dyf" userLabel="valueStep"> | |
33 | + <rect key="frame" x="20" y="531" width="275" height="40"/> | |
34 | + <constraints> | |
35 | + <constraint firstAttribute="height" constant="40" id="uDh-v6-rG3"/> | |
36 | + </constraints> | |
37 | + <fontDescription key="fontDescription" type="system" pointSize="45"/> | |
38 | + <color key="textColor" red="0.047200520830000002" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> | |
39 | + <nil key="highlightedColor"/> | |
40 | + </label> | |
41 | + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="step" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bSt-HN-qcq" userLabel="unitStep"> | |
42 | + <rect key="frame" x="305" y="541" width="50" height="30"/> | |
43 | + <constraints> | |
44 | + <constraint firstAttribute="height" constant="30" id="CNj-tm-yOG"/> | |
45 | + <constraint firstAttribute="width" constant="50" id="fac-mE-Hfh"/> | |
46 | + </constraints> | |
47 | + <fontDescription key="fontDescription" type="system" pointSize="25"/> | |
48 | + <color key="textColor" red="0.047200520830000002" green="1" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> | |
49 | + <nil key="highlightedColor"/> | |
50 | + </label> | |
51 | + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ayh-Y4-2QM" userLabel="ViewOther"> | |
52 | + <rect key="frame" x="0.0" y="579" width="375" height="44"/> | |
53 | + <subviews> | |
54 | + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TIME LINE" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ibI-Db-Rc6"> | |
55 | + <rect key="frame" x="8" y="0.0" width="90" height="44"/> | |
56 | + <constraints> | |
57 | + <constraint firstAttribute="width" constant="90" id="Lof-Td-i7Y"/> | |
58 | + </constraints> | |
59 | + <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/> | |
60 | + <nil key="textColor"/> | |
61 | + <nil key="highlightedColor"/> | |
62 | + </label> | |
63 | + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="12:05:01" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EMF-vR-v3k"> | |
64 | + <rect key="frame" x="106" y="0.0" width="80" height="44"/> | |
65 | + <constraints> | |
66 | + <constraint firstAttribute="width" constant="80" id="57B-fF-bdc"/> | |
67 | + </constraints> | |
68 | + <fontDescription key="fontDescription" type="system" pointSize="17"/> | |
69 | + <nil key="textColor"/> | |
70 | + <nil key="highlightedColor"/> | |
71 | + </label> | |
72 | + <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="86400" translatesAutoresizingMaskIntoConstraints="NO" id="79Q-XB-cW2"> | |
73 | + <rect key="frame" x="192" y="7" width="177" height="31"/> | |
74 | + </slider> | |
75 | + </subviews> | |
76 | + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> | |
77 | + <constraints> | |
78 | + <constraint firstItem="79Q-XB-cW2" firstAttribute="leading" secondItem="EMF-vR-v3k" secondAttribute="trailing" constant="8" id="0a0-t9-1tR"/> | |
79 | + <constraint firstItem="EMF-vR-v3k" firstAttribute="leading" secondItem="ibI-Db-Rc6" secondAttribute="trailing" constant="8" id="1a3-pA-ato"/> | |
80 | + <constraint firstAttribute="bottom" secondItem="79Q-XB-cW2" secondAttribute="bottom" constant="7" id="3l2-mK-se7"/> | |
81 | + <constraint firstItem="79Q-XB-cW2" firstAttribute="top" secondItem="ayh-Y4-2QM" secondAttribute="top" constant="7" id="6uV-xl-zpg"/> | |
82 | + <constraint firstAttribute="bottom" secondItem="EMF-vR-v3k" secondAttribute="bottom" id="7AD-qZ-VE4"/> | |
83 | + <constraint firstItem="EMF-vR-v3k" firstAttribute="top" secondItem="ayh-Y4-2QM" secondAttribute="top" id="B8d-wr-H0p"/> | |
84 | + <constraint firstAttribute="height" constant="44" id="G4K-Ic-5xS"/> | |
85 | + <constraint firstItem="ibI-Db-Rc6" firstAttribute="leading" secondItem="ayh-Y4-2QM" secondAttribute="leading" constant="8" id="NC8-xC-nBM"/> | |
86 | + <constraint firstAttribute="bottom" secondItem="ibI-Db-Rc6" secondAttribute="bottom" id="TKv-6Y-DHi"/> | |
87 | + <constraint firstAttribute="trailing" secondItem="79Q-XB-cW2" secondAttribute="trailing" constant="8" id="bzZ-US-1Hm"/> | |
88 | + <constraint firstItem="ibI-Db-Rc6" firstAttribute="top" secondItem="ayh-Y4-2QM" secondAttribute="top" id="lyI-MR-Y5S"/> | |
89 | + </constraints> | |
90 | + </view> | |
91 | + </subviews> | |
92 | + <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/> | |
93 | + <constraints> | |
94 | + <constraint firstAttribute="bottom" secondItem="GCl-mf-CD8" secondAttribute="bottom" constant="88" id="8R5-IL-ZOZ"/> | |
95 | + <constraint firstItem="ayh-Y4-2QM" firstAttribute="top" secondItem="qLg-XF-Dyf" secondAttribute="bottom" constant="8" id="CCW-El-IlM"/> | |
96 | + <constraint firstAttribute="trailing" secondItem="bSt-HN-qcq" secondAttribute="trailing" constant="20" id="GmG-Qy-kpO"/> | |
97 | + <constraint firstAttribute="trailing" secondItem="ayh-Y4-2QM" secondAttribute="trailing" id="Mwo-O6-jk0"/> | |
98 | + <constraint firstAttribute="trailing" secondItem="GCl-mf-CD8" secondAttribute="trailing" id="PwQ-mm-AeM"/> | |
99 | + <constraint firstItem="GCl-mf-CD8" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" placeholder="YES" id="TRc-4D-tbT"/> | |
100 | + <constraint firstItem="ayh-Y4-2QM" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="Zc1-Ki-ENV"/> | |
101 | + <constraint firstItem="GCl-mf-CD8" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="aM7-E7-p41"/> | |
102 | + <constraint firstItem="bSt-HN-qcq" firstAttribute="leading" secondItem="qLg-XF-Dyf" secondAttribute="trailing" constant="10" id="hlg-b5-9sd"/> | |
103 | + <constraint firstItem="qLg-XF-Dyf" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="20" id="nAo-mi-AuL"/> | |
104 | + <constraint firstItem="ayh-Y4-2QM" firstAttribute="top" secondItem="GCl-mf-CD8" secondAttribute="bottom" id="qaI-c1-69r"/> | |
105 | + <constraint firstItem="qLg-XF-Dyf" firstAttribute="centerY" secondItem="bSt-HN-qcq" secondAttribute="centerY" constant="-5" id="tA8-lE-abe"/> | |
106 | + </constraints> | |
107 | + <point key="canvasLocation" x="32.5" y="70.5"/> | |
22 | 108 | </view> |
23 | 109 | </objects> |
24 | 110 | </document> |
LifeLog/LifeLog/ServerAPI.h
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | |
28 | 28 | #pragma mark - Home Screen Function |
29 | 29 | - (void)requestTopWithMode:(int)mode andDate:(NSString *)date CompletionHandler:(void (^)(TopObject *, NSError *)) completion; |
30 | +- (void)requestCreateLog:(int)mode withStep:(int)numStep startDate:(NSString *)startDate endDate:(NSString *)endDate CompletionHandler:(void (^)(NSError *))completion; | |
30 | 31 | |
31 | 32 | #pragma mark - History Screen Function |
32 | 33 | - (void) requestHistory:(NSString *)token atDate:(NSDate *)date withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryObject *, NSError *)) completion; |
... | ... | @@ -40,5 +41,7 @@ |
40 | 41 | */ |
41 | 42 | - (void) requestTweetsList:(NSString *)token groupID: (int) groupID withPage:(int)page CompletionHandler:(void (^)(NSArray *, NSError *)) completion; |
42 | 43 | - (void) searchGroup:(NSString *)token withKey:(NSString *)key andPage:(int)page CompletionHandler:(void (^)(NSArray *, NSError *)) completion; |
44 | +#pragma mark - Common API | |
45 | +- (void)refreshToken: (NSString *)userID CompletionHandler:(void (^)(NSString *, NSError *))completion; | |
43 | 46 | @end |
LifeLog/LifeLog/ServerAPI.m
... | ... | @@ -262,7 +262,7 @@ |
262 | 262 | { |
263 | 263 | completion(nil, error); |
264 | 264 | } |
265 | - }]; | |
265 | + }]; | |
266 | 266 | } |
267 | 267 | |
268 | 268 | -(NSString *) convertIntToString : (int) type { |
... | ... | @@ -289,7 +289,7 @@ |
289 | 289 | - (void)requestTopWithMode:(int)mode andDate:(NSString *)date CompletionHandler:(void (^)(TopObject *, NSError *)) completion |
290 | 290 | { |
291 | 291 | NSString * token = [[NSUserDefaults standardUserDefaults] stringForKey:kToken]; |
292 | - NSString *url = [kServerAddress stringByAppendingFormat:@"/api/top/%d/%@", mode, date]; | |
292 | + NSString *url = [kServerAddress stringByAppendingFormat:@"api/top/%d/%@", mode, date]; | |
293 | 293 | [self _request:url method:@"GET" token:token paras:nil completion:^(NSData *data, NSError *error) { |
294 | 294 | |
295 | 295 | if (completion == NULL) { |
... | ... | @@ -347,9 +347,15 @@ |
347 | 347 | if (message == nil) { |
348 | 348 | message = @"Unknown error"; |
349 | 349 | } |
350 | - NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
351 | - completion(nil, errorObject); | |
352 | - [self checkToken:message]; | |
350 | + | |
351 | + if ([message isEqualToString:@"Token is invalid"]) { | |
352 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
353 | + [self requestTopWithMode:mode andDate:date CompletionHandler:completion]; | |
354 | + } | |
355 | + else { | |
356 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
357 | + completion(nil, errorObject); | |
358 | + } | |
353 | 359 | } |
354 | 360 | } |
355 | 361 | else |
... | ... | @@ -359,6 +365,46 @@ |
359 | 365 | }]; |
360 | 366 | } |
361 | 367 | |
368 | +- (void)requestCreateLog:(int)mode withStep:(int)numStep startDate:(NSString *)startDate endDate:(NSString *)endDate CompletionHandler:(void (^)(NSError *))completion { | |
369 | + NSString * token = [[NSUserDefaults standardUserDefaults] stringForKey:kToken]; | |
370 | + NSString *url = [kServerAddress stringByAppendingFormat:@"api/createLog"]; | |
371 | + NSDictionary *dict = @{@"mode": [NSNumber numberWithInt:mode], @"numStep": [NSNumber numberWithInt:numStep], @"startTime": startDate, @"endTime": endDate}; | |
372 | + [self _request:url method:@"POST" token:token paras:dict completion:^(NSData *data, NSError *error) { | |
373 | + | |
374 | + if (completion == NULL) { | |
375 | + return ; | |
376 | + } | |
377 | + | |
378 | + if (error == nil) | |
379 | + { | |
380 | + NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error]; | |
381 | + int status = [dataResult[@"status"] intValue]; | |
382 | + if (status == 1) { // status = 1 success | |
383 | + completion(nil); | |
384 | + } | |
385 | + else { | |
386 | + NSString *message = dataResult[@"message"]; | |
387 | + if (message == nil) { | |
388 | + message = @"Unknown error"; | |
389 | + } | |
390 | + | |
391 | + if ([message isEqualToString:@"Token is invalid"]) { | |
392 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
393 | + [self requestCreateLog:mode withStep:numStep startDate:startDate endDate:endDate CompletionHandler:completion]; | |
394 | + } | |
395 | + else { | |
396 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
397 | + completion(errorObject); | |
398 | + } | |
399 | + } | |
400 | + } | |
401 | + else | |
402 | + { | |
403 | + completion(error); | |
404 | + } | |
405 | + }]; | |
406 | +} | |
407 | + | |
362 | 408 | #pragma mark - History Screen Function |
363 | 409 | - (void) requestHistory:(NSString *)token atDate:(NSDate *)date withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryObject *, NSError *)) completion { |
364 | 410 | NSString *url = [kServerAddress stringByAppendingFormat:@"/api/history/%@/%d", [self convertIntToString:type], mode]; |
... | ... | @@ -383,9 +429,16 @@ |
383 | 429 | if (message == nil) { |
384 | 430 | message = @"Unknown error"; |
385 | 431 | } |
386 | - NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
387 | - completion(nil, errorObject); | |
388 | - [self checkToken:message]; | |
432 | + | |
433 | + if ([message isEqualToString:@"Token is invalid"]) { | |
434 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
435 | + NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken]; | |
436 | + [self requestHistory:tokenNew atDate:date withType:type andMode:mode CompletionHandler:completion]; | |
437 | + } | |
438 | + else { | |
439 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
440 | + completion(nil, errorObject); | |
441 | + } | |
389 | 442 | } |
390 | 443 | } |
391 | 444 | else |
... | ... | @@ -418,9 +471,16 @@ |
418 | 471 | if (message == nil) { |
419 | 472 | message = @"Unknown error"; |
420 | 473 | } |
421 | - NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
422 | - completion(nil, errorObject); | |
423 | - [self checkToken:message]; | |
474 | + | |
475 | + if ([message isEqualToString:@"Token is invalid"]) { | |
476 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
477 | + NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken]; | |
478 | + [self requestHistoryGraph:tokenNew withType:type andMode:mode CompletionHandler:completion]; | |
479 | + } | |
480 | + else { | |
481 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
482 | + completion(nil, errorObject); | |
483 | + } | |
424 | 484 | } |
425 | 485 | } |
426 | 486 | else |
... | ... | @@ -464,9 +524,16 @@ |
464 | 524 | if (message == nil) { |
465 | 525 | message = @"Unknown error"; |
466 | 526 | } |
467 | - NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
468 | - completion(nil, errorObject); | |
469 | - [self checkToken:message]; | |
527 | + | |
528 | + if ([message isEqualToString:@"Token is invalid"]) { | |
529 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
530 | + NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken]; | |
531 | + [self requestHistoryList:tokenNew withType:type andMode:mode AtPage:page CompletionHandler:completion]; | |
532 | + } | |
533 | + else { | |
534 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
535 | + completion(nil, errorObject); | |
536 | + } | |
470 | 537 | } |
471 | 538 | } |
472 | 539 | else |
... | ... | @@ -511,9 +578,19 @@ |
511 | 578 | } |
512 | 579 | else { |
513 | 580 | NSString *message = dataResult[@"message"]; |
514 | - NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
515 | - completion(nil, errorObject); | |
516 | - [self checkToken:message]; | |
581 | + if (message == nil) { | |
582 | + message = @"Unknown error"; | |
583 | + } | |
584 | + | |
585 | + if ([message isEqualToString:@"Token is invalid"]) { | |
586 | + [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES]; | |
587 | + NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken]; | |
588 | + [self requestTweetsList:tokenNew groupID:groupID withPage:page CompletionHandler:completion]; | |
589 | + } | |
590 | + else { | |
591 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
592 | + completion(nil, errorObject); | |
593 | + } | |
517 | 594 | } |
518 | 595 | } |
519 | 596 | else |
520 | 597 | |
521 | 598 | |
... | ... | @@ -569,15 +646,60 @@ |
569 | 646 | }]; |
570 | 647 | } |
571 | 648 | |
649 | +#pragma mark - Common API | |
650 | +- (void)refreshToken: (NSString *)userID CompletionHandler:(void (^)(NSString *, NSError *))completion { | |
651 | + [self _request:[kServerAddress stringByAppendingFormat: @"refreshToken"] method:@"POST" token:@"" paras:@{@"userId":userID} completion:^(NSData *data, NSError *error) { | |
652 | + | |
653 | + if (completion == NULL) { | |
654 | + return ; | |
655 | + } | |
656 | + | |
657 | + if (error == nil) | |
658 | + { | |
659 | + NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error]; | |
660 | + | |
661 | + int status = [dataResult[@"status"] intValue]; | |
662 | + if (status == 1) { // status = 1 success | |
663 | + NSArray *arrayResult = dataResult[@"result"]; | |
664 | + if (arrayResult.count > 0) { | |
665 | + NSString *token = arrayResult[0]; | |
666 | + completion(token, nil); | |
667 | + } | |
668 | + else { | |
669 | + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":@"Unknown Error"}]; | |
670 | + completion(nil, errorObject); | |
671 | + } | |
672 | + | |
673 | + } | |
674 | + else { // status = 0 error | |
675 | + NSString *message = dataResult[@"message"]; | |
676 | + if (message == nil) { | |
677 | + message = @"Unknown error"; | |
678 | + } | |
679 | + NSError *loginFaild = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}]; | |
680 | + completion(nil, loginFaild); | |
681 | + } | |
682 | + } | |
683 | + else | |
684 | + { | |
685 | + completion(nil, error); | |
686 | + } | |
687 | + }]; | |
688 | +} | |
689 | + | |
572 | 690 | #pragma mark - Private Function |
573 | -- (BOOL) checkToken:(NSString *)message { | |
574 | - if ([message isEqualToString:@"Token is invalid"]) { | |
575 | - [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationToken object:nil]; | |
576 | - return YES; | |
691 | +- (void) checkToken { | |
692 | + // [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationToken object:nil]; | |
693 | + NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kUser]; | |
694 | + User *user = (User *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; | |
695 | + if (user != nil) { | |
696 | + [self refreshToken:user.user_id CompletionHandler:^(NSString *token, NSError *error) { | |
697 | + if (error == nil) { | |
698 | + [[NSUserDefaults standardUserDefaults] setObject:token forKey:kToken]; | |
699 | + [[NSUserDefaults standardUserDefaults] synchronize]; | |
700 | + } | |
701 | + }]; | |
577 | 702 | } |
578 | - else { | |
579 | - return NO; | |
580 | - } | |
581 | 703 | } |
582 | 704 | - (NSData *) _encodeDictionary: (NSDictionary *) dictionary |
583 | 705 | { |
... | ... | @@ -630,6 +752,13 @@ |
630 | 752 | }]; |
631 | 753 | [task resume]; |
632 | 754 | return task; |
755 | +} | |
756 | + | |
757 | +-(void)waitUntilDone:(void(^)(void))waitBlock { | |
758 | + //use your statement or call method here | |
759 | + if(waitBlock){ | |
760 | + waitBlock(); | |
761 | + } | |
633 | 762 | } |
634 | 763 | |
635 | 764 | @end |