Loading online data very slow difficult to PUSH - ios

First of all I am running a Map page that just only show pins on map for every store. I was running only one pin on the map and it was fast after I put more than 25 pins it push very slow to the map page. What it is doing now at that process the app just load all data of the pin location (as I see in the target output) and then it push to the next screen. So please where would be my problem?
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"";
self.navigationItem.title = #"Mek";
response = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://kalkatawi.com/mapLocation.php"]];
if(response!=nil) {
NSError *parseError = nil;
jsonArray = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingAllowFragments error:&parseError];
jsonArray1 = [[NSMutableArray alloc] init];
jsonArray2 = [[NSMutableArray alloc] init];
jsonArray3 = [[NSMutableArray alloc] init];
for(int i=0;i<[jsonArray count];i++)
{
name = [[jsonArray objectAtIndex:i] objectForKey:#"name"];
longitude = [[jsonArray objectAtIndex:i] objectForKey:#"longitude"];
latitude = [[jsonArray objectAtIndex:i] objectForKey:#"latitude"];
[jsonArray1 addObject:name];
[jsonArray2 addObject:longitude];
[jsonArray3 addObject:latitude];
self.locationMap.delegate = self; //set delegate before adding annotations
CLLocationCoordinate2D annotationCoord;
for (int i=0; i < [jsonArray count]; i++)
{
NSDictionary *annotationDictionary = [jsonArray objectAtIndex:i];
name = [annotationDictionary objectForKey:#"name"];
annotationCoord.latitude
= [[annotationDictionary objectForKey:#"longitude"] doubleValue];
annotationCoord.longitude
= [[annotationDictionary objectForKey:#"latitude"] doubleValue];
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = name;
annotationPoint.subtitle = [NSString stringWithFormat:#"%f %f", annotationPoint.coordinate.latitude, annotationPoint.coordinate.longitude];
[self.locationMap addAnnotation:annotationPoint];
//------------------------//
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annotationPoint.coordinate, 50000, 50000);
[self.locationMap setRegion:[self.locationMap regionThatFits:region] animated:YES];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
lat = locationManager.location.coordinate.latitude;
lon = locationManager.location.coordinate.longitude;
}
}
}
else {
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"You are not connected to internet" message:#"Please check the internet connection" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != locationMap.userLocation)
{
static NSString *defaultPinID = #"myPin";
pinView = (MKAnnotationView *)[locationMap dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.image = [UIImage imageNamed:#"pinpinpin.png"];
pinView.canShowCallout = YES;
pinView.enabled = YES;
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = infoButton;
}
return pinView;
}

SImple way is load data in background thread, and then when data is fully load display it on the map. You can do this in any of view controller, means you can do it in parent view controller and when you got response then update on map view controller.
Or on view did load method load data in background and update it when its load. This approach will not hold your UI. You can use blocks like this
dispatch_async(queue, ^{
//load data from server
dispatch_async(dispatch_get_main_queue(), ^{
//Update map
});
});

Related

Obj-C - All Custom MKMapView annotations not always showing on MapView?

I'm trying to display multiple arrays of locations on my mapView with the below code (Restaurants, Parks, Meet Ups & Stores). When I open the app, not all addresses inside the arrays are displayed on my mapView (even though all data is returned) - e.g. sometimes only 'Stores' and 'Parks' arrays of annotations will show up on my map, but Restaurants aren't visible (even though data for all arrays is returned successfully). If I close out and reopen the app, sometimes Parks will show on the map, but nothing else. Any idea why this happens, and how I can fix it? Code updated below. Been at this forever!
Note: ParksAnnotation, RestAnnotation, meetupAnn, & StoreAnnotation are all MKPointAnnotation classes.
UPDATE (10/13/2020): I tried logging 'placemarks' under the block of code that retrieves and geocodes my 'Stores' coordinates. It appears as though self.storeData is populated, as is the created NSDictionary storeFields. That said, when I log 'placemarks', it isn't returning any coordinates, even though storeFields[#"address"] is populated. The other blocks of code seem to be doing their job just fine (ie. retrieving Meet Ups and retrieving Parks). So Meet Ups, Restaurants and Parks annotations appear fine, but all Stores annotations aren't populated. This happens to at least one type of annotation (sometimes it's Stores that's missing, other times it's Parks) at random when I launch the app. I can't for the life of me sort out why this is happening.
See below code:
MapViewController.m
#import "StoreAnnotation.h"
#import "ParksAnnotation.h"
#import "RestAnnotation.h"
#import "meetupAnn.h"
#interface MapViewController ()
#end
#implementation MapViewController
-(void)viewWillAppear:(BOOL)animated {
NSMutableDictionary *viewParamsallUsers1 = [NSMutableDictionary new];
[viewParamsallUsers1 setValue:#"hosted_meet_ups" forKey:#"view_name"];
[DIOSView viewGet:viewParamsallUsers1 success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.meetUps = [responseObject mutableCopy];
int index = 0;
for (NSMutableDictionary *allMeetups in self.meetUps) {
NSString *location = allMeetups[#"where"];
NSString *userNames = allMeetups[#"node_title"];
NSString *userBio = allMeetups[#"body"];
self.alertMessage = [allMeetups[#"node_title"] mutableCopy];
CLGeocoder *geocoderFriend = [[CLGeocoder alloc] init];
[geocoderFriend geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
MKCoordinateRegion region = self.mapView.region;
region.span.longitudeDelta /= 150.0;
region.span.latitudeDelta /= 150.0;
meetupAnn *meet = [[meetupAnn alloc] init];
meet.coordinate = placemark.coordinate;
meet.title = userNames;
meet.subtitle = userBio;
meet.index = index; // Store index here.
[self.mapView addAnnotation:meet];
}
}
];
index = index + 1;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
/// GRAB ALL RESTAURANT LOCATIONS ///
NSMutableDictionary *viewParams6 = [NSMutableDictionary new];
[viewParams6 setValue:#"restaurants" forKey:#"view_name"];
[DIOSView viewGet:viewParams6 success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.neighbourhoodData = [responseObject mutableCopy];
int index = 0;
for (NSMutableDictionary *multiplelocationsFriend in self.neighbourhoodData) {
NSString *location = multiplelocationsFriend[#"address"];
NSString *userNames = multiplelocationsFriend[#"node_title"];
NSString *ampRemoved = [userNames stringByReplacingOccurrencesOfString:#"amp;" withString:#""];
NSString *userBio = multiplelocationsFriend[#"body"];
self.x3 = multiplelocationsFriend[#"x3"];
CLGeocoder *geocoderFriend = [[CLGeocoder alloc] init];
[geocoderFriend geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
MKCoordinateRegion region = self.mapView.region;
region.span.longitudeDelta /= 150.0;
region.span.latitudeDelta /= 150.0;
RestAnnotation *point1 = [[RestAnnotation alloc] init];
point1.coordinate = placemark.coordinate;
point1.title = ampRemoved;
point1.subtitle = userBio;
point1.index = index; // Store index here.
[self.mapView addAnnotation:point1];
}
}
];
index = index + 1;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
NSString *test = self.areaName;
NSLog(#"SHOW TEST %#", test);
/// GRAB ALL STORE LOCATIONS ///
NSMutableDictionary *viewParams7 = [NSMutableDictionary new];
[viewParams7 setValue:#"stores" forKey:#"view_name"];
[DIOSView viewGet:viewParams7 success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.storesData = [responseObject mutableCopy];
int index = 0;
for (NSMutableDictionary *storeFields in self.storesData) {
NSString *location = storeFields[#"address"];
NSString *userNames = storeFields[#"node_title"];
NSString *ampRemoved = [userNames stringByReplacingOccurrencesOfString:#"amp;" withString:#""];
NSString *userBio = storeFields[#"body"];
self.x3 = storeFields[#"x3"];
CLGeocoder *geocoderFriend = [[CLGeocoder alloc] init];
[geocoderFriend geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
MKCoordinateRegion region = self.mapView.region;
region.span.longitudeDelta /= 150.0;
region.span.latitudeDelta /= 150.0;
StoreAnnotation *point2 = [[StoreAnnotation alloc] init];
point2.coordinate = placemark.coordinate;
point2.title = ampRemoved;
point2.subtitle = userBio;
point2.index = index; // Store index here.
[self.mapView addAnnotation:point2];
}
}
];
index = index + 1;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
/// GRAB ALL PARKS LOCATIONS ///
NSMutableDictionary *viewParams8 = [NSMutableDictionary new];
[viewParams8 setValue:#"parks" forKey:#"view_name"];
[DIOSView viewGet:viewParams8 success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.parksData = [responseObject mutableCopy];
int index = 0;
for (NSMutableDictionary *parkFields in self.parksData) {
// NSLog(#"WHAT IS IN FRIENDS %#", self.friendData);
NSString *location = parkFields[#"address"];
NSString *userNames = parkFields[#"node_title"];
NSString *ampRemoved = [userNames stringByReplacingOccurrencesOfString:#"amp;" withString:#""];
NSString *userBio = parkFields[#"body"];
self.x3 = parkFields[#"x3"];
CLGeocoder *geocoderFriend = [[CLGeocoder alloc] init];
[geocoderFriend geocodeAddressString:location
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
MKCoordinateRegion region = self.mapView.region;
region.span.longitudeDelta /= 150.0;
region.span.latitudeDelta /= 150.0;
ParksAnnotation *point3 = [[ParksAnnotation alloc] init];
point3.coordinate = placemark.coordinate;
point3.title = ampRemoved;
point3.subtitle = userBio;
point3.index = index; // Store index here.
[self.mapView addAnnotation:point3];
}
}
];
index = index + 1;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
MKCoordinateRegion mapRegion;
mapRegion.center = mapView.userLocation.coordinate;
mapRegion.span.latitudeDelta = 0.5;
mapRegion.span.longitudeDelta = 0.5;
[mapView setRegion:mapRegion animated: YES];
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 8000, 8000);
[mapView setRegion:[mapView regionThatFits:region] animated:YES];
[mapView addAnnotations:[mapView annotations]];
});
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if([annotation isKindOfClass:[StoreAnnotation class]]) {
static NSString *identifier = #"stores";
MKAnnotationView *storesView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(storesView == nil) {
storesView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
storesView.displayPriority = MKFeatureDisplayPriorityRequired;
storesView.canShowCallout = YES;
storesView.image = [UIImage imageNamed:#"storeann4.png"];
}
else {
storesView.annotation = annotation;
}
return storesView;
}
if([annotation isKindOfClass:[meetupAnn class]]) {
static NSString *identifier = #"meetUps";
MKAnnotationView *pulsingView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(pulsingView == nil) {
pulsingView.displayPriority = MKFeatureDisplayPriorityRequired;
pulsingView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
pulsingView.image = [UIImage imageNamed:#"meetupbeacon.png"];
pulsingView.canShowCallout = YES;
}
else {
pulsingView.annotation = annotation;
}
return pulsingView;
}
if([annotation isKindOfClass:[ParksAnnotation class]]) {
static NSString *identifier = #"parks";
MKAnnotationView *parksView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(parksView == nil) {
parksView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
parksView.displayPriority = MKFeatureDisplayPriorityRequired;
parksView.image = [UIImage imageNamed:#"parksann.png"];
parksView.canShowCallout = YES;
}
else {
parksView.annotation = annotation;
}
return parksView;
}
if([annotation isKindOfClass:[RestAnnotation class]]) {
static NSString *identifier = #"rests";
MKAnnotationView *restView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(restView == nil) {
restView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
restView.displayPriority = MKFeatureDisplayPriorityRequired;
restView.image = [UIImage imageNamed:#"restann.png"];
restView.canShowCallout = YES;
}
else {
restView.annotation = annotation;
}
return restView;
}
As Ramis said, the problem is that you're setting the displayPriority before you even instantiate the pulsingView. Thus, the MKAnnotationView you subsequently instantiate never got its displayPriority set.
That having been said, I'd suggest a slightly different implementation, though. Specifically, I'd move the configuration of the annotation view into its own subclass, rather than cluttering the view controller with this sort of code:
#interface MeetUpAnnotationView: MKAnnotationView
#end
#implementation MeetUpAnnotationView
- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self) {
self.displayPriority = MKFeatureDisplayPriorityRequired;
self.canShowCallout = YES;
self.image = [UIImage imageNamed:#"meetupbeacon.png"];
}
return self;
}
- (void)setAnnotation:(id<MKAnnotation>)annotation {
[super setAnnotation:annotation];
self.displayPriority = MKFeatureDisplayPriorityRequired;
}
#end
Then, if targeting iOS 11 or later, your view controller's viewDidLoad should register that subclass.
Now, if this is the only annotation view that you’re showing in iOS 11, you don't need a viewForAnnotation at all and can just register your default annotation view:
[self.mapView registerClass:[MeetUpAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];
And having registered the annotation view class, you're done. No viewForAnnotation is needed or desired.
The only time you have to implement viewForAnnotation in iOS 11 and later is if you have multiple custom annotation view types on your map. In that case, you'd register them:
[self.mapView registerClass:[MeetUpAnnotationView class] forAnnotationViewWithReuseIdentifier:meetupIdentifier];
[self.mapView registerClass:[SomeOtherAnnotationView class] forAnnotationViewWithReuseIdentifier:someOtherIdentifier];
And then use dequeueReusableAnnotationViewWithIdentifier:forAnnotation: in your viewForAnnotation:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MeetupAnn class]]) {
return [mapView dequeueReusableAnnotationViewWithIdentifier:meetupIdentifier forAnnotation:annotation];
}
if ([annotation isKindOfClass:[SomeOtherAnnotation class]]) {
return [mapView dequeueReusableAnnotationViewWithIdentifier:someOtherIdentifier forAnnotation:annotation];
}
...
return nil;
}
As you can see, in iOS 11 (especially when you have only one annotation view type), the code is greatly simplified.
But if you need to support older iOS versions, you can't register the identifier and you have to use the older dequeueReusableAnnotationViewWithIdentifier:, but I'd still let the annotation view subclass take care of configuring itself. But, a more subtle problem in your code is that you are not setting the annotation in an else clause, so make sure to do that, e.g.:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MeetupAnn class]]) {
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:meetupIdentifier];
if (!annotationView) {
annotationView = [[MeetUpAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:meetupIdentifier];
} else {
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
You should check if some of your geocoding requests are failing inconsistently.
CLGeocoder rate limits your requests and if you do too many requests in a short time, you'll receive an error. https://developer.apple.com/documentation/corelocation/clgeocoder/1423509-geocodeaddressstring?language=objc
Check if you are getting any reason for failure inside NSError* error inside the completionHandler block.
As many times as it fails, you should see as many less number of annotations on the MapView because it is not entering the following code path.
if (placemarks && placemarks.count > 0) {
// Not entering here
}
if (nil != error) {
// Could land here
}
The only other reason would be not properly calculating map region to show all annotations in screen. Make sure you are calculating/adjusting the region correctly upon each annotation being added to the mapView.
// Define these variables globally in the view controller
CLLocationDegrees minLatitude = 90.0;
CLLocationDegrees maxLatitude = -90.0;
CLLocationDegrees minLongitude = 180.0;
CLLocationDegrees maxLongitude = -180.0;
// Call following method every time a new annotation needs to be added to the mapView
-(void)addAnnotation:(id<MKAnnotation>)annotation toMapView:(MKMapView*)mapView {
// Add the annotation to map
[mapView addAnnotation:annotation];
// Set the map region to make it visible along with all other annotations
CLLocationDegrees latitude = annotation.coordinate.latitude;
CLLocationDegrees longitude = annotation.coordinate.longitude;
minLatitude = min(minLatitude, latitude);
maxLatitude = max(maxLatitude, latitude);
minLongitude = min(minLongitude, longitude);
maxLongitude = max(maxLongitude, longitude);
CLLocationDegrees latitudeDelta = (maxLatitude - minLatitude);
CLLocationDegrees longitudeDelta = (maxLongitude - minLongitude);
CLLocationDegrees midLatitude = (maxLatitude - latitudeDelta/2);
CLLocationDegrees midLongitude = (maxLongitude - longitudeDelta/2);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(midLatitude, midLongitude);
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
MKCoordinateRegion region = MKCoordinateRegionMake(center, span);
if (CLLocationCoordinate2DIsValid(center)) {
[mapView setRegion:region animated:YES];
}
}
You are assigning MKFeatureDisplayPriorityRequired to empty object. Try to assign display priority in two case:
When pulsingView is not nil.
After pulsingView allocated.
if([annotation isKindOfClass:[meetupAnn class]]) {
static NSString *identifier = #"currentLocation";
MKAnnotationView *pulsingView = (MKAnnotationView *)[self.friendsMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(pulsingView == nil) {
pulsingView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
pulsingView.displayPriority = MKFeatureDisplayPriorityRequired;
pulsingView.canShowCallout = YES;
pulsingView.image = [UIImage imageNamed:#"meetupbeacon.png"];
NSLog(#"Location Returned");
} else {
pulsingView.displayPriority = MKFeatureDisplayPriorityRequired;
// TODO: Do map pin initial setup.
}
}

exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'

usually this code has worked perfectly for me, up until recently I went to update my project to support the latest iOS and when clicking on the map button, receive the error;
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
Prior to using Xcode 9 it would work correctly, so I am guessing the way the code works is slightly different now.
The array is NSArray *arr_OfCountryCode;
And we initialise it in the viewDidLoad
//Initialize NSArray object with Images
arr_OfCountryCode=#[#"AF",#"AL",#"DZ",#"AS",#"AD",#"AO",#"AI",#"AQ",#"AG",#"AR",#"AM",#"AW",#"AC",#"AU",#"AT",#"AZ",#"BS",#"BH",#"BD",#"BB",#"BY",#"BE",#"BZ",#"BJ",#"BM",#"BT",#"BO",#"BA",#"BW",#"BV",#"BR",#"IO",#"VG",#"BN",#"BG",#"BF",#"BI",#"KH",#"CM",#"CA",#"IC",#",CV",#"BQ",#"KY",#"CF",#"EA",#"TD",#"CL",#"CN",#"CX",#"CP",#"CC",#"CO",#"KM",#"CD",#"CG",#"CK",#"CR",#"HR",#"CU",#"CW",#"CY",#"CZ",#"CI",#"DK",#"DG",#"DJ",#"DM",#"DO",#"EC",#"EG",#"SV",#"GQ",#"ER",#"EE",#"ET",#"FK",#"FO",#"FJ",#"FI",#"FR",#"FG",#"PF",#"TF",#"GA",#"GM",#"GE",#"DE",#"GH",#"GI",#"GR",#"GL",#"GD",#"GP",#"GU",#"GT",#"GG",#"GN",#"GW",#"GY",#"HT",#"HM",#"HN",#"HK",#"HU",#"IS",#"IN",#"ID",#"IR",#"IQ",#"IE",#"IM",#"IL",#"IT",#"JM",#"JP",#"JE",#"JO",#"KZ",#"KE",#"KI",#"XK",#"KW",#"KG",#"LA",#"LV",#"LB",#"LS",#"LR",#"LY",#"LI",#"LT",#"LU",#"MO",#"MK",#"MG",#"MW",#"MY",#"MV",#"ML",#"MT",#"MH",#"MQ",#"MR",#"MU",#"YT",#"MX",#"FM",#"MD",#"MC",#"MN",#"ME",#"MS",#"MA",#"MZ",#"MM",#"NA",#"NR",#"NP",#"NL",#"NC",#"NZ",#"NI",#"NE",#"NG",#"NU",#"NF",#"KP",#"MP",#"NO",#"OM",#"PK",#"PW",#"PS",#"PA",#"PG",#"PY",#"PE",#"PH",#"PN",#"PL",#"PT",#"PR",#"QA",#"RO",#"RU",#"RW",#"RE",#"WS",#"SM",#"SA",#"SN",#"RS",#"SC",#"SL",#"SG",#"SX",#"SK",#"SI",#"SB",#"SO",#"ZA",#"GS",#"KR",#"SS",#"ES",#"LK",#"BL",#"SH",#"KN",#"LC",#"MF",#"PM",#"VC",#"SD",#"SR",#"SJ",#"SZ",#"SE",#"CH",#"SY",#"ST",#"TW",#"TJ",#"TZ",#"TH",#"TL",#"TG",#"TK",#"TO",#"TT",#"TA",#"TN",#"TR",#"TM",#"TC",#"TV",#"UM",#"VI",#"UG",#"UA",#"AE",#"GB",#"US",#"UY",#"UZ",#"VU",#"VA",#"VE",#"VN",#"WF",#"EH",#"YE",#"ZM",#"ZW",#"AX"];
When the user taps the button, a location on the map is shown at random, within the actionMethod to do that is;
str_Type = #"Randum";
self.mapView.hidden = NO;
int randomIndex = arc4random() % [arr_OfCountryCode count];
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=false",[arr_OfCountryCode objectAtIndex:randomIndex]];
NSURL *url = [[NSURL alloc] initWithString:urlString];
I am struggling as to why the array is classed as empty when it worked for multiple iOS versions and devices prior to the latest.
It is showing as nil as soon as I check it in Xcode, other arrays initialise before it with no issue, I even tried copying an existing array, renaming it to *arr_OfCountryCode; and that still showed as nil !
In this method (entire posted below) I believe the problem is occuring.
- (IBAction)actionMethod:(UIButton *)sender {
if ([sender tag] == 0) {
self.musicView.hidden = NO;
[self.tbl_MusicTable reloadData];
} else if ([sender tag] == 1) {
str_Type = #"Randum";
self.mapView.hidden = NO;
int randomIndex = arc4random() % [arr_OfCountryCode count];
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=false",[arr_OfCountryCode objectAtIndex:randomIndex]];
NSURL *url = [[NSURL alloc] initWithString:urlString];
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:url] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"%#",error.description);
} else {
NSDictionary *jsonObject=[NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableLeaves
error:nil];
NSDictionary *places = [[[[jsonObject objectForKey:#"results"] objectAtIndex:0] objectForKey:#"geometry"] objectForKey:#"location"];
NSDictionary *locations = [[[jsonObject objectForKey:#"results"] objectAtIndex:0] objectForKey:#"address_components"];
float lat = [[places objectForKey:#"lat"] floatValue];
float lon = [[places objectForKey:#"lng"] floatValue];
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.50;
span.longitudeDelta = 0.50;
location.latitude = lat;
location.longitude = lon;
region.span = span;
region.center = location;
[self.mk_MapView setRegion:region animated:YES];
NSString *str_Title = [[locations valueForKey:#"long_name"] objectAtIndex:0];
NSString *str_Short = [[locations valueForKey:#"short_name"] objectAtIndex:0];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = location;
point.title = str_Title;
point.subtitle = str_Short;
[self.mk_MapView addAnnotation:point];
}
}];
}
}
The further code for corelocation is here
#pragma mark - CLLocationManager Delegate Method
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if ([str_Type isEqualToString:#"Custom"]) {
CLLocation *currentLocation = newLocation;
NSString *str_Longitude;
NSString *str_Latitude;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.020;
span.longitudeDelta = 0.020;
location.latitude = currentLocation.coordinate.latitude;
location.longitude = currentLocation.coordinate.longitude;
region.span = span;
region.center = location;
[self.mk_MapView setRegion:region animated:YES];
if (currentLocation != nil) {
str_Longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
str_Latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
// Reverse Geocoding
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = currentLocation.coordinate;
point.title = placemark.country;
point.subtitle = placemark.locality;
[self.mk_MapView addAnnotation:point];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
} else {
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = location;
point.title = placemark.country;
point.subtitle = placemark.locality;
[self.mk_MapView addAnnotation:point];
}
}
#pragma mark - MKMapView Delegate Methods
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != self.mk_MapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[self.mk_MapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
//pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
//pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"HesOnThisMap"]; //
}
else {
//[self.mk_MapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
CGRect endFrame = aV.frame;
aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - 230.0, aV.frame.size.width, aV.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.45];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[aV setFrame:endFrame];
[UIView commitAnimations];
}
}
It was to do with the google maps api callbacks, it was crashing when it hit the maximum callbacks

map kit not working

i am working on a map kit that shows all the data extracted from an xml web service .this web service contains 3 variables longitude (lon),latitude(lat), the name of the atm (atmName).the for loop is extracting the data from the Aatm array but the pins are not showing on the map .also my pins are all from the same region thats why i used a default center from the Aatm array with a default value. here is my code
thank you for helping me in advance :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Aatm = [[NSMutableArray alloc] init];
pinArray = [[NSMutableArray alloc] init];
NSString *url=#"http://192.168.83.1:8080/jeeRestApp-1.0/rest/Atm";
NSXMLParser *parser;
parser=[[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
parser.delegate=self;
if ([parser parse]==FALSE){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Erreur" message:#"erreur de connection!" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
[alert show];
}
//Setting the approximate region
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.mapview setShowsUserLocation:YES];
MKCoordinateRegion Myregion;
CLLocationCoordinate2D center1;
//replace by variable -----------------------------------
atm=[Aatm objectAtIndex:1];
center1.latitude=[atm.lat doubleValue];
center1.longitude=[atm.lon doubleValue];
NSLog(#"la latitude (defaut) est: %#",atm.lat);
MKCoordinateSpan span1;
span1.longitudeDelta = 0.01f;
span1.latitudeDelta = 0.01f;
Myregion.center=center1;
Myregion.span=span1;
[mapview setRegion:Myregion animated:YES];
for(int i = 0; i<=[Aatm count] - 1;i++)
{
//CLLocationCoordinate2D newCoord = { atm.lat, atm.lon};
atm=[Aatm objectAtIndex:i];
CLLocationCoordinate2D pinLocaton;
pinLocaton.latitude=[atm.lat doubleValue];
NSLog(#"latitude est de :%#",atm.lat);
pinLocaton.longitude=[atm.lon doubleValue];
NSLog(#"longitude est de :%#",atm.lon);
MKPointAnnotation *annotation=[MKPointAnnotation alloc];
annotation.title=atm.atmName;
NSLog(#"latitude est de :%#",atm.atmName);
annotation.coordinate=pinLocaton;
MKPinAnnotationView *newAnnotation = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotation1"];
newAnnotation.pinColor = MKPinAnnotationColorGreen;
newAnnotation.animatesDrop = YES;
newAnnotation.canShowCallout = NO;
[newAnnotation setSelected:YES animated:YES];
[mapview addAnnotation:annotation];
NSLog(#"annotation added");
}
You need to implement mapView:viewForAnnotation: something like:
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if([annotation isKindOfClass:[MKPointAnnotation class]])
{
MKPinAnnotationView* view = (MKPinAnnotationView*) [mapView dequeueReusableAnnotationViewWithIdentifier:#"pin"];
if(!view)
{
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"pin"];
}
else
{
view.annotation = annotation;
}
view.pinColor = MKPinAnnotationColorGreen;
view.animatesDrop = YES;
view.canShowCallout = NO;
return view;
}
else
{
return nil;
}
}

MapBox polyline not shown on map

I have a problem when trying to add a polyline on the map.
I get directions from MKDirections, and create a RMPolylineAnnotation, but it does not appear on the map.
As I can see, the following method is called just once when the map appears:
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
Here is the code I am using:
- (void)getRoute {
CLLocation *source = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocation *destination = [[CLLocation alloc] initWithLatitude:self.mapView.selectedAnnotation.coordinate.latitude longitude:self.mapView.selectedAnnotation.coordinate.longitude];
[AppleDirectionManager getDirectionsFromPoint:source toPoint:destination transportType:MKDirectionsTransportTypeAutomobile withCompletion:^(MKDirectionsResponse *result) {
self.routeStepsArray = [[result.routes firstObject] steps];
for (MKRoute *route in result.routes) {
NSMutableArray *points = [NSMutableArray array];
for (int i = 0; i < route.polyline.pointCount; i++) {
MKMapPoint point = route.polyline.points[i];
CLLocation *location = [[CLLocation alloc] initWithLatitude:point.x longitude:point.y];
[points addObject:location];
}
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *arr = [points copy];
RMPolylineAnnotation *polyline = [[RMPolylineAnnotation alloc] initWithMapView:self.mapView points:arr];
[self.mapView addAnnotation:polyline];
});
}
}];
}
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation {
if (annotation.isUserLocationAnnotation)
return nil;
RMMarker *marker = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:#"blabla.png"]];
[marker setCanShowCallout:YES];
[marker setName:#"blabla"];
return marker;
}
Also I can not show a custom callout for a RMPointAnnotation.
For RMPointAnnotation it's easily.
_polylineAnnotation = [[RMPolylineAnnotation alloc] initWithMapView:_mapView points:#[Location,Location]];
_polylineAnnotation.lineColor = [UIColor redColor];
_polylineAnnotation.lineWidth = 10.0f;
[_mapView addAnnotation:_polylineAnnotation];

New PList Retrieval Code Prevents MKMapView Delegate Method From Being Called (iOS)

I added a plist database to store information for annotations in a MKMapView. Once I implemented the code to grab the information, my delegate methods are no longer being called.
The code I added was:
- (void)viewDidLoad
{
NSMutableArray *annotations = [[NSMutableArray alloc]init];
NSString *path = [[NSBundle mainBundle] pathForResource:#"MillersStores" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *anns = [dict objectForKey:#"Root"];
for(int i = 0; i < [anns count]; i++) {
float realLatitude = [[[anns objectAtIndex:i] objectForKey:#"Latitude"] floatValue];
float realLongitude = [[[anns objectAtIndex:i] objectForKey:#"Longitude"] floatValue];
MillersLocations *myAnnotation = [[MillersLocations alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = realLatitude;
theCoordinate.longitude = realLongitude;
myAnnotation.coordinate = theCoordinate;
myAnnotation.title = [[anns objectAtIndex:i] objectForKey:#"Title"];
myAnnotation.subtitle = [[anns objectAtIndex:i] objectForKey:#"Address"];
[mapView addAnnotation:myAnnotation];
[annotations addObject:myAnnotation];
[myAnnotation release];
}
}
And this is one of delegate method that's no longer being called is:
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id ) annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKPinAnnotationView *pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
UIImageView *leftIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"MillersAnnotation.png"]];
pinView.leftCalloutAccessoryView = leftIconView;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = rightButton;
return pinView;
}
I have another delegate method in there that also zooms into the User's Location that's not being called either, as well as the calloutAccessoryControlTapped method that's no longer being called.
I know it has something to do with the new code, but I'm confused as to how to even debug this because it's not giving me errors and I can't log it because the entire methods aren't even being called. When I get rid of the new code, the old code works fine...What is it in the new code that negates the old code?
It sounds like the map view's delegate property is not set.
Did the old code contain this line:
mapView.delegate = self;
Add that to viewDidLoad or, in IB, connect the map view's delegate outlet to File's Owner.

Resources