3. Tweak Parameters
Show the blue breathing dot
Then Build and Go...
Wednesday, September 30, 2009 3
4. And Bada-Boom
A Map App
Wednesday, September 30, 2009 4
5. But we want more,
like the breathing
Blue Dot
Wednesday, September 30, 2009 5
6. Where we are
Headed
‘Right’ Action - Details
‘Left’ Action - Shake Map
Animated ‘Breathing’
Wednesday, September 30, 2009 6
7. Stuff To Do
• View Based Project
• Parse XML from USGS
• Create Earthquakes
• Store Earthquakes
• Add Annotations
• Provide Annotation Views
• Respond to Events
Wednesday, September 30, 2009 7
8. View Based Project
Connect the
MapView to our VC
Wednesday, September 30, 2009 8
9. Parse XML
NSOperationQueue
operation
NSOperation
thread
parseForData:
addOperation:
Parse XML
EarthquakeParser
initWithContentsOfURL:
parse
invokeOnMainThread:
didStartElement:
foundCharcters:
didEndElement:
NSXMLParser
event
loop
addEarthquake:
parserFinished
EarthquakeParserDelegate
(MapQuakesViewController)
Don’t block the main event thread!
Wednesday, September 30, 2009 9
10. NSOperationQueue
operation
NSOperation
thread
Parse XML
parseForData:
addOperation: EarthquakeParser
Kick Off The Parse parseForData: is on an alternate thread,
won’t block event thread while
downloading the XML
Wednesday, September 30, 2009 10
11. EarthquakeParser
initWithContentsOfURL:
Parse XML
parse
NSXMLParser
Parse XML on the Each XML Event comes to the parser’s
delegate on the alternate thread
alternate thread
Wednesday, September 30, 2009 11
13. Create Earthquakes
EarthquakeParser
didStartElement:
foundCharcters:
didEndElement:
NSXMLParser
Parse XML on the Each XML Event comes to the parser’s
delegate on the alternate thread
alternate thread
Wednesday, September 30, 2009 13
14. Entry Element starts
and Earthquake
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
Create Earthquakes
attributes:(NSDictionary *)attributeDict {
if(nil != qName) {
elementName = qName; // swap for the qName if we have a name space
}
if ([elementName isEqualToString:@"entry"]) {
self.currentEarthquake = [[[Earthquake alloc] init] autorelease];
} else if([elementName isEqualToString:@"link"]) {
// ignore the related content and just grab the alternate
if ([[attributeDict valueForKey:@"rel"] isEqualToString:@"alternate"]) {
NSString *link = [attributeDict valueForKey:@"href"];
self.currentEarthquake.detailsURL =
[NSString stringWithFormat:@"http://earthquake.usgs.gov/%@", link];
}
} else if([elementName isEqualToString:@"title"] ||
[elementName isEqualToString:@"updated"] ||
[elementName isEqualToString:@"id"] ||
[elementName isEqualToString:@"georss:point"] ||
[elementName isEqualToString:@"georss:elev"]) {
self.propertyValue = [NSMutableString string];
} else {
self.propertyValue = nil;
}
}
Wednesday, September 30, 2009 14
15. EarthquakeParser Back to the Main
Thread
Store Earthquakes
invokeOnMainThread:
event
loop
addEarthquake:
EarthquakeParserDelegate
Let the main thread know an earthquake was
(MapQuakesViewController)
found by pushing the addEarthquake: and
parserFinished methods onto the main thread
Wednesday, September 30, 2009 15
17. MapQuakesVC holds the
Earthquakes
Store Earthquakes
- (void)addEarthquake:(Earthquake *)earthquake {
[self.earthquakes addObject:earthquake];
}
Wednesday, September 30, 2009 17
18. EarthquakeParser Back to the Main
Thread
Add Annotations
invokeOnMainThread:
event
loop
parserFinished
EarthquakeParserDelegate Once all the XML is parsed we tell the delegate
(MapQuakesViewController) which displays the earthquakes in the form of an
annotation.
Wednesday, September 30, 2009 18
19. Back to the Main Thread
Again
Add Annotations
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[(id)[self delegate] performSelectorOnMainThread:@selector(parserFinished)
withObject:nil
waitUntilDone:NO];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self autorelease];
}
Wednesday, September 30, 2009 19
20. Display Earthquakes as
Annotations
Add Annotations
- (void)parserFinished {
[self displayEarthquakes];
}
Wednesday, September 30, 2009 20
21. Remove Old Annotations
- (void)displayEarthquakes {
Add Annotations
[self removeAnnotations];
NSArray *visibleQuakes = [self sortAndFilterEarthquakes];
// limit the numer to 100
if(visibleQuakes.count > 100) {
// remove the earthquakes from the top of the
// list until we are down to 100
NSUInteger removeCount = visibleQuakes.count - 100;
NSRange keepers = {removeCount, 100}; // location and length
visibleQuakes = [visibleQuakes subarrayWithRange:keepers];
}
for(Earthquake *earthquake in visibleQuakes) {
EarthquakeAnnotation *eqAnn = [EarthquakeAnnotation
annotationWithEarthquake:earthquake];
[self.mapView addAnnotation:eqAnn];
}
}
Wednesday, September 30, 2009 21
22. Find Visible Quakes
Sorted by Magnitude
- (void)displayEarthquakes {
Add Annotations
[self removeAnnotations];
NSArray *visibleQuakes = [self sortAndFilterEarthquakes];
// limit the numer to 100
if(visibleQuakes.count > 100) {
// remove the earthquakes from the top of the
// list until we are down to 100
NSUInteger removeCount = visibleQuakes.count - 100;
NSRange keepers = {removeCount, 100}; // location and length
visibleQuakes = [visibleQuakes subarrayWithRange:keepers];
}
for(Earthquake *earthquake in visibleQuakes) {
EarthquakeAnnotation *eqAnn = [EarthquakeAnnotation
annotationWithEarthquake:earthquake];
[self.mapView addAnnotation:eqAnn];
}
}
Wednesday, September 30, 2009 22
23. Limit Earthquakes to
100
- (void)displayEarthquakes {
Add Annotations
[self removeAnnotations];
NSArray *visibleQuakes = [self sortAndFilterEarthquakes];
// limit the numer to 100
if(visibleQuakes.count > 100) {
// remove the earthquakes from the top of the
// list until we are down to 100
NSUInteger removeCount = visibleQuakes.count - 100;
NSRange keepers = {removeCount, 100}; // location and length
visibleQuakes = [visibleQuakes subarrayWithRange:keepers];
}
for(Earthquake *earthquake in visibleQuakes) {
EarthquakeAnnotation *eqAnn = [EarthquakeAnnotation
annotationWithEarthquake:earthquake];
[self.mapView addAnnotation:eqAnn];
}
}
Wednesday, September 30, 2009 23
24. Find and Display
Earthquakes
- (void)displayEarthquakes {
Add Annotations
[self removeAnnotations];
NSArray *visibleQuakes = [self sortAndFilterEarthquakes];
// limit the numer to 100
if(visibleQuakes.count > 100) {
// remove the earthquakes from the top of the
// list until we are down to 100
NSUInteger removeCount = visibleQuakes.count - 100;
NSRange keepers = {removeCount, 100}; // location and length
visibleQuakes = [visibleQuakes subarrayWithRange:keepers];
}
for(Earthquake *earthquake in visibleQuakes) {
EarthquakeAnnotation *eqAnn = [EarthquakeAnnotation
annotationWithEarthquake:earthquake];
[self.mapView addAnnotation:eqAnn];
}
}
Wednesday, September 30, 2009 24
25. Remove old Earthquake
Annotations
Add Annotations
- (void) removeAnnotations {
// remove the old annotations but
// don't modify the array while iterating
NSArray *annotationsCopy = [self.mapView.annotations copy];
for(id annotation in annotationsCopy) {
if([[annotation class] isSubclassOfClass:[EarthquakeAnnotation class]]) {
[self.mapView removeAnnotation:annotation];
}
}
[annotationsCopy release];
}
Wednesday, September 30, 2009 25
42. Where To Now?
• Your data will likely have more
interesting selection criteria, exploit it
• The ‘detail’ from right and left buttons
can do lots more interesting stuff
• USGS Provides KML files for shake
maps
• Use Core Animation in the right or left
buttons
Wednesday, September 30, 2009 42
43. Summary
• Filtering your Annotations is important
if you have lots of data
• It’s easy to build your own custom
annotation views and add Core
Animation to them
Wednesday, September 30, 2009 43
44. Thanks!
Pragmatic iPhone Studio
Wednesday, September 30, 2009 44