Permalink
Browse files

Show search results on map

  • Loading branch information...
1 parent 2a0f972 commit b3916e15d53e5bf3f4ae35b37f3668aa09d9a407 jose.gonzalez committed May 21, 2012
@@ -12,6 +12,7 @@
1D051A27156A4138007BFE40 /* RKJSONParserJSONKit+TestAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D051A25156A4138007BFE40 /* RKJSONParserJSONKit+TestAdditions.m */; };
1D051A29156A415D007BFE40 /* SearchResultsGroupingSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D051A28156A415D007BFE40 /* SearchResultsGroupingSpec.m */; };
1D051A2A156A4952007BFE40 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D09575D156531A2008C69E3 /* CoreLocation.framework */; };
+ 1D051A31156A6323007BFE40 /* UPCSearchResultGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D051A30156A6323007BFE40 /* UPCSearchResultGroup.m */; };
1D0956B91563A704008C69E3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D0956B81563A704008C69E3 /* UIKit.framework */; };
1D0956BB1563A704008C69E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D0956BA1563A704008C69E3 /* Foundation.framework */; };
1D0956BD1563A704008C69E3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D0956BC1563A704008C69E3 /* CoreGraphics.framework */; };
@@ -85,6 +86,8 @@
1D051A24156A4138007BFE40 /* RKJSONParserJSONKit+TestAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RKJSONParserJSONKit+TestAdditions.h"; sourceTree = "<group>"; };
1D051A25156A4138007BFE40 /* RKJSONParserJSONKit+TestAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RKJSONParserJSONKit+TestAdditions.m"; sourceTree = "<group>"; };
1D051A28156A415D007BFE40 /* SearchResultsGroupingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SearchResultsGroupingSpec.m; sourceTree = "<group>"; };
+ 1D051A2F156A6323007BFE40 /* UPCSearchResultGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UPCSearchResultGroup.h; sourceTree = "<group>"; };
+ 1D051A30156A6323007BFE40 /* UPCSearchResultGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UPCSearchResultGroup.m; sourceTree = "<group>"; };
1D0956B41563A704008C69E3 /* UPC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UPC.app; sourceTree = BUILT_PRODUCTS_DIR; };
1D0956B81563A704008C69E3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
1D0956BA1563A704008C69E3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -371,6 +374,8 @@
children = (
1DD707311566851A00346AE0 /* UPCSearchResult.h */,
1DD707321566851A00346AE0 /* UPCSearchResult.m */,
+ 1D051A2F156A6323007BFE40 /* UPCSearchResultGroup.h */,
+ 1D051A30156A6323007BFE40 /* UPCSearchResultGroup.m */,
);
path = models;
sourceTree = "<group>";
@@ -569,6 +574,7 @@
1DD707331566851A00346AE0 /* UPCSearchResult.m in Sources */,
1DD7077A1566890B00346AE0 /* UPCRestKitConfigurator.m in Sources */,
1D051A1F156A4078007BFE40 /* NSArray+SearchResultsGrouping.m in Sources */,
+ 1D051A31156A6323007BFE40 /* UPCSearchResultGroup.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -11,7 +11,7 @@
#import "RestKit/RestKit.h"
-@interface UPCMapsViewController : UIViewController <UISearchBarDelegate, RKObjectLoaderDelegate>
+@interface UPCMapsViewController : UIViewController <UISearchBarDelegate, RKObjectLoaderDelegate, MKMapViewDelegate>
@property (strong, nonatomic) IBOutlet MKMapView *mapView;
@@ -9,6 +9,8 @@
#import "UPCMapsViewController.h"
#import "UPCRestKitConfigurator.h"
#import "UPCSearchResult.h"
+#import "UPCSearchResultGroup.h"
+#import "NSArray+SearchResultsGrouping.h"
#pragma mark Class implementation
@@ -35,14 +37,42 @@ - (void)viewDidUnload
#pragma mark Search bar
+- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
+{
+ static NSString *SEARCH_RESULT = @"SEARCH_RESULT";
+
+ if ([annotation isKindOfClass:[UPCSearchResultGroup class]]) {
+ MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:SEARCH_RESULT];
+ if (!annotationView) {
+ annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:SEARCH_RESULT];
+ annotationView.canShowCallout = YES;
+ annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
+ annotationView.pinColor = MKPinAnnotationColorRed;
+ annotationView.animatesDrop = YES;
+ }
+ else {
+ annotationView.annotation = annotation;
+ }
+ return annotationView;
+ }
+ else {
+ return nil;
+ }
+}
+
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error
{
NSLog(@"Error while loading search results!");
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
- NSLog(@"Search result ok, with %d results", [objects count]);
+ [self.mapView removeAnnotations:self.mapView.annotations];
+ NSDictionary *groupedSearchResults = [objects groupByLocation];
+ [groupedSearchResults enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
+ NSArray *searchResultsInLocation = (NSArray *)obj;
+ [self.mapView addAnnotation:[[UPCSearchResultGroup alloc] initWithSearchResults:searchResultsInLocation]];
+ }];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
@@ -7,8 +7,24 @@
//
#import <Foundation/Foundation.h>
+#import <MapKit/MapKit.h>
+#pragma mark UPCLocation interface
+
+@interface UPCLocation : NSObject <NSCopying>
+
+@property (strong, nonatomic, readonly) NSNumber *latitude;
+@property (strong, nonatomic, readonly) NSNumber *longitude;
+@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
+
+- (id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude;
+
+@end
+
+
+#pragma mark NSArray category
+
@interface NSArray (SearchResultsGrouping)
- (NSDictionary *)groupByLocation;
@@ -10,6 +10,68 @@
#import "UPCSearchResult.h"
+#pragma mark UPCLocation class implementation
+
+@implementation UPCLocation
+
+#pragma mark Synthesized properties
+
+@synthesize latitude = _latitude;
+@synthesize longitude = _longitude;
+
+#pragma mark Init and dealloc
+
+- (id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude
+{
+ self = [super init];
+ if (self) {
+ self->_latitude = [NSNumber numberWithDouble:latitude];
+ self->_longitude = [NSNumber numberWithDouble:longitude];
+ }
+ return self;
+}
+
+#pragma mark Coordinate
+
+- (CLLocationCoordinate2D)coordinate
+{
+ return CLLocationCoordinate2DMake([self.latitude doubleValue], [self.longitude doubleValue]);
+}
+
+#pragma mark Methods to behave as dictionary key
+
+- (BOOL)isEqual:(id)object
+{
+ if (self == object) {
+ return YES;
+ }
+ else if ([object isMemberOfClass:[self class]]) {
+ UPCLocation *location = (UPCLocation *)object;
+ return [self.latitude isEqualToNumber:location.latitude] && [self.longitude isEqualToNumber:location.longitude];
+ }
+ else {
+ return NO;
+ }
+}
+
+- (NSUInteger)hash
+{
+ return [self.latitude unsignedIntegerValue] ^ [self.longitude unsignedIntegerValue];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+ UPCLocation *copiedLocation = [[UPCLocation allocWithZone:zone] init];
+ copiedLocation->_latitude = self.latitude;
+ copiedLocation->_longitude = self.longitude;
+ return copiedLocation;
+}
+
+@end
+
+
+# pragma mark - Category implementation
+
@implementation NSArray (SearchResultsGrouping)
- (NSDictionary *)groupByLocation
@@ -18,7 +80,7 @@ - (NSDictionary *)groupByLocation
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UPCSearchResult class]]) {
UPCSearchResult *searchResult = (UPCSearchResult *)obj;
- CLLocation *searchResultLocation = [[CLLocation alloc] initWithLatitude:searchResult.latitude longitude:searchResult.longitude];
+ UPCLocation *searchResultLocation = [[UPCLocation alloc] initWithLatitude:searchResult.latitude longitude:searchResult.longitude];
NSMutableArray *searchResultsInSameLocation = [groupedSearchResults objectForKey:searchResultLocation];
if (!searchResultsInSameLocation) {
searchResultsInSameLocation = [[NSMutableArray alloc] init];
@@ -7,7 +7,6 @@
//
#import <Foundation/Foundation.h>
-#import <CoreLocation/CLLocation.h>
extern NSString * const BUILDING_TYPE;
@@ -21,6 +20,5 @@ extern NSString * const UNIT_TYPE;
@property (strong, nonatomic) NSString *name;
@property (nonatomic) double latitude;
@property (nonatomic) double longitude;
-@property (readonly, nonatomic) CLLocationCoordinate2D location;
@end
@@ -25,9 +25,4 @@ @implementation UPCSearchResult
@synthesize latitude;
@synthesize longitude;
-- (CLLocationCoordinate2D)location
-{
- return CLLocationCoordinate2DMake(self.latitude, self.longitude);
-}
-
@end
@@ -0,0 +1,19 @@
+//
+// UPCSearchResultGroup.h
+// UPC
+//
+// Created by Jose Gonzalez Gomez on 21/05/12.
+// Copyright (c) 2012 Universitat Politècnica de Catalunya. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <MapKit/MapKit.h>
+
+
+@interface UPCSearchResultGroup : NSObject <MKAnnotation>
+
+@property (copy, nonatomic, readonly) NSArray *searchResults;
+
+- (id) initWithSearchResults:(NSArray *)searchResults;
+
+@end
@@ -0,0 +1,63 @@
+//
+// UPCSearchResultGroup.m
+// UPC
+//
+// Created by Jose Gonzalez Gomez on 21/05/12.
+// Copyright (c) 2012 Universitat Politècnica de Catalunya. All rights reserved.
+//
+
+#import "UPCSearchResultGroup.h"
+#import "UPCSearchResult.h"
+
+
+#pragma mark Class extension
+
+@interface UPCSearchResultGroup ()
+@property (nonatomic) CLLocationCoordinate2D coordinate;
+@end
+
+
+#pragma mark Class implementation
+
+@implementation UPCSearchResultGroup
+
+#pragma mark Synthesized properties
+
+@synthesize searchResults = _searchResults;
+@synthesize coordinate = _coordinate;
+
+#pragma mark Init and dealloc
+
+- (id)initWithSearchResults:(NSArray *)searchResults
+{
+ self = [super init];
+ if (self) {
+ self->_searchResults = searchResults;
+ }
+ return self;
+}
+
+#pragma mark Annotation methods
+
+- (CLLocationCoordinate2D)coordinate
+{
+ UPCSearchResult *searchResult = (UPCSearchResult *)[self.searchResults objectAtIndex:0];
+ return CLLocationCoordinate2DMake(searchResult.latitude, searchResult.longitude);
+}
+
+- (NSString *)title
+{
+ return ((UPCSearchResult *)[self.searchResults objectAtIndex:0]).name;
+}
+
+- (NSString *)subtitle
+{
+ if ([self.searchResults count] > 1) {
+ return [NSString stringWithFormat:@"i %u resultat(s) mès", [self.searchResults count] - 1];
+ }
+ else {
+ return nil;
+ }
+}
+
+@end
@@ -9,6 +9,7 @@
#import "Kiwi.h"
#import "NSArray+SearchResultsGrouping.h"
#import "UPCSearchResult.h"
+#import <MapKit/MapKit.h>
SPEC_BEGIN(SearchResultsGroupingSpec)
@@ -36,8 +37,8 @@
__block NSArray *searchResults;
beforeAll(^{
- location1 = CLLocationCoordinate2DMake( 0, 0);
- location2 = CLLocationCoordinate2DMake(45, 45);
+ location1 = CLLocationCoordinate2DMake( 0.2894023, 0.9899812);
+ location2 = CLLocationCoordinate2DMake(12.1578094, -5.0914832);
UPCSearchResult *searchResult1 = [[UPCSearchResult alloc] init];
searchResult1.identifier = @"1";
@@ -60,7 +61,7 @@
it(@"should group the results with the same location", ^{
[groupedSearchResults enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
- CLLocation *location = (CLLocation *)key;
+ UPCLocation *location = (UPCLocation *)key;
NSArray *searchResultsInLocation = (NSArray *)obj;
[searchResultsInLocation enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UPCSearchResult *searchResult = (UPCSearchResult *)obj;
@@ -70,6 +71,10 @@
}];
});
+ it(@"should return the correct number of groups", ^{
+ [[theValue([groupedSearchResults count]) should] equal:theValue(2)];
+ });
+
context(@"", ^{
__block NSMutableArray *ungroupedSearchResults;
@@ -88,7 +93,7 @@
});
it(@"should return the same results from the original array", ^{
- [[[NSSet setWithArray:searchResults] should] equal:[NSSet setWithArray:ungroupedSearchResults]];
+ [[[NSSet setWithArray:ungroupedSearchResults] should] equal:[NSSet setWithArray:searchResults]];
});
});
});

0 comments on commit b3916e1

Please sign in to comment.