MapView Overlay Drawing - ios

I have been facing problem which is mkoverlay color. When I open the mapview, sometimes instead of drawing walking path, it colors with biking activity. I do not know how to fix the problem. Even though I have not done any biking activity but it draws biking activity with blue color.
Here is the code implementation.
- (void)showLines {
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSArray* coordinate_array = [[NSArray alloc] init];
int arrayCount = 0;
// walking
NSData *data =[def objectForKey:#"walking_coordinate"];
NSMutableArray *walking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:walking_array];
arrayCount = (int)[walking_array count];
color = 1;
[self parseArray:coordinate_array withArrayCount:arrayCount];
// driving
data =[def objectForKey:#"driving_coordinate"];
NSMutableArray *driving_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:driving_array];
arrayCount = (int)[driving_array count];
color = 2;
[self parseArray:coordinate_array withArrayCount:arrayCount];
// biking
data =[def objectForKey:#"biking_coordinate"];
NSMutableArray *biking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:biking_array];
arrayCount = (int)[biking_array count];
color = 3;
[self parseArray:coordinate_array withArrayCount:arrayCount];
}
- (void) parseArray:(NSArray *) coordinate_array withArrayCount:(int)arrayCount
{
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < arrayCount; i++) {
CoordinateModel *coord = [coordinate_array objectAtIndex:i];
[tempArray addObject:coord];
if ((int)coord.latitude == -1 || (int)coord.longitude == -1 || i == arrayCount-1) {
// this is end of one segment
[tempArray removeLastObject];
CLLocationCoordinate2D *pointsCoordinate = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * [tempArray count]);
for (int j = 0; j < [tempArray count]; j++) {
CoordinateModel *point = [tempArray objectAtIndex:j];
CLLocationCoordinate2D old_coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude);
pointsCoordinate[j] = old_coordinate;
// NSLog(#"(%f, %f)", old_coordinate.latitude, old_coordinate.longitude);
}
if ([tempArray count] > 0) {
int countTemp = (int)[tempArray count];
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:pointsCoordinate count:countTemp];
[mapView addOverlay:polyline];
[tempArray removeAllObjects];
}
}
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineView *lineView = [[MKPolylineView alloc] initWithPolyline:overlay];
lineView.lineWidth = 8;
if (color == 1) {
// walking
lineView.strokeColor = [UIColor greenColor];
lineView.fillColor = [UIColor greenColor];
}
else if(color == 2) {
// driving
lineView.strokeColor = [UIColor redColor];
lineView.fillColor = [UIColor redColor];
}
else if(color == 3) {
// biking
lineView.strokeColor = [UIColor blueColor];
lineView.fillColor = [UIColor blueColor];
}
else {
lineView.strokeColor = [UIColor blackColor];
lineView.fillColor = [UIColor blackColor];
}
return lineView;
}
return nil;
}

In the viewForOverlay delegate method, the overlay color is set using the external variable color which is set before calling parseArray for each type of overlay.
However, there is no guarantee when the delegate method will be called by the map view and it's possible for the delegate method to be called multiple times for the same overlay after you've already added all the overlays (eg. if you zoom/pan the map and the overlay comes back into view).
Since the last color value you set is 3 (for "biking"), any calls that the map view makes to the delegate method after the overlays are already added will end up drawing the overlay with the biking color.
To fix this, you need to be able to determine what color to draw the overlay inside the delegate method itself using some property of the overlay parameter (and not relying on some external variable).
The simplest way to do this is to use the MKPolyline's title property.
See this answer and this answer that explain the fact that MKPolyline has a title property.
So what you could do in your case is:
Make color a parameter that you pass to your parseArray method.
In the parseArray method, after creating polyline, set its title to the color:
polyline.title = [NSString stringWithFormat:#"%d", color];
In viewForOverlay, check the overlay's title property and set the color accordingly. See a specific example in different coloured polygon overlays (it shows it for polygon but the same can be done with polylines).

Here is the answer based on Anna answer to help whomever wants to see in code.
- (void)showLines2 {
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSArray* coordinate_array = [[NSArray alloc] init];
int arrayCount = 0;
// walking
NSData *data =[def objectForKey:#"walking_coordinate"];
NSMutableArray *walking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:walking_array];
arrayCount = (int)[walking_array count];
color = 1;
[self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];
// driving
data =[def objectForKey:#"driving_coordinate"];
NSMutableArray *driving_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:driving_array];
arrayCount = (int)[driving_array count];
color = 2;
[self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];
// biking
data =[def objectForKey:#"biking_coordinate"];
NSMutableArray *biking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
coordinate_array = [NSArray arrayWithArray:biking_array];
arrayCount = (int)[biking_array count];
color = 3;
[self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];
}
- (void) parseArray:(NSArray *) coordinate_array withArrayCount:(int)arrayCount withColor:(int)polyColor
{
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i < arrayCount; i++) {
CoordinateModel *coord = [coordinate_array objectAtIndex:i];
[tempArray addObject:coord];
if ((int)coord.latitude == -1 || (int)coord.longitude == -1 || i == arrayCount-1) {
// this is end of one segment
[tempArray removeLastObject];
CLLocationCoordinate2D *pointsCoordinate = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * [tempArray count]);
for (int j = 0; j < [tempArray count]; j++) {
CoordinateModel *point = [tempArray objectAtIndex:j];
CLLocationCoordinate2D old_coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude);
pointsCoordinate[j] = old_coordinate;
// NSLog(#"(%f, %f)", old_coordinate.latitude, old_coordinate.longitude);
}
if ([tempArray count] > 0) {
int countTemp = (int)[tempArray count];
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:pointsCoordinate count:countTemp];
polyline.title = [NSString stringWithFormat:#"%d", color];
[mapView addOverlay:polyline];
[tempArray removeAllObjects];
}
}
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineView *lineView = [[MKPolylineView alloc] initWithPolyline:overlay];
lineView.lineWidth = 8;
// ActivityType currentActivityType = [DataManager sharedInstance].activityType;
if ([overlay.title isEqualToString:#"1"]) {
// walking
lineView.strokeColor = [UIColor greenColor];
lineView.fillColor = [UIColor greenColor];
}
else if([overlay.title isEqualToString:#"2"]) {
// driving
lineView.strokeColor = [UIColor redColor];
lineView.fillColor = [UIColor redColor];
}
else if([overlay.title isEqualToString:#"3"]) {
// biking
lineView.strokeColor = [UIColor blueColor];
lineView.fillColor = [UIColor blueColor];
}
else {
lineView.strokeColor = [UIColor blackColor];
lineView.fillColor = [UIColor blackColor];
}
return lineView;
}
return nil;
}

Related

How to filter UIColor object in NSMutableArray

I am generating random colors and storing in NSmutableArray like this
for(int i=0; i<1000; i++) {
UIColor *c = [self colorGen];
[_cArray addObject:c];
}
I want to check that every time I add color to array its not repeating, How I apply predicate to _cArray to check color return by [self colorGen] method is not already exist in _cArray, for example _cArray already contains red color after 10 iteration [self colorGen] again return red color so how I can avoid adding it again my array.
for(int i=0; i<1000; i++) {
UIColor *c = [self colorGen];
if (![_cArray containsObject:c]) {
[_cArray addObject:c];
}
}
plz use this code
you can do like,
for(int i=0; i<1000; i++) {
UIColor *c = [self colorGen];
if (![_cArray containsObject:c] ) {
[_cArray addObject:c];
}
else{
NSLog(#"already there");
}
}
Change in methods colorGen it should return hex value of UIColor
for(int i=0; i<1000; ) {
NSString *strCode = [self colorGen];
if (![_cArray containsObject:strCode] ) {
[_cArray addObject:strCode];
i++;
}
else{
NSLog(#"already there");
}
}
NSMutableSet *colors = [NSMutableSet set];
while (colors.count < 1000) {
[colors addObject:[self colorGen]];
}
example code for the way UIColor objects are compared:
NSMutableSet *colors = [NSMutableSet set];
UIColor *color1 = [UIColor colorWithRed:0.1 green:0.2 blue:0.3 alpha:1];
UIColor *color2 = [UIColor colorWithRed:0.1 green:0.2 blue:0.3 alpha:1];
[colors addObjectsFromArray:#[color1, color2]];
NSLog(#"%lu", (unsigned long)colors.count);
this code prints 1 indicating that both colors are treated to be equal!

show user's location with a custom pin on map and in a table view

i m showing user's location in a map view(apple map) with custom pin and those same pins are shown in a table view in front of the user name.Each user should have a different pin and if the user name occurs twice then it should have the same pin colour as the previous one.
This is the table view screen shot and below this table view there is a map view:
if in the table view "user name" has blue pin then in the map "username's" location shud be shown with blue pin.
if user2 has green pin in table, it should be green in map as well.
the response i m getting is
{
"driver_or_rider" = 1;
email = "ish#gmail.com";
isGuest = 0;
lat = "47.606209";
long = "-122.332071";
name = "ish bids";
"status_trip" = 1;
"user_image_url" = "http://app/image/1458101010.userimage";
},
{
"driver_or_rider" = 0;
email = "arin#gmail.com";
isGuest = 0;
lat = "34.052227";
long = "-118.243660";
name = "arin John";
"status_trip" = 1;
"user_image_url" = "http://app/image/5b3ee2e9fb51c7b20303a95b93bf63b2.";
},
{
"driver_or_rider" = 0;
email = "deepak12#gmail.com";
isGuest = 0;
lat = "31.968599";
long = "-99.901813";
name = "Deepak Chaudhary chaudhary ";
"status_trip" = 1;
"user_image_url" = "http://app/image/2197c75dc6b2bbd0ff26008a987781f3.";
},
{
"driver_or_rider" = 0;
email = "ish#gmail.com";
isGuest = 1;
lat = "31.968599";
long = "-99.901813";
name = "Deepak Chaudhary chaudhary 's Guest";
"status_trip" = 1;
"user_image_url" = "http://app/image/no-image.png";
},
{
"driver_or_rider" = 0;
email = "ish#gmail.com";
isGuest = 1;
lat = "41.878114";
long = "-87.629798";
name = "shiv Shankar 's Guest";
"status_trip" = 1;
"user_image_url" = "http://app/image/no-image.png";
},
{
"driver_or_rider" = 0;
email = "shiv#gmail.com";
isGuest = 0;
lat = "41.878114";
long = "-87.629798";
name = "shiv Shankar ";
"status_trip" = 1;
"user_image_url" = "http://app/image/1458129359.userimage";
},
{
"driver_or_rider" = 0;
email = "andrew.payasi#gmail.com";
isGuest = 0;
lat = "43.65322577127058";
long = "-79.38318371772766";
name = username;
"status_trip" = 1;
"user_image_url" = "http://app/image/1456821877.png";
}
)
this is the code in cell for row at index
int randomNumber = indexPath.row % [imageNameArray count];
NSString* nameStr=[goersInfo valueForKey:#"name"];
NSArray * nameStrArray = [nameStr componentsSeparatedByString: #"'s"];
nameStr=[nameStrArray objectAtIndex:0];
NSNumber *indexNumber = self.pinDictionary[nameStr];
index = indexNumber.unsignedIntegerValue;
cell.PinImageView.image=[UIImage imageNamed:[imageNameArray objectAtIndex:index]];
this is dictionary where name are stored
- (void)setupPinDictionary
{
self.pinDictionary = [NSMutableDictionary dictionary];
self.imageNameArray = [[NSArray alloc] initWithObjects:#"pin2#2x.png", #"pin3#2x.png", #"pin4#2x.png", #"pin5#2x.png", #"pin6#2x.png",#"pin8#2x.png",#"pin9#2x.png", nil];
NSUInteger pinImageCount = self.imageNameArray.count;
for (NSDictionary *goersInfo in tableGoersList) {
NSString* nameStr=[goersInfo valueForKey:#"name"];
NSArray * nameStrArray = [nameStr componentsSeparatedByString: #"'s"];
nameStr=[nameStrArray objectAtIndex:0];
if (self.pinDictionary[nameStr] == nil) {
indexPin = arc4random() % pinImageCount;
self.pinDictionary[nameStr] = [NSNumber numberWithUnsignedInteger: indexPin];
}
}
Initially this method is called
-(void)doJourneyGoersList:(id)responseObject{
NSDictionary *dict=[responseObject[#"Count"] firstObject];
checkLocation=[[NSMutableArray alloc]init];
if (dict==nil) {
return;
}
[_messagesButton.badgeButton setBadgeValue:dict[#"Count_Masssage"]];
[_invitesButton.badgeButton setBadgeValue:dict[#"invite_count"]];
[_matchedButton.badgeButton setBadgeValue:dict[#"Count_Match"]];
goersList= [responseObject objectForKey:#"statement"];
CLLocationCoordinate2D orginCllocation=CLLocationCoordinate2DMake([_tripDetails[#"origin_lat"] doubleValue], [_tripDetails[#"origin_long"] doubleValue]);
MKPointAnnotation *annotation =[[MKPointAnnotation alloc] init];
annotation.coordinate=orginCllocation;
[checkLocation addObject:annotation];
tableGoersList=[NSMutableArray new];
for (NSDictionary *dict in goersList) {
NSMutableDictionary *localdict=[NSMutableDictionary new];
loc=[NSMutableDictionary new];
[localdict setObject:[dict objectForKey:#"name"] forKey:#"name"];
[localdict setObject:[dict objectForKey:#"email"] forKey:#"email"];
if ([dict[#"status_trip"] isEqualToString:#"confirm"]) {
[localdict setObject:#"1" forKey:#"status_trip"];
[loc setObject:[dict objectForKey:#"origin_lat"] forKey:#"lat"];
[loc setObject:[dict objectForKey:#"origin_long"] forKey:#"long"];
CLLocationCoordinate2D location=CLLocationCoordinate2DMake([loc[#"lat"] doubleValue], [loc[#"long"] doubleValue]);
[localdict setObject:[dict objectForKey:#"origin_lat"] forKey:#"lat"];
[localdict setObject:[dict objectForKey:#"origin_long"] forKey:#"long"];
if (location.latitude == orginCllocation.latitude && location.longitude == orginCllocation.longitude) {
//location is origin, skip this since it is already added
} else {
MKPointAnnotation *annotation =[[MKPointAnnotation alloc] init];
annotation.coordinate=location;
[checkLocation addObject: annotation];
}
NSLog(#"check location %#",checkLocation);
}
else
[localdict setObject:#"0" forKey:#"status_trip"];
if ([dict[#"isGuest"] isEqualToString:#"1"]) {
[localdict setObject:#"1" forKey:#"isGuest"];
}
else
[localdict setObject:#"0" forKey:#"isGuest"];
[localdict setObject:[dict objectForKey:#"user_image_url"] forKey:#"user_image_url"];
if ([dict[#"driver_or_rider"] isEqualToString:#"Drive"]) {
[localdict setObject:#"1" forKey:#"driver_or_rider"];
[tableGoersList insertObject:localdict atIndex:0];
}
else
{
[localdict setObject:#"0" forKey:#"driver_or_rider"];
[tableGoersList addObject:localdict];
}
//add the objects to the array
}
CLLocationCoordinate2D parkCllocation=CLLocationCoordinate2DMake([_tripDetails[#"park_lat"] doubleValue], [_tripDetails[#"park_long"] doubleValue]);
MKPointAnnotation *jauntAnnotationPark =[[MKPointAnnotation alloc] init];
jauntAnnotationPark.coordinate=parkCllocation;
[checkLocation addObject:jauntAnnotationPark];
[mapView showAnnotations: checkLocation animated:NO];
[mapView setCenterCoordinate:mapView.region.center animated:NO];
int count = [checkLocation count];
CLLocationCoordinate2D coordinateArray[count];
for (int i = 0; i < count; i++) {
coordinateArray[i] = ((MKPointAnnotation *)checkLocation[i]).coordinate;
}
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:count];
[mapView addOverlay:self.routeLine];
[self setupPinDictionary];
[self.ridersTableView reloadData];
}
and this is the code for view for annotation
{
imageNameArray = [[NSArray alloc] initWithObjects:#"pin2#2x.png", #"pin3#2x.png", #"pin4#2x.png", #"pin5#2x.png", #"pin6#2x.png",#"pin8#2x.png",#"pin9#2x.png",nil];
[self setupPinDictionary];
myAnnotation.image=[UIImage imageNamed:[imageNameArray objectAtIndex:indexPin]];
}
return myAnnotation;
}

UIPopoverController is not so with a color

Does anyone know why is appearing white part? My View is already gray, but gets two white pieces
whites: Arrow and final Popover!
[UPDATE]
this is the code that calls the popover and makes the arrow points to the button that was clicked!
- (void) buttonFilter {
if (viewFilter == #"Artistas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"TipoArtistaViewController"]; // MUDAR PARA O NOVO FILTRO DE ARTISTAS
} else if (viewFilter == #"Músicas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"CategoriaViewController"];
}
[self callFilter:btnFilter Filter:content];
}
- (void)callFilter:(id)sender Filter:(UIViewController *) content{
self.currentPop = popoverController;
popoverController = [[WYPopoverController alloc] initWithContentViewController:content];
UIButton * bt = (UIButton * )sender;
UIView *view = [bt valueForKey:#"view"];
popoverController.popoverContentSize = CGSizeMake(320, 180);
popoverController.delegate = self;
[popoverController presentPopoverFromRect:view.bounds inView:view permittedArrowDirections:WYPopoverArrowDirectionAny animated:YES];
}
the next is where to mount the session:
//extend and collpase
- (void)setupViewController {
categoriaBD = [categoriaDAO selectCategoria];
self.data = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSMutableDictionary * teste = [categoriaBD objectForKey:[NSString stringWithFormat:#"%i", i]];
ID = [[teste objectForKey:#"1"] integerValue];
subcategoriaBD = [categoriaDAO selectSubCategoriaByCategoriaID:ID];
NSMutableArray* section = [[NSMutableArray alloc] init];
for (int j = 0; j < [subcategoriaBD count]; j++)
{
NSMutableDictionary * subCat = [subcategoriaBD objectForKey:[NSString stringWithFormat:#"%i", j]];
[section addObject:[NSString stringWithFormat:[subCat objectForKey:#"1"]]];
}
[self.data addObject:section];
}
self.headers = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSString *inStr = [NSString stringWithFormat: #"%i", (int)i];
nomeCategoria = [categoriaBD objectForKey:inStr];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 310, 40)];
[label setText:[nomeCategoria objectForKey:#"2"]];
UIView* header = [[UIView alloc] init];
[header setBackgroundColor:[UIColor colorWithRed:(226/255.0) green:(226/255.0) blue:(226/255.0) alpha:1]];
[header addSubview:label];
[self.headers addObject:header];
}
}
You can to create a custom UIPopoverBackgroundView subclass that sets the properties of the arrow you want.
popoverController.popoverBackgroundViewClass = [MyPopoverBackgroundView class];

NSMutable Array crashed when being accessed at other method

-(void)Aray
{
NSMutableArray *ColorArray = [[NSMutableArray alloc] init];
if(Counter < NewColor)
{
[ColorArray addObject:[NSNumber numberWithInteger:ColorTemp]];
Counter += 1;
}
}
-(IBAction)Go:(id)sender
{
NSMutableArray *ColorArray = [[NSMutableArray alloc] init];
Color = [[ColorArray objectAtIndex:Index] intValue];
if(Color == 2)
{
ColorLabel.text = #"The Color is Black";
Screen.image = [UIImage imageNamed:#"BlackTile.png"];
}
else
{
Screen.image = [UIImage imageNamed:#"Tunnel.png"];
ColorLabel.text = #"The Color is Green";
}
Index += 1;
}
-(IBAction)Black:(id)sender
{
ColorTemp = 2;
NewColor += 1;
[self Array];
}
-(IBAction)Green:(id)sender
{
ColorTemp = 1;
NewColor += 1;
[self Array];
}
The issue is that the ColorArray needs to be an instance variable (or #property) of the class so that it persists outside of the method calls.
This code will always crash, regardless of the value of Index:
NSMutableArray *ColorArray = [[NSMutableArray alloc] init];
Color = [[ColorArray objectAtIndex:Index] intValue];
Color appears to already be an instance variable (or #property), so this concept should not be alien to you.
Side note: variables conventionally start with lower case and use camal-case naming.

unable to draw mkpolyline

I have used MKMapView to show map and current user location which is working correctly.
Now I want to draw a polyline as user moves but it is not working I tried follwing code:
for(int i = 0; i < [longarray count]; i++)
{
NSNumber *latt=[latarray objectAtIndex:i];
NSNumber *lonn=[longarray objectAtIndex:i];
sklat =[[NSString stringWithFormat:#"%#",latt]doubleValue];
sklongi =[[NSString stringWithFormat:#"%#",lonn]doubleValue];
CLLocationCoordinate2D coordinate1 = CLLocationCoordinate2DMake(sklat,sklongi);
// break the string down even further to latitude and longitude fields.
MKMapPoint point = MKMapPointForCoordinate(coordinate1);
// if it is the first point, just use them, since we have nothing to compare to yet.
pointsArray[i] = point;
}
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:[latarray count]];
free(pointsArray);
[mapview addOverlay:self.routeLine];
then i usedd overlay function as
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine] ;
routeLineView.fillColor = [UIColor colorWithRed:0.000 green:5.100 blue:0.100 alpha:1];
routeLineView.strokeColor = [UIColor colorWithRed:0.000 green:5.100 blue:0.100 alpha:1];
routeLineView.lineWidth = 4;
overlayView = routeLineView;
}
return overlayView;
}

Resources