Commit f7449e66183391dde7b6478d94bbd36e6631b122

Authored by phong
1 parent b0579422a5

update save step of 7 day before date now

Showing 4 changed files with 161 additions and 34 deletions Side-by-side Diff

LifeLog/LifeLog/HomeViewController.m
... ... @@ -40,7 +40,6 @@
40 40 @property (nonatomic, assign) NSInteger running;
41 41 @property (nonatomic, strong) NSDate *dateCurrent;
42 42  
43   -//@property (nonatomic, assign) BOOL isRequesting;
44 43 @property (nonatomic, assign) int totalRequest;
45 44 @property (nonatomic, assign) int countComplete;
46 45  
... ... @@ -50,7 +49,7 @@
50 49  
51 50 - (void)viewDidLoad {
52 51 [super viewDidLoad];
53   - // Do any additional setup after loading the view from its nib.
  52 +
54 53 self.lblTitle.text = NSLocalizedString(@"lifelog.home.title", nil);
55 54  
56 55 [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.lblTitle attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
57 56  
58 57  
59 58  
60 59  
... ... @@ -106,27 +105,45 @@
106 105 _walking = 0;
107 106 _running = 0;
108 107 _segmentHome.selectedSegmentIndex = 1;
109   -// _isRequesting = NO;
110 108 _totalRequest = 0;
111 109 _countComplete = 0;
112 110  
113 111 progressHud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
114 112 progressHud.mode = MBProgressHUDModeIndeterminate;
115 113 progressHud.detailsLabel.text = NSLocalizedString(@"lifelog.home.progressHud.title", nil);
  114 + [self saveDataStep7LastDay];
116 115 }
117 116  
118 117 - (void)viewWillAppear:(BOOL)animated {
119 118 [super viewWillAppear:animated];
120   -// _timer = [NSTimer scheduledTimerWithTimeInterval:1.5f target:self selector:@selector(countStep) userInfo:nil repeats:YES];
121   -// [_timer fire];
122   - [self countStep];
123   -
  119 + [self saveStepForDay:self.dateCurrent];
  120 + [self requestTopByDate:_dateCurrent];
  121 +}
  122 +
  123 +- (void)requestTopByDate:(NSDate *)date {
124 124 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
125 125 [dateFormatter setDateFormat:@"yyyy-MM-dd"];
126   - NSString *dateString = [dateFormatter stringFromDate:_dateCurrent];
  126 + NSString *dateString = [dateFormatter stringFromDate:date];
127 127  
128 128 HomeViewController __weak *weakSelf = self;
129   - [[ServerAPI server] requestTopWithMode:(int)_segmentHome.selectedSegmentIndex andDate:dateString CompletionHandler:^(TopObject *topObject, NSError *error) {
  129 + int mode = 1;
  130 + switch (_segmentHome.selectedSegmentIndex) {
  131 + case 0:
  132 + mode = 3;
  133 + break;
  134 +
  135 + case 1:
  136 + mode = 1;
  137 + break;
  138 +
  139 + case 2:
  140 + mode = 2;
  141 + break;
  142 +
  143 + default:
  144 + break;
  145 + }
  146 + [[ServerAPI server] requestTopWithMode:mode andDate:dateString CompletionHandler:^(TopObject *topObject, NSError *error) {
130 147 if(weakSelf == nil) {
131 148 return ;
132 149 }
... ... @@ -144,7 +161,6 @@
144 161  
145 162 - (void)viewWillDisappear:(BOOL)animated {
146 163 [super viewWillDisappear:animated];
147   - //[_timer invalidate];
148 164 }
149 165  
150 166 - (void)didReceiveMemoryWarning {
151 167  
... ... @@ -168,14 +184,14 @@
168 184 {
169 185 self.dateCurrent = [self.dateCurrent dateByAddingTimeInterval:-(24*60*60)];
170 186 self.lblDateCurrent.text = [NSString stringWithFormat:@"%ld%@%ld%@%ld%@", (long)[_dateCurrent getYear], NSLocalizedString(@"lifelog.common.year", nil), (long)[_dateCurrent getMonth], NSLocalizedString(@"lifelog.common.month", nil), (long)[_dateCurrent getDay], NSLocalizedString(@"lifelog.common.day", nil)];
171   - [self countStep];
  187 + [self saveStepForDay:self.dateCurrent];
172 188 }
173 189  
174 190 - (IBAction)rightButtonTouchUpInside:(id)sender
175 191 {
176 192 self.dateCurrent = [self.dateCurrent dateByAddingTimeInterval:24*60*60];
177 193 self.lblDateCurrent.text = [NSString stringWithFormat:@"%ld%@%ld%@%ld%@", (long)[_dateCurrent getYear], NSLocalizedString(@"lifelog.common.year", nil), (long)[_dateCurrent getMonth], NSLocalizedString(@"lifelog.common.month", nil), (long)[_dateCurrent getDay], NSLocalizedString(@"lifelog.common.day", nil)];
178   - [self countStep];
  194 + [self saveStepForDay:self.dateCurrent];
179 195 }
180 196  
181 197 - (IBAction)segmentValueChange:(id)sender {
182 198  
183 199  
184 200  
185 201  
... ... @@ -183,23 +199,19 @@
183 199 }
184 200  
185 201 #pragma mark - Functions Private
186   -- (void)countStep
  202 +- (void)saveStepForDay:(NSDate *)date
187 203 {
188   -// if (self.isRequesting == YES) {
189   -// return;
190   -// }
191 204 if ([CMMotionActivityManager isActivityAvailable]) {
192 205 [progressHud showAnimated:YES];
193 206 [progressHud setHidden:NO];
194   - // self.isRequesting = YES;
195 207 self.bike = 0;
196 208 self.walking = 0;
197 209 self.running = 0;
198   - NSDate *startDate = [self.dateCurrent beginningAtMidnightOfDay];
  210 + NSDate *startDate = [date beginningAtMidnightOfDay];
199 211 NSDate *endDate = [startDate dateByAddingTimeInterval:(24*60*60 - 1)];
200 212  
201 213 HomeViewController __weak *weakSelf = self;
202   - dispatch_queue_t myQueue = dispatch_queue_create("mobileworld.jp.lifelog", NULL);
  214 + dispatch_queue_t myQueue = dispatch_queue_create("mobileworld.jp.lifelog.forDay", NULL);
203 215 dispatch_async(myQueue, ^{
204 216 if (weakSelf == nil) {
205 217 return ;
206 218  
207 219  
208 220  
209 221  
210 222  
... ... @@ -232,32 +244,26 @@
232 244 }
233 245  
234 246 for (CMMotionActivityExtra *activityExtra in arrayActivities) {
235   - // NSLog(@"%@", activityExtra.activity.startDate);
236 247 [weakSelf.pedometer queryPedometerDataFromDate:activityExtra.activity.startDate toDate:activityExtra.endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
237 248 NSInteger numberStep = [pedometerData.numberOfSteps integerValue];
238 249 int mode = 1;
239 250 if (activityExtra.activity.cycling) {
240 251 // self.bike
241 252 weakSelf.bike += numberStep;
242   - //NSLog(@"Step cycling");
243 253 mode = 3;
244 254 }
245 255 else if (activityExtra.activity.walking) {
246 256 // self.walking
247 257 weakSelf.walking += numberStep;
248   - //NSLog(@"Step walking");
249 258 mode = 1;
250 259 }
251 260 else if (activityExtra.activity.running) {
252 261 weakSelf.running += numberStep;
253   - //NSLog(@"Step running");
254 262 mode = 2;
255 263 }
256 264 else {
257 265 // unknown
258   - //NSLog(@"Step unknown");
259 266 }
260   - // NSLog(@"Number of step--> %ld", numberStep);
261 267 weakSelf.countComplete += 1;
262 268  
263 269 // save step to server
... ... @@ -277,7 +283,6 @@
277 283 });
278 284 }];
279 285 }
280   - // NSLog(@"-----------------------------------------------------");
281 286 }];
282 287 });
283 288 }
... ... @@ -286,7 +291,7 @@
286 291 }
287 292 }
288 293  
289   -- (void)updateStepUI //:(NSInteger)numberStep
  294 +- (void)updateStepUI
290 295 {
291 296 if (self.totalRequest == self.countComplete) {
292 297 switch (self.segmentHome.selectedSegmentIndex) {
293 298  
... ... @@ -311,11 +316,87 @@
311 316 default:
312 317 break;
313 318 }
314   - // NSLog(@"Walking: %ld || Running: %ld || Bike: %ld", self.walking, self.running, self.bike);
315   - // self.isRequesting = NO;
316 319 self.countComplete = 0;
317 320 self.totalRequest = 0;
318 321 [progressHud setHidden:YES];
  322 + }
  323 +}
  324 +
  325 +- (void)saveDataStep7LastDay
  326 +{
  327 + NSDate *dateNow = [NSDate date];
  328 + for (int index = 0; index < 7; index++) {
  329 + dateNow = [dateNow dateByAddingTimeInterval:-(24*60*60)];
  330 + [self saveStepByDate:dateNow];
  331 + }
  332 +}
  333 +
  334 +- (void)saveStepByDate:(NSDate *)date
  335 +{
  336 + if ([CMMotionActivityManager isActivityAvailable]) {
  337 + NSDate *startDate = [date beginningAtMidnightOfDay];
  338 + NSDate *endDate = [startDate dateByAddingTimeInterval:(24*60*60 - 1)];
  339 +
  340 + HomeViewController __weak *weakSelf = self;
  341 + dispatch_queue_t myQueue = dispatch_queue_create("mobileworld.jp.lifelog.7lastday", NULL);
  342 + dispatch_async(myQueue, ^{
  343 + if (weakSelf == nil) {
  344 + return ;
  345 + }
  346 +
  347 + [weakSelf.motionActivityManager queryActivityStartingFromDate:startDate toDate:endDate toQueue:_operationQueue withHandler:^(NSArray<CMMotionActivity *> * _Nullable activities, NSError * _Nullable error) {
  348 + if (error || activities.count <= 0) {
  349 + return ;
  350 + }
  351 + // set EndDate
  352 + NSMutableArray *arrayActivities = [[NSMutableArray alloc] init];
  353 + for (int i = 0; i < activities.count; i++) {
  354 + CMMotionActivity *activity = [activities objectAtIndex:i];
  355 + CMMotionActivityExtra *activityExtra = [[CMMotionActivityExtra alloc] init];
  356 + activityExtra.activity = activity;
  357 + if (i == activities.count - 1) {
  358 + activityExtra.endDate = endDate;
  359 + }
  360 + else {
  361 + CMMotionActivity *activityNext = [activities objectAtIndex:i+1];
  362 + activityExtra.endDate = activityNext.startDate;
  363 + }
  364 + [arrayActivities addObject:activityExtra];
  365 + }
  366 +
  367 + for (CMMotionActivityExtra *activityExtra in arrayActivities) {
  368 + [weakSelf.pedometer queryPedometerDataFromDate:activityExtra.activity.startDate toDate:activityExtra.endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
  369 + NSInteger numberStep = [pedometerData.numberOfSteps integerValue];
  370 + int mode = 1;
  371 + if (activityExtra.activity.cycling) {
  372 + mode = 3;
  373 + }
  374 + else if (activityExtra.activity.walking) {
  375 + mode = 1;
  376 + }
  377 + else if (activityExtra.activity.running) {
  378 + mode = 2;
  379 + }
  380 + else {
  381 + // unknown
  382 + }
  383 +
  384 + // save step to server
  385 + if (numberStep > 0) {
  386 + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  387 + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  388 + NSString *dateBegin = [dateFormatter stringFromDate:activityExtra.activity.startDate];
  389 + NSString *dateEnd = [dateFormatter stringFromDate:activityExtra.endDate];
  390 + [[ServerAPI server] requestCreateLog:mode withStep:(int)numberStep startDate:dateBegin endDate:dateEnd CompletionHandler:^(NSError *error) {
  391 + if (error) {
  392 + NSLog(@"Error: %@", error);
  393 + }
  394 + }];
  395 + }
  396 + }];
  397 + }
  398 + }];
  399 + });
319 400 }
320 401 }
321 402  
LifeLog/LifeLog/MapViewController.m
... ... @@ -70,10 +70,10 @@
70 70 [_timer fire];
71 71 }
72 72  
73   -- (void)viewWillDisappear:(BOOL)animated {
74   - [super viewWillDisappear:animated];
75   - [_timer invalidate];
76   -}
  73 +//- (void)viewWillDisappear:(BOOL)animated {
  74 +// [super viewWillDisappear:animated];
  75 +// [_timer invalidate];
  76 +//}
77 77  
78 78 #pragma mark - CLLocationManagerDelegate
79 79 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
LifeLog/LifeLog/TodayViewController.m
... ... @@ -77,6 +77,22 @@
77 77 [self.navigationController popViewControllerAnimated:YES];
78 78 }
79 79  
  80 +- (IBAction)buttonShareTouchUpInside:(id)sender {
  81 +
  82 +}
  83 +
  84 +- (IBAction)buttonFacebookTouchUpInside:(id)sender {
  85 + NSString * content = @"Finish 500 steps";
  86 + TodayViewController __weak *weakSelf = self;
  87 + [Utilities shareFacebook:content withViewController:weakSelf];
  88 +}
  89 +
  90 +- (IBAction)buttonLineTouchUpInside:(id)sender {
  91 + NSString * content = @"Finish 500 steps";
  92 + TodayViewController __weak *weakSelf = self;
  93 + [Utilities shareLine:content withViewController:weakSelf];
  94 +}
  95 +
80 96 #pragma mark - Functions Private
81 97 - (void)countStep
82 98 {
LifeLog/LifeLog/TodayViewController.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>
... ... @@ -67,6 +67,12 @@
67 67 <constraint firstAttribute="width" constant="42" id="abX-W4-Ho4"/>
68 68 </constraints>
69 69 </imageView>
  70 + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1ak-Ne-wz9" userLabel="ButtonShare">
  71 + <rect key="frame" x="8" y="137" width="42" height="57"/>
  72 + <connections>
  73 + <action selector="buttonShareTouchUpInside:" destination="-1" eventType="touchUpInside" id="dkw-ed-JhQ"/>
  74 + </connections>
  75 + </button>
70 76 <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_facebook" translatesAutoresizingMaskIntoConstraints="NO" id="Jtx-be-zjg">
71 77 <rect key="frame" x="8" y="202" width="40" height="40"/>
72 78 <constraints>
... ... @@ -74,6 +80,12 @@
74 80 <constraint firstAttribute="height" constant="40" id="5hP-gZ-Qrl"/>
75 81 </constraints>
76 82 </imageView>
  83 + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HLr-Qj-bm4" userLabel="ButtonFacebook">
  84 + <rect key="frame" x="8" y="202" width="40" height="40"/>
  85 + <connections>
  86 + <action selector="buttonFacebookTouchUpInside:" destination="-1" eventType="touchUpInside" id="MHi-pC-vsR"/>
  87 + </connections>
  88 + </button>
77 89 <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_line" translatesAutoresizingMaskIntoConstraints="NO" id="wHy-xz-GJV">
78 90 <rect key="frame" x="8" y="250" width="40" height="40"/>
79 91 <constraints>
... ... @@ -81,6 +93,12 @@
81 93 <constraint firstAttribute="height" constant="40" id="myc-Ev-aCy"/>
82 94 </constraints>
83 95 </imageView>
  96 + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="equ-yC-hU1" userLabel="ButtonLine">
  97 + <rect key="frame" x="8" y="250" width="40" height="40"/>
  98 + <connections>
  99 + <action selector="buttonLineTouchUpInside:" destination="-1" eventType="touchUpInside" id="9mi-bX-Uqp"/>
  100 + </connections>
  101 + </button>
84 102 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oRx-7J-bma" customClass="CircleProgressBar">
85 103 <rect key="frame" x="60" y="94" width="255" height="255"/>
86 104 <subviews>
87 105  
88 106  
89 107  
90 108  
91 109  
92 110  
93 111  
94 112  
... ... @@ -195,25 +213,37 @@
195 213 <color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
196 214 <constraints>
197 215 <constraint firstAttribute="trailing" secondItem="11m-je-qZ1" secondAttribute="trailing" id="5wQ-9t-fkx"/>
  216 + <constraint firstItem="1ak-Ne-wz9" firstAttribute="top" secondItem="PW6-AR-UCs" secondAttribute="top" id="7Lu-Sw-8Vd"/>
198 217 <constraint firstItem="V2B-wZ-Efk" firstAttribute="centerY" secondItem="oRx-7J-bma" secondAttribute="centerY" id="Bhj-5W-tqM"/>
199 218 <constraint firstItem="yOP-KX-J14" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="5" id="Bp4-Am-rzQ"/>
200 219 <constraint firstItem="Jtx-be-zjg" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="8" id="C4T-QJ-aV0"/>
201 220 <constraint firstItem="dQq-cp-R2A" firstAttribute="leading" secondItem="oRx-7J-bma" secondAttribute="trailing" id="CSy-Of-ifG"/>
202 221 <constraint firstAttribute="trailing" secondItem="dQq-cp-R2A" secondAttribute="trailing" id="Ct9-ZA-fqo"/>
  222 + <constraint firstItem="HLr-Qj-bm4" firstAttribute="bottom" secondItem="Jtx-be-zjg" secondAttribute="bottom" id="DGk-ic-g00"/>
203 223 <constraint firstItem="oRx-7J-bma" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="60" id="DKw-80-JuB"/>
204 224 <constraint firstItem="11m-je-qZ1" firstAttribute="leading" secondItem="oRx-7J-bma" secondAttribute="trailing" id="FOq-gH-CTf"/>
  225 + <constraint firstItem="HLr-Qj-bm4" firstAttribute="leading" secondItem="Jtx-be-zjg" secondAttribute="leading" id="FhM-mA-AWq"/>
205 226 <constraint firstItem="RSj-iV-Oaf" firstAttribute="centerY" secondItem="2SZ-sd-ADD" secondAttribute="centerY" id="JTA-NC-8qU"/>
206 227 <constraint firstItem="V2B-wZ-Efk" firstAttribute="top" secondItem="dQq-cp-R2A" secondAttribute="bottom" constant="8" id="KF9-QN-1Vc"/>
207 228 <constraint firstItem="wHy-xz-GJV" firstAttribute="top" secondItem="Jtx-be-zjg" secondAttribute="bottom" constant="8" id="LFj-zM-kIs"/>
208 229 <constraint firstAttribute="trailing" secondItem="RSj-iV-Oaf" secondAttribute="trailing" constant="10" id="Ldg-q1-Jsy"/>
209 230 <constraint firstItem="V2B-wZ-Efk" firstAttribute="leading" secondItem="oRx-7J-bma" secondAttribute="trailing" id="Ls8-7Q-gjM"/>
210 231 <constraint firstItem="Jtx-be-zjg" firstAttribute="top" secondItem="PW6-AR-UCs" secondAttribute="bottom" constant="8" id="MMi-Mg-qDV"/>
  232 + <constraint firstItem="1ak-Ne-wz9" firstAttribute="leading" secondItem="PW6-AR-UCs" secondAttribute="leading" id="NK3-Gl-NZu"/>
211 233 <constraint firstAttribute="trailing" secondItem="2SZ-sd-ADD" secondAttribute="trailing" id="O9f-yA-cZ5"/>
  234 + <constraint firstItem="equ-yC-hU1" firstAttribute="leading" secondItem="wHy-xz-GJV" secondAttribute="leading" id="Oe7-aI-2zb"/>
212 235 <constraint firstItem="Jtx-be-zjg" firstAttribute="centerY" secondItem="oRx-7J-bma" secondAttribute="centerY" id="U3o-rO-Gcb"/>
213 236 <constraint firstItem="oRx-7J-bma" firstAttribute="top" secondItem="2SZ-sd-ADD" secondAttribute="bottom" constant="50" id="WGj-Jf-jSz"/>
  237 + <constraint firstItem="equ-yC-hU1" firstAttribute="bottom" secondItem="wHy-xz-GJV" secondAttribute="bottom" id="ad4-KH-cYo"/>
  238 + <constraint firstItem="equ-yC-hU1" firstAttribute="top" secondItem="wHy-xz-GJV" secondAttribute="top" id="adt-MK-oHP"/>
214 239 <constraint firstItem="PW6-AR-UCs" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="8" id="bsc-pa-ApI"/>
  240 + <constraint firstItem="HLr-Qj-bm4" firstAttribute="trailing" secondItem="Jtx-be-zjg" secondAttribute="trailing" id="h5E-wF-FZV"/>
  241 + <constraint firstItem="1ak-Ne-wz9" firstAttribute="trailing" secondItem="PW6-AR-UCs" secondAttribute="trailing" id="jXm-mH-e3x"/>
215 242 <constraint firstAttribute="trailing" secondItem="V2B-wZ-Efk" secondAttribute="trailing" id="kQV-FL-4Zq"/>
  243 + <constraint firstItem="HLr-Qj-bm4" firstAttribute="top" secondItem="Jtx-be-zjg" secondAttribute="top" id="lE9-vw-sw6"/>
216 244 <constraint firstItem="2SZ-sd-ADD" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="q0L-8m-E0D"/>
  245 + <constraint firstItem="equ-yC-hU1" firstAttribute="trailing" secondItem="wHy-xz-GJV" secondAttribute="trailing" id="vDi-q7-eov"/>
  246 + <constraint firstItem="1ak-Ne-wz9" firstAttribute="bottom" secondItem="PW6-AR-UCs" secondAttribute="bottom" id="vlQ-WK-pY4"/>
217 247 <constraint firstItem="11m-je-qZ1" firstAttribute="top" secondItem="V2B-wZ-Efk" secondAttribute="bottom" constant="8" id="vrX-sS-hWJ"/>
218 248 <constraint firstItem="2SZ-sd-ADD" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" placeholder="YES" id="w1M-Il-jBT"/>
219 249 <constraint firstAttribute="trailing" secondItem="oRx-7J-bma" secondAttribute="trailing" constant="60" id="y6f-vv-nWJ"/>