MKMapView - Removing annotation causes app crash - iphone

Removing annotations from my map view in the following way:
if ([[self.mapView annotations] count] > 0)
{
[self.mapView removeAnnotations:[self.mapView annotations]];
}
causes my application to crash with the following exception:
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MKAnnotationContainerView 0xe87b420> for the key path "title" from <PFAnnotation 0x10851230> because it is not registered as an observer.'
The annotations are added in the following way:
CLLocationCoordinate2D pinPosition;
for (int index = 0; index < [array count]; index++)
{
Station *aStation = [array objectAtIndex:index];
PFAnnotation *stationPin = [[PFAnnotation alloc] init]; //StationPinView
pinPosition = CLLocationCoordinate2DMake([[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]);
stationPin.stationName = [aStation valueForKey:#"stationName"];
stationPin.stationPosition = pinPosition;
stationPin.stationLength = [aStation valueForKey:#"platformLength"];
[self.mapView addAnnotation:stationPin];
[stationPin release];
}
My PFAnnotation.h is:
#interface PFAnnotation : NSObject <MKAnnotation>
{
NSString *stationName;
CLLocationCoordinate2D stationPosition;
NSNumber *stationLength;
}
#property (nonatomic, retain) NSString *stationName;
#property CLLocationCoordinate2D stationPosition;
#property (nonatomic, retain) NSNumber *stationLength;
#end
and my PFAnnotation.m is:
#implementation PFAnnotation
#synthesize stationName;
#synthesize stationPosition;
#synthesize stationLength;
- (CLLocationCoordinate2D)coordinate;
{
return stationPosition;
}
- (NSString *)title
{
return stationName;
}
- (NSString *)subtitle
{
if (stationLength == nil)
return nil;
else
return [NSString stringWithFormat:#"Platform Length: %#ft",stationLength];
}
- (void)dealloc {
[stationName release];
[stationLength release];
[super dealloc];
}
I have read in some other threads that, setting the annotation properties from background thread is the reason for the above error. But in my case,it is not so because every thing is performed on the main thread. Please advise.

ok..solved it at last!!! I think it was due to the animation provided during addition of annotations. since there were a number of annotations that were added back-to-back with animation and also the annotations were removed just before the animation started, there could have been a reference to the released annotation(this is my guess). Moreover, the removal+addition process was made on each regionDidChangeAnimated call, which could have made a overlap between the removal and addition process. Anyway, how I solved it was that, I provided a timer which will be fired only after 1 second after every regionDidchangeAnimated to make sure that the user has done with dragging. Thus unnecessary addition+removal of annotations was avoided and I was able to avoid the crash. Thanks to all guys here for their time taken to support me, especially Guntis Treulands.

In your PFAnnotation class, did you declare both title and subtitle properties as they are in the protocol?
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html

If Your PFAnnotation really has incorrect setters getters for string values:
from here: http://cocoadevcentral.com/d/learn_objectivec/
Setter:
- (void) setCaption: (NSString*)input
{
[caption autorelease];
caption = [input retain];
}
Getter:
- (NSString*) caption
{
return caption;
}
Release:
- (void) dealloc
{
[caption release];
[super dealloc];
}
also - it's easier to provide coordinates in this way: (also works on ios 3.1.3)
stationPin.stationPosition = (CLLocationCoordinate2D) {[[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]}
than (only from ios 4)
stationPin.stationPosition = CLLocationCoordinate2DMake([[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]);

Please check whether an explicit removal of observer to the property "title" is being done anywhere in the code.

Related

How to pass annotation title to another view controller

I am new to iOS programming, and I am having trouble with passing data between view controllers.
I have a view controller that geocodes an annotation on a map view, and sets the address as the title of the annotation view. The annotation view has a callout button that pushes another view to the stack, which has a label, and I want the address that was geocoded to show up as the label. Here is some code:
This is where I drop the pin:
-(void)press:(UILongPressGestureRecognizer *)recognizer
{
CGPoint touchPoint = [recognizer locationInView:worldView];
CLLocationCoordinate2D touchMapCoordinate = [worldView convertPoint:touchPoint toCoordinateFromView:worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"reverseGeocoder:completionHandler: called");
if (error) {
NSLog(#"Geocoder failed with error: %#", error);
}
if (placemarks && placemarks.count > 0)
{
CLPlacemark *place = [placemarks objectAtIndex:0];
_address = [NSString stringWithFormat:#"%# %#, %# %#", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
_addressPin = [[MapPoint alloc]initWithCoordinate:touchMapCoordinate
title:_address];
[worldView addAnnotation:_addressPin];
}
}
}];
}
Here is the code for the view where I want the address to show up:
#import <UIKit/UIKit.h>
#class MapPoint;
#interface PinViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate,UITextFieldDelegate>
{
__weak IBOutlet UILabel *addressLabel;
}
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (strong, nonatomic) MapPoint *pin;
-(void)takePicture:(id)sender;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
#end
#import "PinViewController.h"
#import "MapPoint.h"
#interface PinViewController ()
#end
#implementation PinViewController
#synthesize imageView, pin;
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[addressLabel setText:[pin title]];
}
The class MapPoint has a title property and subtitle property. When the PinViewController is pushed to the top of the stack, I try to set the text of the label to the title of the pin, but the label does not show any text. Can someone help me out and tell me what I am missing? Your help is greatly appreciated.
You must share more code blocks for this question :) . instead of you have to get more idea about Communication in Object-Oriented Programs
You can read a good tutorial about Passing Data Between View Classes here
Read best way to pass an object between two views here
There is a good document that i found in Developer.apple regarding CommunicatingWithObjects
Also you can watch a good video here
Just create property for the label and pass the label text from callout tapped method
- (void)mapView:(MKMapView *)mapView annotationView:(MKPinAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
Details *det=[[Details alloc]init];
det.label.text=annotation.title;
[self.navigationController pushViewController:det animated:YES];
[det release];
}

Data going missing when passed between threads using a Singleton

Edit:
Thanks #BlackFrog. I think I'm nearer now, but the values are still not get getting through...
The values are set as shown by logs within [progressController updateProgressSummary:...] but are nil when I log them in progressUpdate initWithProgressUpdate:.... as shown below.
I'm slightly confused over which property is used the one set for progressUpdate or the ones set for each of the 3 components of progressUpdate. I have changed the 3 individual properties from assign to retain as suggested and have also tried doing the same with the overall progressUpdate property too (not shown here).
progressController.h
......
#property (nonatomic, assign) ProgressUpdate *progressUpdate;
progressController.m
// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {
// These report the proper values
DLog(#"Reporting Summary - %s", [summary UTF8String]);
DLog(#"Reporting Detail - %s", [detail UTF8String]);
DLog(#"Reporting Complete - %i", [complete intValue]);
if (summary != nil)
self.progressUpdate.summaryText = summary;
self.progressUpdate.detailText = detail;
self.progressUpdate.percentComplete = complete;
ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWithProgressUpdate:progressUpdate];
[self.delegate performSelectorOnMainThread:#selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO];
[progressUpdateForIssue release];
}
But then a few milliseconds later...., inside the object....they're nil.
progressUpdate.h
.....
#property (nonatomic, retain) NSString *summaryText;
#property (nonatomic, retain) NSString *detailText;
#property (nonatomic, retain) NSNumber *percentComplete;
progressUpdate.m
-(id) initWithProgressUpdate:(ProgressUpdate *)update {
if ((self = [super init])) {
summaryText = [update.summaryText copy];
detailText = [update.detailText copy];
percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue]];
}
// These report nil values
DLog(#"Reporting in progUpdate summaryText - %s", [summaryText UTF8String]);
DLog(#"Reporting in progUpdate detailText - %s", [detailText UTF8String]);
DLog(#"Reporting in progUpdate percentComplete - %i", [percentComplete intValue]);
return self;
}
end of update
I need some help with passing data in a custom class from one thread to another. Its there before the pass but then disappears upon arrival. I've tried everything I know, but to no avail.
My background thread calls ProgressController and passes it details of the current progress. That in turn does performSelectorOnMainThread on ProgressController's delegate (the view controller) to display the details.
It was all working fine when I was passing through a single NSString, but I need to pass two strings and a number and as performSelectorOnMainThread can only pass one object, I have encapsulated these in a custom object - ProgressUpdate.
The data gets through to ProgressController correctly but is null by the time that it appears in the View Controller. I know this as I've put NSLogs in various places.
I wonder if its to do with:
multithreading and custom objects
the fact that ProgressController is a singleton, which is why I have then alloc'd a new ProgressUpdate each time its called, but that has not helped.
Any ideas welcome. For clarity, the code is below.
ProgressUpdate.h
#import <Foundation/Foundation.h>
#interface ProgressUpdate : NSObject {
NSString *summaryText;
NSString *detailText;
NSNumber *percentComplete;
}
#property (nonatomic, assign) NSString *summaryText;
#property (nonatomic, assign) NSString *detailText;
#property (nonatomic, assign) NSNumber *percentComplete;
-(id) initWith:(ProgressUpdate *)update;
#end
ProgressUpdate.m
#import "ProgressUpdate.h"
#implementation ProgressUpdate
#synthesize summaryText, detailText, percentComplete;
-(id) initWith:(ProgressUpdate *)update {
self = [super init];
self.summaryText = update.summaryText;
self.detailText = update.detailText;
self.percentComplete = update.percentComplete;
return self;
}
#end
ProgressController.m
static ProgressController *sharedInstance;
+ (ProgressController *)sharedInstance {
#synchronized(self) {
if (!sharedInstance)
[[ProgressController alloc] init];
}
return sharedInstance;
}
+(id)alloc {
#synchronized(self) {
NSAssert(sharedInstance == nil, NSLocalizedString(#"Attempted to allocate a second instance of a singleton ProgressController.", #"Attempted to allocate a second instance of a singleton ProgressController."));
sharedInstance = [super alloc];
}
return sharedInstance;
}
-(id) init {
if (self = [super init]) {
[self open];
}
return self;
}
.........
// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {
if (summary != nil)
self.progressUpdate.summaryText = summary;
self.progressUpdate.detailText = detail;
self.progressUpdate.percentComplete = complete;
ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWith:progressUpdate];
[self.delegate performSelectorOnMainThread:#selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO];
[progressUpdateForIssue release];
}
RootViewController.m
// Delegate method to display specific text in Progress label
- (void) displayProgress:(ProgressUpdate *)update {
[progressSummaryLabel setText:update.summaryText];
[progressDetailLabel setText:update.detailText];
[progressBar setProgress:[update.percentComplete intValue]];
[progressView setNeedsDisplay];
}
In the init method, you are only assigning the ivars and not retaining them in the new object.
Redo your init method as the following:
-(id) initWithProgressUpdate:(ProgressUpdate *)update {
if ((self = [super init])) {
summaryText = [update.summaryText copy];
detailText = [update.detailText copy];
percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue];
}
return self;
}
Couple of points:
You should not use accessor in the init method
Rename your init method to be a lot clear
In the #property, change the assign to retain
Try removing the statement '[progressUpdateForIssue release];' in the method
'-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete '.
Also change the property attribute from 'assign' to 'retain' in your class ProgressUpdate.
You could release those properties in the dealloc method .
Good luck.

MKMapView removeAnnotations cause memory leak

everyone!
I have tested this simplest code as following:
StorePin.h
#import <Foundation/Foundation.h>
#import <MAPKIT/mapkit.h>
#import <CORELOCATION/corelocation.h>
#interface StorePin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *subtitle;
NSString *title;
}
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,retain) NSString *subtitle;
#property (nonatomic,retain) NSString *title;
-(id) initWithCoords:(CLLocationCoordinate2D) coords;
#end
StorePin.m
#import "StorePin.h"
#implementation StorePin
#synthesize coordinate, subtitle, title;
- (id) initWithCoords:(CLLocationCoordinate2D) coords{
self = [super init];
if (self != nil) {
coordinate = coords;
}
return self;
}
- (void) dealloc
{
[title release];
[subtitle release];
[super dealloc];
}
#end
In my ViewControlller, I made a button to add and remove annotations repeatly.
#import "mapViewTestViewController.h"
#import "StorePin.h"
#implementation mapViewTestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)refresh
{
[mapView removeAnnotations:mapView.annotations];
for (int i = 0; i < 101; i ++)
{
CLLocationCoordinate2D p1;
p1.latitude = i/10.0;
p1.longitude = i/10.0;
StorePin *poi = [[StorePin alloc] initWithCoords:p1];
[mapView addAnnotation:poi];
[poi release];
}
}
- (void)dealloc
{
[super dealloc];
}
#end
If I loop less than 100 times to add and remove annotations, all work normally. But if I loop more than 100 times, it will cause memory leak once. I'm nearly crazy to this strange problem. Is this my code's bug or mkmapview's bug? Thank you for helping me.
You don't say what objects have been detected as leaking, but if they are StorePins, then it's MapKit's problem -- your memory management code for the StorePins you create in the loop is just fine.
One thing that you do that might be causing MapKit trouble is passing the map view a reference to its own ivar that you want it to modify. It doesn't seem too likely -- if it was really a problem, it would probably cause a crash rather than a leak. However, you might try making a copy, either shallow (as Kai wrote earlier, but absolutely do not follow the advice about using retain counts and calling release in a loop):
NSArray * annotationsCopy = [NSArray arrayWithArray:mapView.annotations];
or deep:
NSArray * annotationsDeepCopy = [[[NSArray alloc] initWithArray:mapView.annotations
copyItems:YES]
autorelease];
then pass the copy to removeAnnotations:.
The second option creates an autoreleased array with a copy of every item in the annotations list so that the map view doesn't try to remove the same instances that it's iterating over. Obviously this uses twice the memory; you probably only want to bother with this for bug-hunting.
If it fixes the leak, great, if not, then there's probably nothing you can do about it.
In case you don't want to remove the user's location blue dot on the map, you can use:
NSArray * annotationsCopy = [NSArray arrayWithArray:[mapView.annotations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"!(self isKindOfClass: %#)", [MKUserLocation class]]]];

Objective-C Custom Getter / Setter

I am using the following NSManagedObject which was automatically generated by Xcode:
#interface Portion : NSManagedObject
{
}
#property (nonatomic, retain) NSNumber * volume;
I would like to create a custom getter/setter to convert between ml/oz depending on what the user has set, that way the database always stores the same value and it is automatically converted to the preferred units. My latest attempt looks like this:
#import "Portion.h"
#import "SettingHandler.h"
#define MILLILITERS_PER_OUNCE 29.5735296
#implementation Portion
#dynamic volume;
- (void) setVolume:(NSNumber *) number {
if ([SettingHandler getUnitsTypeShort] == #"oz") {
[self setValue:number forKey:#"volume"];
} else {
[self setValue:[NSNumber numberWithFloat:[number floatValue] * MILLILITERS_PER_OUNCE] forKey:#"volume"];
}
}
- (NSNumber *) volume {
if ([SettingHandler getUnitsTypeShort] == #"oz") {
return [self valueForKey:#"volume"];
} else {
return [NSNumber numberWithDouble: [[self valueForKey:#"volume"] floatValue] * MILLILITERS_PER_OUNCE];
}
}
The setVolume call ends up invoking itself causing an infinite loop. I'm guessing there is a way to do this but I don't know what it is, any ideas?
Sorry to play devil's advocate, but IMO, it seems like you're trying to address how a value is displayed to the user at too low of a level (in the model object itself; see The Model-View-Controller Design Pattern). Why not use a formatter that works more at the view level to help format the raw NSNumber value to a string that will be presented to the user?
You'd then have a reusable class you could use anywhere you use a number value that represents a volume. The formatter would store a "unitsType" value so it would know how to format the incoming number properly.
I did a quick version by using one of my existing formatters, MDFileSizeFormatter, as a starting point:
#import <Foundation/Foundation.h>
enum {
MDVolumeFormatterMetricUnitsType = 1,
MDVolumeFormatterOurStupidAmericanUnitsType = 2,
MDVolumeFormatterDefaultUnitsType = MDVolumeFormatterMetricUnitsType
};
typedef NSUInteger MDVolumeFormatterUnitsType;
#interface MDVolumeFormatter : NSFormatter {
MDVolumeFormatterUnitsType unitsType;
NSNumberFormatter *numberFormatter;
}
- (id)initWithUnitsType:(MDVolumeFormatterUnitsType)aUnitsType;
#property (assign) MDVolumeFormatterUnitsType unitsType;
#end
Then the .m file:
#import "MDVolumeFormatter.h"
#define MILLILITERS_PER_OUNCE 29.5735296
#implementation MDVolumeFormatter
#synthesize unitsType;
- (id)init {
return [self initWithUnitsType:MDVolumeFormatterDefaultUnitsType];
}
- (id)initWithUnitsType:(MDVolumeFormatterUnitsType)aUnitsType {
if (self = [super init]) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormat:#"#,###.#"];
[self setUnitsType:aUnitsType];
}
return self;
}
- (void)dealloc {
[numberFormatter release];
[super dealloc];
}
- (NSString *)stringForObjectValue:(id)anObject {
if ([anObject isKindOfClass:[NSNumber class]]) {
NSString *string = nil;
if (unitsType == MDVolumeFormatterMetricUnitsType) {
string = [[numberFormatter stringForObjectValue:
[NSNumber numberWithFloat:
[(NSNumber *)anObject floatValue] * MILLILITERS_PER_OUNCE]]
stringByAppendingString:#" mL"];
} else {
string = [[numberFormatter stringForObjectValue:anObject] stringByAppendingString:#" oz"];
}
return string;
}
return nil;
}
#end
This could potentially be expanded to do tests on the incoming value and automatically determine the appropriate volume unit. For example, if the floatValue was 16.0, you could use if then logic to return a string of "2.0 cups" instead of 16 oz.
Check out "Custom Attribute and To-One Relationship Accessor Methods" in the Core Data Programming Guide. Basically, you should use the primitive getter/setter methods to access/change the value and wrap those calls with KVO notifications.
You will need to add declarations for the primitive accessors:
#interface Portion (PrimitiveAccessors)
- (NSNumber *)primitiveVolume;
- (void)setPrimitiveVolume:(NSNumber *)number;
#end
Then you need to replace each occurrence of:
[self setValue:number forKey:#"volume"];
with:
[self willChangeValueForKey:#"volume"];
[self setPrimitiveVolume:number];
[self didChangeValueForKey:#"volume"];
And make the corresponding changes in the getter.
Try using [self setPrimitiveValue:number forKey:#"volume"]; instead.
I would suggest yet another approach. Decide on canonical representation - either ounces or milliliters. This be what volume is actually stored as. Then declare the following getters/setters:
- (void) setOunces:(double)ounces;
- (double) ounces;
- (void) setMilliliters:(double)milliliters;
- (double*) milliliters;
If the canonical volume is milliliters, then:
- (void) setOunces:(double)ounces
{
[self setVolume:[NSNumber numberWithDouble:(ounces* MILLILITERS_PER_OUNCE)]];
}
- (double) ounces
{
return [[self volume] doubleValue]/MILLILITERS_PER_OUNCE;
}
- (void) setMilliliters:(double)milliliters
{
[self setVolume:[NSNumber numberWithDouble:milliliters]];
}
- (double) milliliters
{
return [[self volume] doubleValue];
}

MKMapView refresh after pin moves

A custom AnnotationView is updated with new coordinates. But the problem is that it visually updates only after some manipulations with MKMapView, e.g. zooming or moving.
What should I do to manually update visual position on a map?
PS. I've tried to change region to current map's region. But it does change zoom. It's strange.
[mapView setRegion:[mapView region] animated:YES];
I am a little shoked after hours of research. The answer is just:
[mapView setCenterCoordinate:mapView.region.center animated:NO];
Do not ask me why, but it updates a mapview and it's what i was need.
MKMapView observes the coordinate property of annotations via KVO. You simply need to observe proper KVO protocol and send the annotation willChangeValueForKey: and didChangeValueForKey: with keypath of #"coordinate" before and after you update the coordinates.
Likewise title and subtitle are also observed by MKMapView. so if you update those and want the value in the callout to change automatically without any effort on your part, just do the same: call willChangeValueForKey: and didChangeValueForKey:
if your adding your annoations from a thread it wont work.
i had the same problem and just wrapping my function that was adding the annotations with the following worked
[self performSelectorOnMainThread:#selector(addCameraIconOnMain:) obj waitUntilDone:true];
-(void) addCameraIconOnMain:(myobjecttype*)obj
{
// this isnt the entire function, customize for your own purpose.....
[mapView addAnnotation:annotation];
}
The answer here is NOT to refresh the MapView or the Annotation!
the coordinate property of MKAnnotation has KVO on it. If you just add the id pointer, of the object you want on the map, to the mapview and update the coordinate property with a new location, MKMapView will do the rest for you.
As close as you can get to a free lunch!
I solved this error with an asynchronous call, at least 0.5 delay.
e.g.: [self performSelector:#selector(redrawPins) withObject:nil afterDelay:0.5];
Where "redrawPins" is the function which adds and removes pins.
There's no reason you can't remove and then re-add the annotation. That's probably way more performant than moving the entire map, even if its a fake move.
Here is the interface to MapAnnotation:
// CSMapAnnotation.h
// mapLines
// Created by Craig on 5/15/09.
// Copyright 2009 Craig Spitzkoff. All rights reserved.
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
// types of annotations for which we will provide annotation views.
typedef enum {
MapAnnotationTypeStart = 0,
MapAnnotationTypeEnd = 1,
MapAnnotationTypeImage = 2
} MapAnnotationType;
#interface MapAnnotation : NSObject <MKAnnotation>
{
CLLocationCoordinate2D _coordinate;
MapAnnotationType _annotationType;
NSString* _title;
NSString* _subtitle;
NSString* _userData;
NSString* speed;
NSString* identifier;
}
#property (nonatomic, retain) NSString *speed;
#property (nonatomic, retain) NSString *identifier;
-(id) initWithCoordinate:(CLLocationCoordinate2D)coordinate
annotationType: (MapAnnotationType) annotationType
title: (NSString*) title
subtitle: (NSString*) subtitle
speed: (NSString *) speed
identifier: (NSString *) identifier;
-(id) setWithCoordinate: (CLLocationCoordinate2D) coordinate
annotationType: (MapAnnotationType) annotationType
title: (NSString*) title
subtitle: (NSString*) subtitle
speed: (NSString*) speed
identifier: (NSString*) identifier;
#property MapAnnotationType annotationType;
#property (nonatomic, retain) NSString* userData;
#end
And here is the implementation:
// CSMapAnnotation.m
// mapLines
// Created by Craig on 5/15/09.
// Copyright 2009 Craig Spitzkoff. All rights reserved.
#import "MapAnnotation.h"
#implementation MapAnnotation
#synthesize coordinate = _coordinate;
#synthesize annotationType = _annotationType;
#synthesize userData = _userData;
#synthesize speed;
#synthesize identifier;
-(id) initWithCoordinate:(CLLocationCoordinate2D)coordinate
annotationType: (MapAnnotationType) annotationType
title: (NSString*)title
subtitle: (NSString*) subtitle
speed: (NSString *) speedz
identifier: (NSString *) identifierz
{
self = [super init];
_coordinate = coordinate;
_title = [title retain];
_subtitle = [subtitle retain];
_annotationType = annotationType;
speed = speedz;
identifier = identifierz;
return self;
}
-(id) setWithCoordinate:(CLLocationCoordinate2D)coordinate
annotationType: (MapAnnotationType) annotationType
title: (NSString*) title
subtitle: (NSString*) subtitle
speed: (NSString*) speedz
identifier: (NSString*) identifierz
{
_coordinate = coordinate;
_title = [title retain];
_subtitle = [subtitle retain];
_annotationType = annotationType;
speed = speedz;
identifier = identifierz;
return self;
}
-(NSString*) title
{
return _title;
}
-(NSString*) subtitle
{
return _subtitle;
}
-(void) dealloc
{
[_title release];
[_userData release];
[super dealloc];
}
#end