For this example, we will assume you are making a real estate app since most people that want this are. It looks a little confusing at first but once you get over the scary factor, it is very easy.
You will need;
-an MKAnnotation object (this holds all the details about each object so it is easier to find)
-an MKAnnotationview object (this holds all the unique view details about the object)
-an MKMapView to put it on (this is the map itself)
we will call our annotation PropertyUnit and our annotation view called PropertyUnitView.
We have created an object called "PropertyListing" with the actual details of our property. We are linking one to one for each unit.
in PropertyUnit.h;
You will need;
-an MKAnnotation object (this holds all the details about each object so it is easier to find)
-an MKAnnotationview object (this holds all the unique view details about the object)
-an MKMapView to put it on (this is the map itself)
we will call our annotation PropertyUnit and our annotation view called PropertyUnitView.
We have created an object called "PropertyListing" with the actual details of our property. We are linking one to one for each unit.
in PropertyUnit.h;
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "PropertyListing.h"
@interface PropertyUnit : NSObject <MKAnnotation>{
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *address;
@property (nonatomic, assign) CLLocationCoordinate2D theCoordinate;
@property (nonatomic, strong) PropertyListing *property;
//propertyListing is just or actual details for the object and can be anything
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate;
- (MKMapItem*)mapItem;
@end
we need to assign information when someone clicks on the item in the map, they are commonly set as "title" and "subtitle" we are just assigning our own information to these texts.
in PropertyUnit.m;
#import "PropertyUnit.h"
#import <AddressBook/AddressBook.h>
@implementation PropertyUnit
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate {
if ((self = [super init])) {
if ([name isKindOfClass:[NSString class]]) {
self.name = name;
} else {
self.name = @"Unknown charge";
}
self.address = address;
self.theCoordinate = coordinate;
}
return self;
}
- (NSString *)title {
return _address;
}
- (NSString *)subtitle {
return [NSNumberFormatter localizedStringFromNumber:_property.price numberStyle:NSNumberFormatterCurrencyStyle];
}
- (CLLocationCoordinate2D)coordinate {
return _theCoordinate;
}
- (MKMapItem*)mapItem {
NSDictionary *addressDict = @{(NSString*)kABPersonAddressStreetKey : _address};
MKPlacemark *placemark = [[MKPlacemark alloc]
initWithCoordinate:self.coordinate
addressDictionary:addressDict];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
mapItem.name = self.title;
return mapItem;
}
@end
The views are very basic and supposedly don't even really need to exist because most of the custom details are done in the main mapview but I left it here for consistancey sake.
In PropertyUnitView.h;
#import <MapKit/MapKit.h>
#import "PropertyListing.h"
@interface PropertyUnitView : MKAnnotationView
@property (nonatomic, strong) PropertyListing *property;
@end
In PropertyUnivewView.m;
#import "PropertyUnitView.h"
@implementation PropertyUnitView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
@end
Now for the real meat and potatoes.
In MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "PropertyListing+methods.h"
#import "PropertyUnit.h"
#import "PropertyUnitView.h"
#import "PropertyInfoViewController.h"
#import "ScrollNavigationViewController.h"
#import "SearchViewController.h"
#define METERS_PER_MILE 1609.344
@interface MapViewController : UIViewController <MKMapViewDelegate> {
}
@property(nonatomic,retain) MKMapView *mapView;
@end
in MapViewController.m
@implementation MapViewController
-(id)init{
self = [super init];
if (self){
//create the mapview
_mapView = [[MKMapView alloc] init];
[self.view addSubview:_mapView];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
//iphone
_mapView.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-20, self.view.frame.size.width, self.view.frame.size.height+27);
}else{
//ipad
_mapView.frame = CGRectMake(self.view.frame.origin.x-20, self.view.frame.origin.y, 1024, self.view.frame.size.height-90);
}
_mapView.delegate = self;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_mapView.showsUserLocation = YES;
[self setDefaultTorontoView];
}
-(void)setDefaultTorontoView{
//center on the office and create a zoom level to go by.
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 43.662431;
zoomLocation.longitude= -79.383667;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 120000, 120000);
[_mapView setRegion:viewRegion animated:YES];
}
#pragma mark - unit detail methods
- (NSInteger)numberOfUnits
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][0];
return [sectionInfo numberOfObjects];
}
-(void)printframe:(CGRect)frame{
//just a way to print off the frames if needed
NSLog(@"current x:%.0f, y:%.0f, length:%.0f, height:%.0f",frame.origin.x, frame.origin.y,frame.size.width,frame.size.height);
}
#pragma mark - map delegate
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
//called Tells the delegate that one or more annotation views were added to the map.
if (existingProperties == nil){
existingProperties = [[NSMutableArray alloc] init];
}
for (PropertyUnitView *annView in views)
{
if (![existingProperties containsObject:annView]){
CGRect endFrame = annView.frame;
annView.frame = CGRectMake(endFrame.origin.x, endFrame.origin.y + endFrame.size.height, endFrame.size.width, 0);
//NSLog(@"Start point");
//[self printframe:annView.frame];
//[self printframe:endFrame];
[UIView animateWithDuration:0.5 animations:^{ annView.frame = endFrame; }];
[existingProperties addObject:annView];
}
}
}
- (PropertyUnitView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *annotationViewReuseIdentifier = @"annotationViewReuseIdentifier";
PropertyUnitView *annotationView = (PropertyUnitView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:annotationViewReuseIdentifier];
if (annotationView == nil)
{
annotationView = [[PropertyUnitView alloc] initWithAnnotation:annotation reuseIdentifier:annotationViewReuseIdentifier];
}
if ([annotation isMemberOfClass:[PropertyUnit class]]){
//if the annotation is a property
annotationView.image = [UIImage imageNamed:@"house20.png"];
annotationView.draggable = FALSE;
annotationView.canShowCallout = YES;
UIButton *goToDetail = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView = goToDetail;
} else {
//it is probably the MKUserLocation
if ([annotation isKindOfClass:[MKUserLocation class]]) {
}
}
annotationView.annotation = annotation;
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{
PropertyUnit *unit = (PropertyUnit*)view.annotation;
PropertyListing *listing = unit.property;
PropertyInfoViewController *infoView = [[PropertyInfoViewController alloc] initWithPropertyListing:listing];
[self.navigationController pushViewController:infoView animated:YES];
}
@end
No comments:
Post a Comment