forked from eway2012/SampleCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRootViewController.m
More file actions
315 lines (260 loc) · 13.6 KB
/
RootViewController.m
File metadata and controls
315 lines (260 loc) · 13.6 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*
File: RootViewController.m
Abstract: View controller for displaying the earthquake list.
Version: 1.0
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2011 Apple Inc. All Rights Reserved.
*/
#import "RootViewController.h"
#import "Earthquake.h"
@implementation RootViewController
@synthesize managedObjectContext, fetchedResultsController, twoWeeksAgo;
#pragma mark -
- (void)dealloc {
[dateFormatter release];
[fetchedResultsController release];
[managedObjectContext release];
[twoWeeksAgo release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
// The table row height is not the standard value. Since all the rows have the same height,
// it is more efficient to set this property on the table, rather than using the delegate
// method -tableView:heightForRowAtIndexPath:
//
self.tableView.rowHeight = 64;
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
// You should not use this function in a shipping application, although it may be useful
// during development. If it is not possible to recover from the error, display an alert
// panel that instructs the user to quit the application by pressing the Home button.
//
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// compute the date two weeks ago from today, used later when dumping old earthquakes
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setDay:-14]; // 14 days back from today
self.twoWeeksAgo = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
[offsetComponents release];
[gregorian release];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.twoWeeksAgo = nil;
}
// On-demand initializer for read-only property.
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
}
return dateFormatter;
}
// Based on the magnitude of the earthquake, return an image indicating its seismic strength.
- (UIImage *)imageForMagnitude:(CGFloat)magnitude {
if (magnitude >= 5.0) {
return [UIImage imageNamed:@"5.0.png"];
}
if (magnitude >= 4.0) {
return [UIImage imageNamed:@"4.0.png"];
}
if (magnitude >= 3.0) {
return [UIImage imageNamed:@"3.0.png"];
}
if (magnitude >= 2.0) {
return [UIImage imageNamed:@"2.0.png"];
}
return nil;
}
#pragma mark -
#pragma mark UITableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[fetchedResultsController sections] count];
}
// The number of rows is equal to the number of earthquakes in the array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger numberOfRows = 0;
if ([[fetchedResultsController sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];
}
return numberOfRows;
}
// The cell uses a custom layout, but otherwise has standard behavior for UITableViewCell.
// In these cases, it's preferable to modify the view hierarchy of the cell's content view, rather
// than subclassing. Instead, view "tags" are used to identify specific controls, such as labels,
// image views, etc.
//
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Each subview in the cell will be identified by a unique tag.
static NSUInteger const kLocationLabelTag = 2;
static NSUInteger const kDateLabelTag = 3;
static NSUInteger const kMagnitudeLabelTag = 4;
static NSUInteger const kMagnitudeImageTag = 5;
// Declare references to the subviews which will display the earthquake data.
UILabel *locationLabel = nil;
UILabel *dateLabel = nil;
UILabel *magnitudeLabel = nil;
UIImageView *magnitudeImage = nil;
static NSString *kEarthquakeCellID = @"EarthquakeCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kEarthquakeCellID];
if (cell == nil) {
// No reusable cell was available, so we create a new cell and configure its subviews.
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:kEarthquakeCellID] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
locationLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0, 300.0, 40.0)] autorelease];
locationLabel.tag = kLocationLabelTag;
locationLabel.font = [UIFont boldSystemFontOfSize:16.0];
[cell.contentView addSubview:locationLabel];
dateLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10.0, 42.0, 170.0, 14.0)] autorelease];
dateLabel.tag = kDateLabelTag;
dateLabel.font = [UIFont systemFontOfSize:12.0];
[cell.contentView addSubview:dateLabel];
magnitudeLabel = [[[UILabel alloc] initWithFrame:CGRectMake(277.0, 30.0, 170.0, 29.0)] autorelease];
magnitudeLabel.tag = kMagnitudeLabelTag;
magnitudeLabel.font = [UIFont boldSystemFontOfSize:24.0];
magnitudeLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:magnitudeLabel];
magnitudeImage = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"5.0.png"]] autorelease];
CGRect imageFrame = magnitudeImage.frame;
imageFrame.origin = CGPointMake(180.0, 27.0);
imageFrame.size = CGSizeMake(imageFrame.size.width - 8.0, imageFrame.size.height - 8.0); // skring the image a little to fit
magnitudeImage.frame = imageFrame;
magnitudeImage.tag = kMagnitudeImageTag;
magnitudeImage.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:magnitudeImage];
} else {
// A reusable cell was available, so we just need to get a reference to the subviews
// using their tags.
//
locationLabel = (UILabel *)[cell.contentView viewWithTag:kLocationLabelTag];
dateLabel = (UILabel *)[cell.contentView viewWithTag:kDateLabelTag];
magnitudeLabel = (UILabel *)[cell.contentView viewWithTag:kMagnitudeLabelTag];
magnitudeImage = (UIImageView *)[cell.contentView viewWithTag:kMagnitudeImageTag];
}
// get the specific earthquake for this row
Earthquake *earthquake = (Earthquake *)[fetchedResultsController objectAtIndexPath:indexPath];
// set the relevant data for each subview in the cell
locationLabel.text = earthquake.location;
dateLabel.text = [NSString stringWithFormat:@"%@", [self.dateFormatter stringFromDate:earthquake.date]];
magnitudeLabel.text = [NSString stringWithFormat:@"%.1f", [earthquake.magnitude floatValue]];
magnitudeImage.image = [self imageForMagnitude:[earthquake.magnitude floatValue]];
return cell;
}
#pragma mark -
#pragma mark Core Data
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil) {
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Earthquake"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
}
return fetchedResultsController;
}
// this is called from mergeChanges: method,
// requested to be made on the main thread so we can update our table with our new earthquake objects
//
- (void)updateContext:(NSNotification *)notification
{
NSManagedObjectContext *mainContext = [self managedObjectContext];
[mainContext mergeChangesFromContextDidSaveNotification:notification];
// keep our number of earthquakes to a manageable level, remove earthquakes older than 2 weeks
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Earthquake"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date < %@", self.twoWeeksAgo];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *olderEarthquakes = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
Earthquake *earthquake;
for (earthquake in olderEarthquakes) {
[self.managedObjectContext deleteObject:earthquake];
}
// update our fetched results after the merge
//
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
// You should not use this function in a shipping application, although it may be useful
// during development. If it is not possible to recover from the error, display an alert
// panel that instructs the user to quit the application by pressing the Home button.
//
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[fetchRequest release];
[self.tableView reloadData];
}
// this is called via observing "NSManagedObjectContextDidSaveNotification" from our ParseOperation
- (void)mergeChanges:(NSNotification *)notification {
NSManagedObjectContext *mainContext = [self managedObjectContext];
if ([notification object] == mainContext) {
// main context save, no need to perform the merge
return;
}
[self performSelectorOnMainThread:@selector(updateContext:) withObject:notification waitUntilDone:YES];
}
@end