I am trying to draw a map with routes from a file. I am trying to learn this procedure by following this blog (http://spitzkoff.com/craig/?p=108).
When the process hits my function, it terminates (I have given the error message below)
- (void) drawRoute {
//
// load the points from our local resource
//
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"route" ofType:#"csv"];
NSString* fileContents = [NSString stringWithContentsOfFile:filePath];
NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray* points = [[NSMutableArray alloc] initWithCapacity:pointStrings.count];
for(int idx = 0; idx < pointStrings.count; idx++)
{
// break the string down even further to latitude and longitude fields.
NSString* currentPointString = [pointStrings objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocation* currentLocation = [[[CLLocation alloc] initWithLatitude:latitude longitude:longitude] autorelease];
[points addObject:currentLocation];
}
// CREATE THE ANNOTATIONS AND ADD THEM TO THE MAP
// first create the route annotation, so it does not draw on top of the other annotations.
CSRouteAnnotation* routeAnnotation = [[[CSRouteAnnotation alloc] initWithPoints:points] autorelease];
[secondMap addAnnotation:routeAnnotation];
// create the rest of the annotations
CSMapAnnotation* annotation = nil;
// create the start annotation and add it to the array
annotation = [[[CSMapAnnotation alloc] initWithCoordinate:[[points objectAtIndex:0] coordinate]
annotationType:CSMapAnnotationTypeStart
title:#"Start Point"] autorelease];
[secondMap addAnnotation:annotation];
// create the end annotation and add it to the array
annotation = [[[CSMapAnnotation alloc] initWithCoordinate:[[points objectAtIndex:points.count - 1] coordinate]
annotationType:CSMapAnnotationTypeEnd
title:#"End Point"] autorelease];
[secondMap addAnnotation:annotation];
[points release];
// center and size the map view on the region computed by our route annotation.
[secondMap setRegion:routeAnnotation.region];
}
Error message:
[Session started at 2010-07-30 01:22:13 -0400.]
2010-07-30 01:22:19.078 ActualTry[4893:20b] Found center of new Route Annotation at 0.000000, 0
2010-07-30 01:22:19.079 ActualTry[4893:20b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
2010-07-30 01:22:19.080 ActualTry[4893:20b] Stack: (
807902715,
2492862011,
807986683,
807986522,
810976489,
810572359,
13379,
12278,
10121,
814709201,
815110321,
815119058,
815114270,
814813151,
814722763,
814748641,
839148405,
807687520,
807683624,
839142449,
839142646,
814752238,
9380,
9234
)
I will be really thankful if someone could help me in this. I know that this is basic gdb debugging, but I am not able to figure this out.
Thank you.
The error message says that you are trying to access an object in the array which doesn't exist. Looking at your code, it seems pointStrings array is empty. Are you sure your csv file has data? Try printing the pointStrings with NSlog.
Related
I am trying to add some annotations to my mkMapView in this loop:
for (PFObject *fetchedCompany in companyArray)
{
Store *store = [[Store alloc] initWithObject:fetchedCompany];
[self loadStore:store];
[store release];
}
- (void) loadStore:(Store *) store {
CLLocationCoordinate2D location = [self getLocationFromAddressString:store.address];
MapViewAnnotation *mapAnnotation = [[MapViewAnnotation alloc] initWithTitle:store.name coordinate:location];
[self.indexMapView addAnnotation:mapAnnotation];
}
And this the getLocationFromAddressString method that convert the address to a location using google api:
-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr {
NSString *urlStr = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv", [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSError *error = nil;
NSString *locationStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlStr] encoding:NSUTF8StringEncoding error:&error];
NSArray *items = [locationStr componentsSeparatedByString:#","];
double lat = 0.0;
double lon = 0.0;
if([items count] >= 4 && [[items objectAtIndex:0] isEqualToString:#"200"]) {
lat = [[items objectAtIndex:2] doubleValue];
lon = [[items objectAtIndex:3] doubleValue];
}
else {
NSLog(#"Address, %# not found: Error %#",addressStr, [items objectAtIndex:0]);
}
CLLocationCoordinate2D location;
location.latitude = lat;
location.longitude = lon;
return location;
}
When I send just one location always it works perfectly, but when I add annotations in my loop sometimes some locations could not be recognized and I got the error from my NSLog:
Address, Vallgatan 3 GĂ–TEBORG not found: Error 620
The thing is I am pretty sure about the addresses because when I tried them without loop they worked. Do you know how can I solve the problem?
You've submitted too many queries and your request got rejected. See Geocoding API V2 docs.
620: G_GEO_TOO_MANY_QUERIES
"The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly"
I have an iphone app which displays a list of businesses and their location on a Google Map using the MKMapView. As a new feature, I am trying to add a "Nearby" feature, whereby it gets the users current location and displays several map annotations on a google map within the vicinity of say 10KM. Currently, the businesses location is stored as an address string in a mysql database, this is then retrieved and geocoded to display it on a google map.
How do I go about doing this? If there is any tutorials around, please point me to one. (I haven't had any luck with finding one).
Thanks in advance!
UPDATE:
I got it partially working - it's only displaying businesses within a 20KM radius which is great, the problem i'm having is that when they open this Nearby Businesses View, it takes quite some time for it to go through each business and check the distance between the user and each individual business. Is there any way to speed this up? Here is my code:, both these methods are called from the viewDidLoad method.
-(void)getMapData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSInteger *bizMax = [[numOfBiz objectAtIndex:0]intValue];
int x = 0;
while(x < bizMax)
{
NSURL *mapURL = [NSURL URLWithString:[NSString stringWithFormat:#"getBizMap-xml.php?biz_id=%#",[bizIDS objectAtIndex:x]]];
NSMutableArray *mapArray = [[NSMutableArray alloc] initWithContentsOfURL:mapURL];
self.mapLocation = mapArray;
self.mapStringLocation = [mapArray objectAtIndex:0];
NSLog(#"Location: %#",mapStringLocation);
[mapArray release];
CLLocationCoordinate2D trueLocation = [self getLocationFromAddressString:mapStringLocation];
AddressAnnotation *addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:trueLocation];
CLLocation *bizLoc = [[CLLocation alloc] initWithLatitude:trueLocation.latitude longitude:trueLocation.longitude];
CLLocation *userLocation = [[CLLocation alloc] initWithLatitude:nearbyMapView.userLocation.coordinate.latitude longitude:nearbyMapView.userLocation.coordinate.longitude];
//double distance = [userLocation getDistanceFrom: bizLoc] / 1000;
double kilometers = [userLocation distanceFromLocation:bizLoc] / 1000;
NSLog(#"Distance from %# to current location is %g",mapStringLocation,kilometers);
if(kilometers < maxDistance)
{
[self.nearbyMapView addAnnotation:addAnnotation];
[addAnnotation release];
}
x++;
}
[pool release];
}
-(void)getNumOfBusinesses
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSString *numOfBizJSON = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"numOfBiz.php"]]];
NSString *bizIDSJSON = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"allBizIDSJSON.php"]]];
SBJsonParser *parser = [[SBJsonParser alloc]init];
numOfBiz = [[parser objectWithString:numOfBizJSON error:nil]copy];
bizIDS = [[parser objectWithString:bizIDSJSON error:nil]copy];
NSLog(#"biz id 1 = %#",[bizIDS objectAtIndex:0]);
[parser release];
[numOfBizJSON release];
[bizIDSJSON release];
[pool release];
}
This isn't that hard. You can fetch all your data, calculate the distance between you and the location. The next step would be comparing the distance with the maxDistance(the search radius). If the distance < maxDistance, add you can display that location.
I think this could be achieved with very little cocoa knowledge...
If you need something more specific, start coding and I'll help you with that.
Hey guys, I am having trouble getting overlays in my map view to refresh via the setNeedsDisplayInMapRect: function. Here is the relevant code:
ParkingMapViewController.m:
for (ParkingRegionOverlay *overlay in mapView.overlays) {
[overlay setNeedsDisplayInMapRect:self.mapView.visibleMapRect];
}
//...
- (MKOverlayView *)mapView:(MKMapView *)mapView
viewForOverlay:(id <MKOverlay>)overlay
{
NSLog(#"ParkingMapViewController.m mapView:viewForOverlay");
//...
}
//...
ParkingRegionOverlay.h:
#interface ParkingRegionOverlay : MKOverlayView <MKOverlay> {
MKPolygon *polygon;
MKMapRect boundingRect;
CLLocationCoordinate2D centerCoord;
//...
}
//...
And I am not getting the "ParkingMapViewController.m mapView:viewForOverlay" output to console I am expecting. I have walked through he debugger and have ensured that the for loop is being reached and executed, however mapView:viewForOverlay: isn't being called for some reason. Anyone know what I am doing wrong? Thanks in advance!
EDIT 1:
I believe I have set the delegate, coordinates, and bounding rect properly, but please take a look...
ParkingMapViewController.h
#interface ParkingMapViewController : UIViewController <MKMapViewDelegate> {
MKMapView *mapView;
//...
ParkingMapViewController.m:
//...
- (void)viewDidLoad {
[super viewDidLoad];
mapView.delegate = self;
//...
ParkingRegionOverlay.m:
//...
//initializes polygon and calculates bounding rect as well as its center coordinate
-(id)initWithPoints:(NSArray *)pointsArray andTitle:(NSString *)overlayTitle{
MKMapPoint points[[pointsArray count]];
double maxX = MIN_COORD_VAL;
double minX = MAX_COORD_VAL;
double maxY = MIN_COORD_VAL;
double minY = MAX_COORD_VAL;
double tempX = 0;
double tempY = 0;
if (self = [super init]) {
int i = 0;
//determine min/max extrema to help calculate the bounding rect
for (id coordDict in pointsArray){
tempX = [[coordDict objectForKey:#"latitude"] doubleValue];
tempY = [[coordDict objectForKey:#"longitude"] doubleValue];
maxX = fmax(tempX, maxX);
minX = fmin(tempX, minX);
maxY = fmax(tempY, maxY);
minY = fmin(tempY, minY);
CLLocationCoordinate2D coord = {tempX,tempY};
points[i] = MKMapPointForCoordinate(coord);
i++;
}//for
CLLocationCoordinate2D northWestCorner = CLLocationCoordinate2DMake(maxX, minY);
CLLocationCoordinate2D southEastCorner = CLLocationCoordinate2DMake(minX, maxY);
MKMapPoint northWestPoint = MKMapPointForCoordinate(northWestCorner);
MKMapPoint southEastPoint = MKMapPointForCoordinate(southEastCorner);
boundingRect = MKMapRectMake(northWestPoint.x, northWestPoint.y,
(southEastPoint.x-northWestPoint.x),
(southEastPoint.y-northWestPoint.y));
centerCoord = CLLocationCoordinate2DMake((maxX-minX)/2,(maxY-minY)/2);
polygon = [MKPolygon polygonWithPoints:points count:[pointsArray count]];
polygon.title = overlayTitle;
[self initAcceptedPermitsBasedOnTitle:overlayTitle];
}//if
return self;
}
//...
Thanks.
EDIT 2:
An alternate method I have tried, to no avail:
ParkingMapViewController.m
NSArray *overlayArray = [[NSArray alloc] initWithArray:[mapView overlays]];
[self.mapView removeOverlays:mapView.overlays];
[self.mapView addOverlays:overlayArray];
Removing and re-adding all overlays ain't working too well for me. It merely crashes when that third line is executed. Any ideas?
EDIT 3:
So I changed the previously posted code to the following:
NSArray *overlayArray = [mapView overlays];
[self.mapView removeOverlays:overlayArray];
[self.mapView addOverlays:overlayArray];
And am now seeing this in the console:
2011-05-05 14:24:54.145 Parking[68501:207] -[NSCFNumber boundingMapRect]: unrecognized selector sent to instance 0xa9afae0
2011-05-05 14:24:54.147 Parking[68501:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber boundingMapRect]: unrecognized selector sent to instance 0xa9afae0'
Chances are you haven't set up the coordinate or boundingMapRect properties on the MKOverlay correctly. The MapView will only ask for the view if it thinks there is a possibility that it is visible, if its visible rect doesn't intersect the boundMapRect, it won't.
Also make sure your delegate for the mapView is set properly.
So I figured it out. Not necessarily the most efficient method, but it works for me. This is what I did:
[self.mapView removeOverlays:[mapView overlays]];
[self loadOverlaysAndAnnotations];
And here is loadOverlaysAndAnnotations:
- (void)loadOverlaysAndAnnotations {
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
CoreDataSingleton *coreDataSingleton = [CoreDataSingleton sharedManager];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"ParkingLot" inManagedObjectContext:[coreDataSingleton managedObjectContext]];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [[coreDataSingleton managedObjectContext] executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *overlayEntity in fetchedObjects) {
NSArray *pointsArray = [NSArray arrayWithArray:[overlayEntity valueForKey:#"overlayCoordPoints"]];
ParkingRegionOverlay *regionPolygon = [[ParkingRegionOverlay alloc] initWithPoints:pointsArray andTitle:[overlayEntity valueForKey:#"lotName"]];
[mapView addOverlay:regionPolygon];
[regionPolygon release];
NSSet *annotationsSet = [NSSet setWithSet:[overlayEntity valueForKey:#"parkingAnnotations"]];
NSArray *allAnnotations = [NSArray arrayWithArray:[annotationsSet allObjects]];
CLLocationCoordinate2D workingCoordinate;
for (ParkingAnnotations *annotation in allAnnotations) {
ParkingAnnotation *parkingAnnot = [[ParkingAnnotation alloc] init];
workingCoordinate.latitude = [[annotation latitude] doubleValue];
workingCoordinate.longitude = [[annotation longitude] doubleValue];
[parkingAnnot setCoordinate:workingCoordinate];
[parkingAnnot setTitle:[overlayEntity valueForKey:#"lotName"]];
if ([[overlayEntity valueForKey:#"lotName"] isEqualToString:#"VP 1"]) {
[parkingAnnot setLot:lot1];
}
[mapView addAnnotation:parkingAnnot];
[parkingAnnot release];
}
}
[fetchRequest release];
}//loadOverlaysAndAnnotations
In short, I didn't have to create a new function but merely call the function I used to load overlays into the map view and that works fine! Hope this helps anyone else stuck in a similar situation.
EDIT:
Important to note that I am reloading BOTH annotations and overlays, and, if done without first removing both annotations and overlays, can lead to crashing of your app if the reload function is called too many times. This is what I am currently experiencing. Just something to be aware of. To fix this I am going to have separate load functions, one for overlays, and one for annotations which will be called appropriately.
I have an array which I store different classes which again hold different arrays. All arrays are defined as NSMutabelArrays.
When I want to delete an object in an array, my app crashes. This is my code:
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabReference] objectAtIndex:tid]);
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabColours] objectAtIndex:tid]);
NSLog(#"string to be deleted:%#", [[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabTitles] objectAtIndex:tid]);
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabReference] removeObjectAtIndex:tid];
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabColours] removeObjectAtIndex:tid];
[[[self.myLibrary objectAtIndex:self.currentNoteBookNumber] tabTitles] removeObjectAtIndex:tid];
And this is the console output:
2011-05-01 22:03:40.788 M[61452:207] string to be deleted:2
2011-05-01 22:03:40.789 M[61452:207] string to be deleted:Orange
2011-05-01 22:03:40.791 M[61452:207] string to be deleted:Art
2011-05-01 22:03:40.806 M[61452:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
I don't really know what I'm doing wrong. There is obviously something in the array, so it shouldn't be 0. I mean it is the ONLY thing stored in the array at the moment, but that shouldn't be a problem, I guess?
I'd be very grateful for any help on this.
EDIT:
I think I haven't provided enough code. This is the method in which I set up myLibrary:
-(void) setupLibrary {
myLibrary = [[NSMutableArray alloc] init];
NoteBook *newNoteBook = [[NoteBook alloc] init];
newNoteBook.titleName = #"TEST";
NSMutableArray *ttArray = [[NSMutableArray alloc] init];
[ttArray addObject:#"Art"];
NSMutableArray *tcArray = [[NSMutableArray alloc] init];
[tcArray addObject:#"Orange"];
NSMutableArray *trArray = [[NSMutableArray alloc] init];
[trArray addObject: [NSNumber numberWithInteger:2]];
newNoteBook.tabTitles = ttArray;
newNoteBook.tabColours = tcArray;
newNoteBook.tabReference = trArray;
[myLibrary addObject:newNoteBook];
currentNoteBookNumber = 0;
[newNoteBook release];
[ttArray release];
[tcArray release];
[trArray release];
}
Now it appears that if I delete, for instance, one object in the tabTitles array (e.g. "Art"), I delete the entire newNoteBook object. I.e. once I delete a string in tabTitles, all other strings at the same position in tabColours or tabReference will be deleted as well. Why is this so?
The following code will crash after I successfully deleted the string # position 0 in an array in my class which is stored in another array:
NSLog(#"string deleted:%#", [[[self.myLibrary objectAtIndex:0] tabReference] objectAtIndex:0]);
[[[self.myLibrary objectAtIndex:0] tabReference] removeObjectAtIndex:0];
NSLog(#"string deleted:%#", [[[self.myLibrary objectAtIndex:0] tabColours] objectAtIndex:0]);
[[[self.myLibrary objectAtIndex:0] tabColours] removeObjectAtIndex:0];
Don't know what's the problem here, but you should consider to keep your arrays safe:
if([yourArray count] > tid) {
[yourArray removeObjectAtIndex.tid;
}
Your error
-[NSMutableArray objectAtIndex:]: index 0
is telling that you are trying to get an object at index 0 not that you want to remove it. So I think what you did is you called the method where you have your reading and removing code 2 times in a row. Try to see it that is the case.
I have a MKMapView, and I would like to know how I can find the nearest 5 annotations to the user, and only display them on the MKMapView.
My code currently is:
- (void)loadFiveAnnotations {
NSString *string = [[NSString alloc] initWithContentsOfURL:url];
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSArray *chunks = [string componentsSeparatedByString:#";"];
NSArray *keys = [NSArray arrayWithObjects:#"type", #"name", #"street", #"address1", #"address2", #"town", #"county", #"postcode", #"number", #"coffeeclub", #"latlong", nil];
// max should be a multiple of 12 (number of elements in keys array)
NSUInteger max = [chunks count] - ([chunks count] % [keys count]);
NSUInteger i = 0;
while (i < max)
{
NSArray *subarray = [chunks subarrayWithRange:NSMakeRange(i, [keys count])];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:subarray forKeys:keys];
// do something with dict
NSArray *latlong = [[dict objectForKey:#"latlong"] componentsSeparatedByString:#","];
NSString *latitude = [[latlong objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *longitude = [[latlong objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
CLLocationDegrees lat = [latitude floatValue];
CLLocationDegrees longi = [longitude floatValue];
Annotation *annotation = [[Annotation alloc] initWithCoordinate:CLLocationCoordinate2DMake(lat, longi)];
annotation.title = [dict objectForKey:#"name"];
annotation.subtitle = [NSString stringWithFormat:#"%#, %#, %#",[dict objectForKey:#"street"],[dict objectForKey:#"county"], [dict objectForKey:#"postcode"]];
[mapView addAnnotation:annotation];
[dict release];
i += [keys count];
}
}
A long answer, already mostly written when Stephen Poletto posted and containing example code on how to use the built-in methods for sorting an array, so I though it was still worth posting though the essential answer is the same (ie, "pick the five closest for yourself, pass only those on"):
You're going to need to sort your annotations by distance for yourself, and submit only the closest five to the MKMapView. If you have two CLLocations then you can get the distance between them using the distanceFromLocation: method (which was getDistanceFrom: prior to iOS 3.2; that name is now deprecated).
So, for example, supposing your Annotation class had a method 'setReferenceLocation:' to which you pass a CLLocation and a getter 'distanceFromReferenceLocation' which returns the distance between the two, you could do:
// create and populate an array containing all potential annotations
NSMutableArray *allPotentialAnnotations = [NSMutableArray array];
for(all potential annotations)
{
Annotation *annotation = [[Annotation alloc]
initWithCoordinate:...whatever...];
[allPotentialAnnotations addObject:annotation];
[annotation release];
}
// set the user's current location as the reference location
[allPotentialAnnotations
makeObjectsPerformSelector:#selector(setReferenceLocation:)
withObject:mapView.userLocation.location];
// sort the array based on distance from the reference location, by
// utilising the getter for 'distanceFromReferenceLocation' defined
// on each annotation (note that the factory method on NSSortDescriptor
// was introduced in iOS 4.0; use an explicit alloc, init, autorelease
// if you're aiming earlier)
NSSortDescriptor *sortDescriptor =
[NSSortDescriptor
sortDescriptorWithKey:#"distanceFromReferenceLocation"
ascending:YES];
[allPotentialAnnotations sortUsingDescriptors:
[NSArray arrayWithObject:sortDescriptor]];
// remove extra annotations if there are more than five
if([allPotentialAnnotations count] > 5)
{
[allPotentialAnnotations
removeObjectsInRange:NSMakeRange(5,
[allPotentialAnnotations count] - 5)];
}
// and, finally, pass on to the MKMapView
[mapView addAnnotations:allPotentialAnnotations];
Depending on where you're loading from, you made need to create a local store (in memory or on disk) for annotations and select the five nearest whenever the user moves. Either register yourself as a CLLocationManager delegate or key-value observe on the map view's userLocation property. If you have quite a lot of potential annotations then sorting all of them is a bit wasteful and you'd be better advised to use a quadtree or a kd-tree.
First you'll need to grab the user's current location. You can build a CLLocationManager and register yourself as the delegate for location updates as follows:
locationManager = [[[CLLocationManager alloc] init] autorelease];
[locationManager setDelegate:self];
[locationManager startUpdatingLocation];
After setting yourself as the delegate, you'll receive the following callback:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Now that you have the user's location (newLocation), you can find the five closest annotations. There is a handy method in CoreLocation:
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
As you're iterating through your annotations, just store the five nearest locations. You can build a CLLocation out of the 'lat' and 'longi' variables you have using:
- (id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude
Hope this helps!