Add subtitle to annotation using UICRouteAnnotation - iphone

UICRouteAnnotation *startAnnotation = [[UICRouteAnnotation alloc] initWithCoordinate [[routePoints objectAtIndex:0] coordinate]
title:#"Origin"
subtitle:#"Subtitle Here"
annotationType:UICRouteAnnotationTypeStart];
I am trying to add a subtitle to this annotation but don't have much experience with UICRouteAnnotation and was not able to find much documentation on it. Adding "subtitle:" through exceptions.
What am I missing? Why doesn't the subtitle work when doing it like this?

What I didn't realize is that UICRouteAnnotation needed to be modified to accept a subtitle. Here is my updated h and m files for UICRouteAnnotation. Making the below changes fixed my issue so the code I posted in my question works as intended.
Thanks Anna for pointing me in the right direction.
.h file
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
typedef enum UICRouteAnnotationType {
UICRouteAnnotationTypeStart,
UICRouteAnnotationTypeEnd,
UICRouteAnnotationTypeWayPoint,
} UICRouteAnnotationType;
#interface UICRouteAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
UICRouteAnnotationType annotationType;
}
#property (nonatomic) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) UICRouteAnnotationType annotationType;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord
title:(NSString *)aTitle
subtitle:(NSString *)aSubTitle
annotationType:(UICRouteAnnotationType)type;
#end
.m file
#import "UICRouteAnnotation.h"
#implementation UICRouteAnnotation
#synthesize coordinate;
#synthesize title;
#synthesize subtitle;
#synthesize annotationType;
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord
title:(NSString *)aTitle
subtitle:(NSString *)aSubTitle
annotationType:(UICRouteAnnotationType)type {
self = [super init];
if (self != nil) {
coordinate = coord;
title = [aTitle retain];
subtitle = [aSubTitle retain];
annotationType = type;
}
return self;
}
- (void)dealloc {
[title release];
[subtitle release];
[super dealloc];
}
#end

Related

Importing NSMutable Array into Map Annotations

Hi all i have a mysql database that consists of 7 columns and i have a script that reads it and extracts the data as JSON which i have pulled into an NSMutableArray, I want to be able to use this array to setup annotations on my Map but i'm not sure what to do here, as you can see i have defined one annotation here which shows up no problem but i'm honestly not sure how to show the NSMutableArray items? The NSMutable array will have more information than needed for the Annotations, I only need, coordinate, title and subtitle so how can i go about doing this? Here is my code so far:
hazards.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Hazards : NSObject <MKAnnotation>
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, strong) NSString * ID;
#property (nonatomic, strong) NSString * ROUTE;
#property (nonatomic, strong) NSString * ADDRESS;
#property (nonatomic, strong) NSString * LATITUDE;
#property (nonatomic, strong) NSString * LONGITUDE;
#property (nonatomic, strong) NSString * HAZARD;
#property (nonatomic, strong) NSString * RISK;
// Methods
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK;
#end
hazards.m
#import "Hazards.h"
#implementation Hazards
#synthesize coordinate, title, subtitle, ID, ROUTE, ADDRESS, LATITUDE, LONGITUDE, HAZARD, RISK;
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK {
self = [super init];
if (self)
{
ID = hazardsID;
ROUTE = hazardsROUTE;
ADDRESS = hazardsADDRESS;
LATITUDE = hazardsLATITUDE;
LONGITUDE = hazardsLONGITUDE;
HAZARD = hazardsHAZARD;
RISK = hazardsRISK;
}
return self;
}
#end
viewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "Hazards.h"
#interface ViewController : UIViewController
#property (nonatomic, strong) NSMutableArray *json;
#property (nonatomic, strong) NSMutableArray *hazardsArray;
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#pragma mark - Methods
-(void) retrieveData;
#end
viewController.m
#import "ViewController.h"
#import "Hazards.h"
#interface ViewController ()
#end
// Railway Street Ballymena Coordinates
#define BALLYMENA_LATITUDE 54.857719;
#define BALLYMENA_LONGITUDE -6.280654;
// Span
#define THE_SPAN 0.01f;
#define getDataURL #"localhost:8888/rmb/json.php"
#implementation ViewController
#synthesize json, hazardsArray, mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Create the region
MKCoordinateRegion myRegion;
// Center
CLLocationCoordinate2D center;
center.latitude = BALLYMENA_LATITUDE;
center.longitude = BALLYMENA_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = center;
myRegion.span = span;
// Set our mapview
[mapView setRegion:myRegion animated: YES];
// Annotation
NSMutableArray *locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Hazards *myAnn;
// Pin to show Royal Mail Ballymena delivery office
myAnn = [[Hazards alloc] init];
location.latitude = BALLYMENA_LATITUDE;
location.longitude = BALLYMENA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = #"Royal Mail Ballymena";
myAnn.subtitle = #"111, Railway Street";
[locations addObject:myAnn];
[self.mapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Methods
-(void) retrieveData {
NSURL *url = [NSURL URLWithString:getDataURL];
NSData *data = [NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Setup our hazards array
hazardsArray = [[NSMutableArray alloc] init];
for (int i =0; i < json.count; i++) {
// Create hazard object
NSString *hazardsID = [[json objectAtIndex:i] objectForKey:#"ID"];
NSString *hazardsROUTE = [[json objectAtIndex:i] objectForKey:#"ROUTE"];
NSString *hazardsADDRESS = [[json objectAtIndex:i] objectForKey:#"ADDRESS"];
NSString *hazardsLATITUDE = [[json objectAtIndex:i] objectForKey:#"LATITUDE"];
NSString *hazardsLONGITUDE = [[json objectAtIndex:i] objectForKey:#"LONGITUDE"];
NSString *hazardsHAZARD = [[json objectAtIndex:i] objectForKey:#"HAZARD"];
NSString *hazardsRISK = [[json objectAtIndex:i] objectForKey:#"RISK"];
Hazards *myHazards = [[Hazards alloc] initWithID:hazardsID andROUTE:hazardsROUTE andADDRESS:hazardsADDRESS andLATITUDE:hazardsLATITUDE andLONGITUDE:hazardsLONGITUDE andHAZARD:hazardsHAZARD andRISK:hazardsRISK];
// Add our hazards object to our hazards array
[hazardsArray addObject:myHazards];
}
// [self.mapView addAnnotation:hazardsArray];
}
#end
Many Thanks in Advance
Assuming your retrieveData correctly builds Hazard objects and is called at the right time you could either add them one at a time with this line inside the loop
[self.mapView addAnnotation:myHazards];
or all at once after the loop is finished
[self.mapView addAnnotations:hazardsArray];

simple question - sending NSString to another class

//StringStringViewController.h
#import <UIKit/UIKit.h>
#import "MyClass.h"
#interface SendStringViewController : UIViewController {
NSString *string1;
MyClass *secondview;
}
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) MyClass *secondview;
-(IBAction)sendString1:(id)sender;
#end
// SendStringViewController.m
#import "SendStringViewController.h"
#implementation SendStringViewController
#synthesize string1;
#synthesize secondview;
-(IBAction)sendString1:(id)sender {
string1 = #"firststring";
secondview.string2 = string1;
MyClass *mc = [[MyClass alloc]init];
[self presentModalViewController:mc animated:YES];
}
#end
// MyClass.h
#import <UIKit/UIKit.h>
#interface MyClass : UIViewController {
NSString *string2;
}
#property (nonatomic, retain) NSString *string2;
#end
// MyClass.m
#import "MyClass.h"
#implementation MyClass
#synthesize string2;
- (void)viewDidLoad {
NSLog(#"%#", string2);
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
#end
I know it's a simple and easy task but I'm having hard time googling it, because it's way too easy.
Here's the link of my project too.
Thanks.
http://dl.dropbox.com/u/12439052/SendString.zip
Edit: the question is on the title actually but how do i send the value of string1 to string2 cause currently when i nslog the string2 only null comes out
-(IBAction)sendString1:(id)sender {
string1 = #"firststring";
MyClass *mc = [[MyClass alloc]init];
mc.string2 = string1;
[self presentModalViewController:mc animated:YES];
}

Getting leaks from substringWithRange

I'm getting a leak from using substringWithRange as shown in the line of code below. I though all these functions were Autorelease and you didnt need to alloc/release them manually.
NSCFString is the object being leaked.
What is it I am doing wrong?
aLTR.drew = [substring substringWithRange:NSMakeRange(match.location+1, (match2.location-(match.location+1)))];
What I am trying to do is extract a substring and store it into my storage class. Code for that below.
#import <Foundation/Foundation.h>
#interface LeagueTableRow : NSObject
{
NSString *_teamName;
NSString *_played;
NSString *_won;
NSString *_drew;
NSString *_lost;
NSString *_goalsFor;
NSString *_goalsAgainst;
NSString *_points;
}
#property(nonatomic, copy) NSString *teamName;
#property(nonatomic, copy) NSString *played;
#property(nonatomic, copy) NSString *won;
#property(nonatomic, copy) NSString *drew;
#property(nonatomic, copy) NSString *lost;
#property(nonatomic, copy) NSString *goalsFor;
#property(nonatomic, copy) NSString *goalsAgainst;
#property(nonatomic, copy) NSString *points;
-(id)init;
#end
#import "LeagueTableRow.h"
#implementation LeagueTableRow
#synthesize teamName = _teamName;
#synthesize played = _played;
#synthesize won = _won;
#synthesize drew = _drew;
#synthesize lost = _lost;
#synthesize goalsFor = _goalsFor;
#synthesize goalsAgainst = _goalsAgainst;
#synthesize points = _points;
-(id)init
{
self = [super init];
return self;
}
-(void) dealloc
{
self.teamName = nil;
self.played = nil;
self.won = nil;
self.drew = nil;
self.lost = nil;
self.goalsFor = nil;
self.goalsAgainst = nil;
self.points = nil;
[super dealloc];
}
#end
I'm quiet surprised I got some leaks I though I was managing the memory quiet tidily.
Thanks for the advice and tips.
-Code
In your dealloc, simply release all the string ivars:
[_teamName release];
etc...
Alternatively, you could do:
[self.teamName release];
etc...
I prefer to use the ivars directly, in such situations.

MapKit crashes - unrecognized selector sent to instance

I'm trying to add pin/address annotations in my Google maps view. When I do this everyting works fine:
[self addPin: CLLocationCoordinate2DMake(lat, lng) title: #"test" subtitle: #"test"];
with:
- (void) addPin: (CLLocationCoordinate2D) position title: (NSString *) pinTitle subtitle: (NSString *) pinSubtitle{
AddressAnnotation *addAnnotation = [[AddressAnnotation alloc] initWithTitle:pinTitle andCoordinate:position andSubtitle:pinSubtitle];
[mapView addAnnotation:addAnnotation];
[addAnnotation autorelease];
}
and
#import "AddressAnnotation.h"
#implementation AddressAnnotation
#synthesize title, coordinate, subtitle;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d andSubtitle:(NSString *)sbtitle {
[super init];
title = ttl;
coordinate = c2d;
subtitle = sbtitle;
return self;
}
- (void)dealloc {
[title release];
[super dealloc];
}
#end
with:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface AddressAnnotation : NSObject <MKAnnotation> {
NSString *title;
CLLocationCoordinate2D coordinate;
NSString *subtitle;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d andSubtitle:(NSString *)sbtitle;
#end
things go wrong when I do this:
NSString *detailTitle = [NSString stringWithFormat:#"%#", [key objectForKey:#"name"]];
NSString *detailSubtitle = [NSString stringWithFormat:#"%#", [key objectForKey:#"vicinity"]];
NSLog(#"%#", detailSubtitle);
[self addPin: CLLocationCoordinate2DMake(lat, lng) title: detailTitle subtitle: detailSubtitle];
The app chrases somethimes when the pins are supposed to go in my view and somethimes this error:
'NSInvalidArgumentException', reason: '-[NSCFNumber length]: unrecognized selector sent to instance 0x5851c80'
Try changing your init function from AddressAnnotation.m to
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d andSubtitle:(NSString *)sbtitle {
self = [super init];
if (self) {
self.title = ttl;
self.coordinate = c2d;
self.subtitle = sbtitle;
}
return self;
}
You are using the instance variables directly to set the values in the class instance and not the properties so the actual values that you pass are not copied hence not retained.
NSCFNumber is one of the private implementations of NSNumber. NSNumber does not have a method called length, so it does not recognize the selector. So far so good.
It is hard to tell where this NSNumber is being used. ISTM that the problem is not in your code. I don't know enough of MapKit to give you a workaround.

How to add another annotation in the mapview a certain distance from current location

Wondering how to add another annotation in the mapview a certain distance from current location?
you can use below sample code;
// .h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface AddressAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
MKPinAnnotationColor pinColor;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *subtitle;
#property (nonatomic, assign) MKPinAnnotationColor pinColor;
#end
// .m
#import "AddressAnnotation.h"
#implementation AddressAnnotation
#synthesize coordinate;
#synthesize title;
#synthesize subtitle;
#synthesize pinColor;
- (NSString *)subtitle{
return subtitle;
}
- (NSString *)title{
return title;
}
-(id)initWithCoordinate:(CLLocationCoordinate2D) c{
coordinate=c;
return self;
}
#end
currentLocation.latitude = latitudeValue;
currentLocation.longitude = longitudeValue;
AddressAnnotation *addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:currentLocation];
[addAnnotation setTitle:#"Title"];
[addAnnotation setPinColor:MKPinAnnotationColorGreen];
[map addAnnotation:addAnnotation];
[addAnnotation release];
otherLocation.latitude = latitudeValue;
otherLocation.longitude = longitudeValue;
addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:otherLocation];
[addAnnotation setTitle:#"otherTitle"];
[map addAnnotation:addAnnotation];
[addAnnotation release];