Re-using this code for multiple mapkit pin annotations - ios

I have this code below working perfectly for a unique Pin and one annotation. I want to adapt it without too many changes to display more Pins, locations and annotations.
There is a class called MyAnnotationPins with the following lines:
MyAnnotationPins.h
#interface MyAnnotationPins : NSObject < MKAnnotation>
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
-(id)initWithCoordinate:(CLLocationCoordinate2D)annotCoordinate title:(NSString*)annotTitle subtitle:(NSString*)annotSubtitle;
MyAnnotationPins.m
#synthesize coordinate;
#synthesize subtitle;
#synthesize title;
-(id)initWithCoordinate:(CLLocationCoordinate2D)annotCoordinate title:(NSString*)annotTitle subtitle:(NSString*)annotSubtitle
{
self = [super init];
if (self)
{
coordinate = annotCoordinate;
subtitle = [[NSString alloc] initWithString:annotSubtitle];
title = [[NSString alloc] initWithString:annotTitle];
}
return self;
}
And at the view controller the following code:
SecondViewController.h
import "MyAnnotationPins.h"
#interface SecondViewController : UIViewController < MKMapViewDelegate >
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) MyAnnotationPins* biblioAnnotation;
At the SecondViewController.m the implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
mapView.delegate = self;
MKCoordinateRegion mapRegion;
mapRegion.center.latitude=-18.924129;
mapRegion.center.longitude=-48.283963;
mapRegion.span.latitudeDelta=0.2;
mapRegion.span.longitudeDelta=0.2;
[mapView setRegion:mapRegion animated:YES];
///// This is just for One annotaion/Pin on Map /////
CLLocationCoordinate2D parliamentLocation = CLLocationCoordinate2DMake(-18.924129, -48.283963);
biblioAnnotation = [[MyAnnotationPins alloc]
initWithCoordinate:parliamentLocation
title:#"Ponto Biblioteca"
subtitle:#"Taxi proximo"];
[mapView addAnnotation:biblioAnnotation];
If you want more than one pin and annotaion copy the CLLocation instance below and change the following atributes
CLLocationCoordinate2D secondLocation = CLLocationCoordinate2DMake(another latitude, another longitude);
secondAnnotation = [[MyAnnotationPins alloc]
initWithCoordinate:secondLocation
title:#"Second Title"
subtitle:#"Second subtitle"];
[mapView addAnnotation:secondAnnotation]; <code>
And so on for the third, fourth fifth etc. Do not forget to create the secondLocation proerty at your view controller like the first one in SecondViewController.h and also
#synthesize secondAnnotation property at SecondViewController.m file
#property (strong, nonatomic) MyAnnotationPins* secondAnnotation;

Add them in a loop like so
for(X in Y)
{
CLLocationCoordinate2D parliamentLocation = CLLocationCoordinate2DMake(-18.924129, -48.283963);
MyAnnotationPins* biblioAnnotation = [[MyAnnotationPins alloc]
initWithCoordinate:parliamentLocation
title:#"Ponto Biblioteca"
subtitle:#"Taxi proximo"];
[mapView addAnnotation:biblioAnnotation];
}
As you loop through your list you can get the right coordinates and title for each one. This way you list can grow or shrink and you won't need to add third, fourth or fifth annotation properties.

Related

Measuring the distance between latest coordinates with a fixed one in iOS showing larger distance while they are very near

I am getting inaccurate result while measuring distance between latest coordinate and some a fixed coordinate which can be done by taping on the "Set fixed location" button.
Initially the distance is 0.0 meter as no location is fixed which is the first screenshoot below. Once I tap on the "Set fix location" button, it sets the the coordinate where I am standing at the time of pressing the button and the distance is immediately started calculated which is in the second screenshoot.
When I walk around 10 meters or more and come back to the position where I took the initial fixed location coordinate, its showing me more than 7 meters distance, although it should be less than half meter. I am testing this demo app outside in an open ground.
I have pasted all my code below and could you please help me to fixed the issue? I am new in GPS location related world and please kindly let me know if I am missing anything in the code. Are there any other ways to achieve more accurate result? I have been checking many stack-overflow articles and none help me to improve in my case.
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) CLLocation *fixedLocation;
#property (strong, nonatomic) CLLocation *latestLocation;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *fixedLocationLatitude;
#property (weak, nonatomic) IBOutlet UILabel *fixedLocationLongitude;
#property (weak, nonatomic) IBOutlet UILabel *latestLocationLatitude;
#property (weak, nonatomic) IBOutlet UILabel *latestLocationLongitude;
#property (weak, nonatomic) IBOutlet UILabel *distanceBetweenLocations;
- (IBAction)setFixLocation:(UIButton *)sender;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//self.fixedLocation = [[CLLocation alloc] initWithLatitude:90.0 longitude:0.0]; // North pole if no location is fixed for the first time
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
if([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]){
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
if(locations.lastObject!=nil){
self.latestLocation = locations.lastObject;
self.latestLocationLatitude.text = [NSString stringWithFormat:#"%.8f", self.latestLocation.coordinate.latitude];
self.latestLocationLongitude.text = [NSString stringWithFormat:#"%.8f", self.latestLocation.coordinate.longitude];
}
if(self.fixedLocation != nil && self.latestLocation != nil){
CLLocationDistance distanceInMeter = [self.latestLocation distanceFromLocation:self.fixedLocation];
self.distanceBetweenLocations.text = [NSString stringWithFormat:#"%.2f",distanceInMeter] ;
} else {
self.distanceBetweenLocations.text = [NSString stringWithFormat:#"%.f",0.0] ;
}
}
- (IBAction)setFixLocation:(UIButton *)sender {
if(self.locationManager.location != nil){
self.fixedLocation = self.locationManager.location;
self.fixedLocationLatitude.text = [NSString stringWithFormat:#"%.8f", self.fixedLocation.coordinate.latitude];
self.fixedLocationLongitude.text = [NSString stringWithFormat:#"%.8f", self.fixedLocation.coordinate.longitude];
}
}
#end

The Pin is not working

My Map shows a pin on a specific place but it's not showing the pin
Here is the code
WadiRumViewControllerJordan.h
#import <UIKit/UIKit.h>
#include <MapKit/MapKit.h>
#interface WadiRumViewControllerJordan : UIViewController
#property (strong, nonatomic) IBOutlet MKMapView *WadiRumMapView;
#end
WadiRumViewControllerJordan.m
#import "WadiRumViewControllerJordan.h"
#import "WadiRumNSOjectPIN.h"
#interface WadiRumViewControllerJordan ()
#end
//Wadi Rum Coordinates
#define WadiRum_Latitude 29.537355
#define WidiRum_longtitude 35.415026
//Wadi Rum Span
#define WadiRumSpan 0.01f;
#implementation WadiRumViewControllerJordan
#synthesize WadiRumMapView;
- (void)viewDidLoad {
[super viewDidLoad];
//Create WadiRum Region
MKCoordinateRegion WadiRumRegion;
//Center
CLLocationCoordinate2D center;
center.latitude = WadiRum_Latitude;
center.longitude = WidiRum_longtitude;
//Span
MKCoordinateSpan span;
span.latitudeDelta = WadiRum_Latitude;
span.longitudeDelta = WidiRum_longtitude;
WadiRumRegion.center = center;
WadiRumRegion.span = span;
//Set our map
[WadiRumMapView setRegion:WadiRumRegion animated:YES];
//WadiRumNSObjectPIN
//1. Create a coordinate for the use of WadiRum
CLLocationCoordinate2D WadiRumLocation;
WadiRumLocation.latitude = WadiRum_Latitude;
WadiRumLocation.longitude = WidiRum_longtitude;
WadiRumNSOjectPIN * WadiRumAnnitation = [[WadiRumNSOjectPIN alloc] init];
WadiRumAnnitation.coordinate = WadiRumLocation;
WadiRumAnnitation.title = #"Services";
WadiRumAnnitation.subtitle = #"Desert";
{[self.WadiRumMapView addAnnotation:WadiRumAnnitation];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be WadiRumNSOjectPIN
}
#end
WadiRumNSOjectPIN.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface WadiRumNSOjectPIN : NSObject <MKAnnotation>
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString * title;
#property(nonatomic, copy) NSString * subtitle;
#end
WadiRumNSOjectPIN.m
#import "WadiRumNSOjectPIN.h"
#implementation WadiRumNSOjectPIN
#synthesize coordinate;
- (id)initWithLocation:(CLLocationCoordinate2D)coord {
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
#synthesize coordinate, title, subtitle;
#end
I edited the code above to make it exactly like what I want, I got this error in the picture bellow
In order to conform to MKAnnotation, you must have properties called coordinate, title and subtitle. You've added three extra properties, ttcoordinate, tttitle, and ttsubtitle, but MKAnnotation is going to ignore those, and will look for coordinate, title, and subtitle.
The key reason you're not seeing your annotation is that you're setting ttcoordinate in viewDidLoad. But MKAnnotation will not use that, but rather will refer to the coordinate property you synthesized, but never set. (You do have an initWithLocation method, which suggests you were going to update coordinate, but you never call that.)
Bottom line, I would suggest renaming ttcoordinate, ttitle and ttsubtitle to coordinate, title, and subtitle, and updating all of those references accordingly, and that should fix everything. And you can retire the #synthesize line.

Problems in adding object from one view to a mutableArray in another view

Hi everyone I have been building an app and have met some problems.
My app has two viewControllers. One is MenuViewController and another one is MainViewController.
I want to pass a string from MainViewController to a mutableArray in MenuViewController, but have no idea how.
Here are my codes:
<MenuViewController.h>
#import <UIKit/UIKit.h>
#interface MenuViewController : UITableViewController {
NSMutableArray *secondFavourite;
}
#property (nonatomic, strong) NSMutableArray *secondFavourite;
#end
.
<MenuViewController.m>
#import "MenuViewController.h"
#import "MainViewController.h"
#interface MenuViewController ()
#property (strong, nonatomic) NSArray *menu;
#end
#implementation MenuViewController
#synthesize menu;
#synthesize secondFavourite;
- (void)viewDidLoad
{
[super viewDidLoad];
self.secondFavourite = [[NSMutableArray alloc] init];
self.menu = self.secondFavourite;
}
.
<MainViewController.h>
#import <UIKit/UIKit.h>
#import <social/Social.h>
#interface MainViewController : UIViewController {
IBOutlet UIImageView *imagepost;
UILabel *predictionLabel;
}
- (IBAction)sampleSelector:(UIButton *)sender;
- (IBAction)showAllClick:(id)sender;
#property (nonatomic, retain) IBOutlet UILabel *predictionLabel;
#property (strong, nonatomic) NSArray *predictionArray;
#property (strong, nonatomic) UIButton *menuBtn;
#property (strong, nonatomic) NSMutableArray *fav;
#property (strong, nonatomic) IBOutlet UILabel *favLabel;
#property (strong, nonatomic) IBOutlet UITableView* tableView;
#property (nonatomic, strong) NSMutableArray *favourite;
#end
.
<MainViewController.m>
- (void)viewDidLoad
{
[super viewDidLoad];
self.predictionArray = [[NSArray alloc] initWithObjects:#"Hey gurl", nil];
}
//Add to favourite
- (void) addToFav {
self.favourite = [[NSMutableArray alloc] init];
[self.favourite addObject:self.predictionLabel.text];
[self.tableView reloadData];
NSLog(#"%#", self.favourite);
}
//add to favourite button action
- (IBAction)addToFavButton:(id)sender {
[self addToFav];
//pass data from favourite here to secondFacourite in MenuViewController (found on stack overflow)
MenuViewController *menuViewController = [[MenuViewController alloc]initWithNibName:#"MenuViewController" bundle:nil];
menuViewController.secondFavourite = [[NSMutableArray alloc]initWithArray:self.favourite];
[self.navigationController pushViewController:menuViewController animated:YES];
}
I used NSLog to check that the menuViewController.secondFavourite in MainViewController successfully added the string into the array, isn't the array the same array in MenuViewController? Why doesn't the menu.tableView update and show the new string added? I am very confused and I hope someone will help me out.
Thanks for reading this.
This has to do with the fact that your menu viewDidLoad is overwriting the value in these two lines:
self.secondFavourite = [[NSMutableArray alloc] init];
self.menu = self.secondFavourite;
That first line is setting your secondFavourite property to an empty NSMutableArray instance. And since viewDidLoad will be called only after the view has been loaded into memory (in this case, when you try to push the view controller onto the stack), your initial values in the secondFavourite property will be lost.
Instead, you should move that initialization code into the an init method.

Pass the selected location from one map to another map view, iOS 7

I have the singleton class that stores the property - selected location (MKPointAnnotation). This location is set from the first map view by the user. However, I don't grasp why this property is null? Here the code.
Link to the project
The selected pieces of the code.
Class where I store information about the selected place:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface GeoChatInformationAboutTheSelectedPlace : NSObject <MKMapViewDelegate>
//create object that mimic the Place with the required information
#property (nonatomic) NSUInteger numberOfThePostsForTheSelectedLocation;
#property (nonatomic, strong) MKPointAnnotation *annotation;
+(GeoChatInformationAboutTheSelectedPlace *)returnInstance;
#end
//implementation of the above class
#import "GeoChatInformationAboutTheSelectedPlace.h"
#implementation GeoChatInformationAboutTheSelectedPlace
static GeoChatInformationAboutTheSelectedPlace *info=NULL;
+(GeoChatInformationAboutTheSelectedPlace *)returnInstance{
if (!info){
info = [[GeoChatInformationAboutTheSelectedPlace alloc] init];
info.annotation=[[MKPointAnnotation alloc] init];
}
return info;
}
#end
How I add the selected location (based on Anna's comments):
.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "GeoChatInformationAboutTheSelectedPlace.h"
#interface GeoChatMapViewController : UIViewController <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *map;
#property (strong,nonatomic) NSMutableArray *matchingItems;
#property (strong, nonatomic) IBOutlet UITextField *textSearch;
#property (strong, nonatomic) GeoChatInformationAboutTheSelectedPlace *info;
#property (weak, nonatomic) IBOutlet UIStepper *stepper;
- (IBAction)increaseDecreaseRadiousOfTheSearch:(id)sender;
#end
/*------------part of the implementation class--------*/
//selecting the location and displaying its coordinates
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Would you like to add this location?"
message:[view.annotation title]
delegate:self
cancelButtonTitle:#"Yep!"
otherButtonTitles:#"No :(", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0) {
MKAnnotationView *selectedAnnotation=[_map.selectedAnnotations objectAtIndex:0];
if ([selectedAnnotation isKindOfClass:[MKPointAnnotation class]]) {
MKPointAnnotation *pa = (MKPointAnnotation *)selectedAnnotation;
//[_info.arrayOfTheSelectedPlaces addObject:pa];
_info.annotation=pa;
}
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_info=[GeoChatInformationAboutTheSelectedPlace returnInstance];
_map.showsUserLocation=YES;
}
How I display the selected annotation at the second map:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "GeoChatInformationAboutTheSelectedPlace.h"
#interface GeoChatProjectSavedLocationToDisplayOnMapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *map;
#property (strong, nonatomic) GeoChatInformationAboutTheSelectedPlace *info;
#property (strong, nonatomic) MKPointAnnotation *bb;
#end
/*----------------------------.m---------------------------------------*/
#import "GeoChatProjectSavedLocationToDisplayOnMapViewController.h"
#interface GeoChatProjectSavedLocationToDisplayOnMapViewController ()
#end
#implementation GeoChatProjectSavedLocationToDisplayOnMapViewController
-(void)setBb:(MKPointAnnotation *)bb{
_bb=bb;
}
-(void)setMap:(MKMapView *)map {
_map=map;
_map.delegate=self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_map.showsUserLocation=YES;
_info=[GeoChatInformationAboutTheSelectedPlace returnInstance];
//displays nothing
NSLog(#"%#",[_info.annotation title]);
//however, when I write
//NSLog(#"%#",_info.annotation);
//It displays me that the object is not nill
//adds nothing to the map
[_map addAnnotation:_info.annotation];
}
#end

class -(MyAnnotation annotation) was deallocated

An instance 0x11d0ce4b0 of class -(MyAnnotation annotation) was
deallocated while key value observers were still registered with it.
Observation info was leaked, and may even become mistakenly attached
to some other object. Set a breakpoint on NSKVODeallocateBreak to stop
here in the debugger. Here's the current observation info:
But I have put a breakpoint on my dealloc method, and in there, I do deregister for those notifications. Dealloc is called, and I did check that it was the same object, and all the calls to deregister are there. So I don't know how it could not be removing the observers.
Create custom AnnotationView:
#import <MapKit/MapKit.h>
#interface AnnotationView : MKPlacemark
#property (nonatomic, readwrite, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *subtitle;
#end
And in .m file
#import "AnnotationView.h"
#implementation AnnotationView
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary *)addressDictionary
{
if ((self = [super initWithCoordinate:coordinate addressDictionary:addressDictionary]))
{
self.coordinate = coordinate;
}
return self;
}
#end
// Use Annotation Add #import "AnnotationView.h" in your relevant .m file:
CLLocationCoordinate2D pCoordinate ;
pCoordinate.latitude = LatValue;
pCoordinate.longitude = LanValue;
// Create Obj Of AnnotationView class
AnnotationView *annotation = [[AnnotationView alloc] initWithCoordinate:pCoordinate addressDictionary:nil] ;
annotation.title = #"I m Here";
annotation.subtitle = #"This is Sub Tiitle";
[self.mapView addAnnotation:annotation];
Above is simple Example of how to create AnnotationView.

Resources