Alright, the problem I'm having is that I have an overlay that is driven by the compass heading for the iphone. Whenever the compass heading changes, the line should move across the map with the heading. There are two overlays, one for the compass and another one. When only the compass overlay is being displayed, the line will flicker as it changes, but when the other line is displayed, the flicker goes away and the line moves smoothly.
- (MKOverlayView *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
SatFinderAppDelegate *appdel = (SatFinderAppDelegate *)[[UIApplication sharedApplication]delegate];
float s = [appdel.location floatValue];
if (overlay == self.headingline)
{
headinglineView = [[MKPolylineView alloc] initWithPolyline:self.headingline];
headinglineView.fillColor = [UIColor greenColor];
headinglineView.strokeColor = [UIColor greenColor];
headinglineView.lineWidth = 5;
return self.headinglineView;
}
if (overlay == self.routeLine)
{
if (s == 0) {
return routeLineView = nil;
}
routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
routeLineView.fillColor = [UIColor cyanColor];
routeLineView.strokeColor = [UIColor cyanColor];
routeLineView.lineWidth = 5;
if (ele < 0) {
routeLineView.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithFloat:12],
[NSNumber numberWithFloat:8],nil];
routeLineView.strokeColor = [UIColor redColor];
}
return routeLineView;
}
return nil;
}
...
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
//line for heading
[self headinglineupdate];
}
....
-(void)headinglineupdate
{
[map removeOverlay:self.headingline];
self.headingline = nil;
self.headingline = [MKPolyline polylineWithCoordinates:locations count:2];
[map addOverlay:headingline];
[headinglineView setNeedsDisplay];
[map setNeedsDisplay];
}
Related
I have a pickerview that is getting its information from a separate AFPickerView file. I'm getting the error "Implicit conversion of 'int' to 'UIColor*' is disallowed with ARC". Any suggestions on an easy fix for this?
Here is the code that it effects:
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
Here is the full code:
#import "AFPickerView.h"
#implementation AFPickerView
#pragma mark - Synthesization
#synthesize dataSource;
#synthesize delegate;
#synthesize selectedRow = currentRow;
#synthesize rowFont = _rowFont;
#synthesize rowIndent = _rowIndent;
#pragma mark - Custom getters/setters
- (void)setSelectedRow:(int)selectedRow
{
if (selectedRow >= rowsCount)
return;
currentRow = selectedRow;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
}
- (void)setRowFont:(UIFont *)rowFont
{
_rowFont = rowFont;
for (UILabel *aLabel in visibleViews)
{
aLabel.font = _rowFont;
}
for (UILabel *aLabel in recycledViews)
{
aLabel.font = _rowFont;
}
}
- (void)setRowIndent:(CGFloat)rowIndent
{
_rowIndent = rowIndent;
for (UILabel *aLabel in visibleViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
for (UILabel *aLabel in recycledViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
}
#pragma mark - Initialization
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// setup
[self setup];
// backgound
UIImageView *bacground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerBackground.png"]];
[self addSubview:bacground];
// content
contentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
contentView.showsHorizontalScrollIndicator = NO;
contentView.showsVerticalScrollIndicator = NO;
contentView.delegate = self;
[self addSubview:contentView];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTap:)];
[contentView addGestureRecognizer:tapRecognizer];
// shadows
UIImageView *shadows = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerShadows.png"]];
[self addSubview:shadows];
// glass
UIImage *glassImage = [UIImage imageNamed:#"pickerGlass.png"];
glassImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 76.0, glassImage.size.width, glassImage.size.height)];
glassImageView.image = glassImage;
[self addSubview:glassImageView];
}
return self;
}
- (void)setup
{
_rowFont = [UIFont boldSystemFontOfSize:24.0];
_rowIndent = 30.0;
currentRow = 0;
rowsCount = 0;
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
}
#pragma mark - Buisness
- (void)reloadData
{
// empry views
currentRow = 0;
rowsCount = 0;
for (UIView *aView in visibleViews)
[aView removeFromSuperview];
for (UIView *aView in recycledViews)
[aView removeFromSuperview];
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
rowsCount = [dataSource numberOfRowsInPickerView:self];
[contentView setContentOffset:CGPointMake(0.0, 0.0) animated:NO];
contentView.contentSize = CGSizeMake(contentView.frame.size.width, 39.0 * rowsCount + 4 * 39.0);
[self tileViews];
}
- (void)determineCurrentRow
{
CGFloat delta = contentView.contentOffset.y;
int position = round(delta / 39.0);
currentRow = position;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * position) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
- (void)didTap:(id)sender
{
UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer *)sender;
CGPoint point = [tapRecognizer locationInView:self];
int steps = floor(point.y / 39) - 2;
[self makeSteps:steps];
}
- (void)makeSteps:(int)steps
{
if (steps == 0 || steps > 2 || steps < -2)
return;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
int newRow = currentRow + steps;
if (newRow < 0 || newRow >= rowsCount)
{
if (steps == -2)
[self makeSteps:-1];
else if (steps == 2)
[self makeSteps:1];
return;
}
currentRow = currentRow + steps;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
#pragma mark - recycle queue
- (UIView *)dequeueRecycledView
{
UIView *aView = [recycledViews anyObject];
if (aView)
[recycledViews removeObject:aView];
return aView;
}
- (BOOL)isDisplayingViewForIndex:(NSUInteger)index
{
BOOL foundPage = NO;
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39.0 - 2;
if (viewIndex == index)
{
foundPage = YES;
break;
}
}
return foundPage;
}
- (void)tileViews
{
// Calculate which pages are visible
CGRect visibleBounds = contentView.bounds;
int firstNeededViewIndex = floorf(CGRectGetMinY(visibleBounds) / 39.0) - 2;
int lastNeededViewIndex = floorf((CGRectGetMaxY(visibleBounds) / 39.0)) - 2;
firstNeededViewIndex = MAX(firstNeededViewIndex, 0);
lastNeededViewIndex = MIN(lastNeededViewIndex, rowsCount - 1);
// Recycle no-longer-visible pages
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39 - 2;
if (viewIndex < firstNeededViewIndex || viewIndex > lastNeededViewIndex)
{
[recycledViews addObject:aView];
[aView removeFromSuperview];
}
}
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
- (void)configureView:(UIView *)view atIndex:(NSUInteger)index
{
UILabel *label = (UILabel *)view;
label.text = [dataSource pickerView:self titleForRow:index];
CGRect frame = label.frame;
frame.origin.y = 39.0 * index + 78.0;
label.frame = frame;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self tileViews];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
[self determineCurrentRow];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self determineCurrentRow];
}
#end
This should work with ARC. Replace RGBACOLOR with colorWithRed:green:blue:alpha
label.textColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.75f];
The Problem:
After I finish a pan gesture, the cell under the initiating tap no longer responds to selection. didSelectItemAtIndexPath will fire when tapping other cells, but not the cell that was under the pan gesture.
How can I get that cell to respond to touch input again? Alternatively, how can I check if that cell is stuck responding to an event?
Background:
I have a UICollectionView with a bunch of cells. Tapping a cell in this collection view fires didSelectItemAtIndexPath.
The collection view has a pan gesture recognizer. Panning creates an image of the view and translates it around the screen. The collection view is left underneath the other views for the duration of the pan gesture.
Theories:
It's possible that the selection is never completing due to the pan. Maybe there's a touch event hanging around in the UI. If I could clear it, maybe the cell would respond again. I tried setting [panHandler setCancelsTouchesInView:YES], but it didn't change anything.
Update 1:
In the comments, a couple people suggested that the image may be hanging around and blocking the touch. In the completion block passed to animateWithDuration, I have the following lines:
[self.regionScreenshot removeFromSuperview];
self.regionScreenshot = nil;
I verified that these lines are executed.
Another factor that leads me to believe that that is not the issue is that, of all the cells, only ones that have been used to drag are affected. Surrounding cells still respond.
Update 2: Code & Gif
- (IBAction)handlePanFrom:(UIPanGestureRecognizer*)recognizer
{
CGPoint translation = [recognizer translationInView:recognizer.view];
float transparencyLevel = 0.85;
if (recognizer.state == UIGestureRecognizerStateBegan)
{
SFCYRegion* centerRegion = self.region;
//North
if (centerRegion.regionToNorth != nil)
{
self.region = centerRegion.regionToNorth;
[self reloadRegion];
self.regionToNorthScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToNorthScreenshot = [[UIView alloc] init];
self.regionToNorthScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToNorthScreenshot];
self.regionToNorthScreenshot.alpha = transparencyLevel;
self.regionToNorthScreenshot.frame = northFrame;
//East
if (centerRegion.regionToEast != nil)
{
self.region = centerRegion.regionToEast;
[self reloadRegion];
self.regionToEastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToEastScreenshot = [[UIView alloc] init];
self.regionToEastScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToEastScreenshot];
self.regionToEastScreenshot.alpha = transparencyLevel;
self.regionToEastScreenshot.frame = eastFrame;
//South
if (centerRegion.regionToSouth != nil)
{
self.region = centerRegion.regionToSouth;
[self reloadRegion];
self.regionToSouthScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToSouthScreenshot = [[UIView alloc] init];
self.regionToSouthScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToSouthScreenshot];
self.regionToSouthScreenshot.alpha = transparencyLevel;
self.regionToSouthScreenshot.frame = southFrame;
//West
if (centerRegion.regionToWest != nil)
{
self.region = centerRegion.regionToWest;
[self reloadRegion];
self.regionToWestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToWestScreenshot = [[UIView alloc] init];
self.regionToWestScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToWestScreenshot];
self.regionToWestScreenshot.alpha = transparencyLevel;
self.regionToWestScreenshot.frame = westFrame;
//Northeast
if (centerRegion.regionToNorth != nil && centerRegion.regionToNorth.regionToEast != nil)
{
self.region = centerRegion.regionToNorth.regionToEast;
[self reloadRegion];
self.regionToNortheastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToNortheastScreenshot = [[UIView alloc] init];
self.regionToNortheastScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToNortheastScreenshot];
self.regionToNortheastScreenshot.alpha = transparencyLevel;
self.regionToNortheastScreenshot.frame = northeastFrame;
//Southeast
if (centerRegion.regionToSouth != nil && centerRegion.regionToSouth.regionToEast != nil)
{
self.region = centerRegion.regionToSouth.regionToEast;
[self reloadRegion];
self.regionToSoutheastScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToSoutheastScreenshot = [[UIView alloc] init];
self.regionToSoutheastScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToSoutheastScreenshot];
self.regionToSoutheastScreenshot.alpha = transparencyLevel;
self.regionToSoutheastScreenshot.frame = southeastFrame;
//Southwest
if (centerRegion.regionToSouth != nil && centerRegion.regionToSouth.regionToWest != nil)
{
self.region = centerRegion.regionToSouth.regionToWest;
[self reloadRegion];
self.regionToSouthwestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToSouthwestScreenshot = [[UIView alloc] init];
self.regionToSouthwestScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToSouthwestScreenshot];
self.regionToSouthwestScreenshot.alpha = transparencyLevel;
self.regionToSouthwestScreenshot.frame = southwestFrame;
//Northwest
if (centerRegion.regionToNorth != nil && centerRegion.regionToNorth.regionToWest != nil)
{
self.region = centerRegion.regionToNorth.regionToWest;
[self reloadRegion];
self.regionToNorthwestScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
}
else
{
self.regionToNorthwestScreenshot = [[UIView alloc] init];
self.regionToNorthwestScreenshot.backgroundColor = [UIColor darkGrayColor];
}
[self.view.superview addSubview:self.regionToNorthwestScreenshot];
self.regionToNorthwestScreenshot.alpha = transparencyLevel;
self.regionToNorthwestScreenshot.frame = northwestFrame;
//Self
self.region = centerRegion;
[self reloadRegion];
self.regionScreenshot = [self.collectionView snapshotViewAfterScreenUpdates:YES];
self.regionScreenshot.frame = mainFrame;
self.regionScreenshot.center = mainFrameCenter;
[self.view.superview addSubview:self.regionScreenshot];
self.collectionView.alpha = 0;
}
else if (recognizer.state == UIGestureRecognizerStateChanged)
{
//Track the movement:
self.regionScreenshot.center = [self movePoint:mainFrameCenter
byX:translation.x andY:translation.y];
self.regionToNorthScreenshot.center = [self movePoint:northFrameCenter
byX:translation.x andY:translation.y];
self.regionToEastScreenshot.center = [self movePoint:eastFrameCenter
byX:translation.x andY:translation.y];
self.regionToSouthScreenshot.center = [self movePoint:southFrameCenter
byX:translation.x andY:translation.y];
self.regionToWestScreenshot.center = [self movePoint:westFrameCenter byX:translation.x andY:translation.y];
self.regionToNortheastScreenshot.center = [self movePoint:northeastFrameCenter
byX:translation.x andY:translation.y];
self.regionToSoutheastScreenshot.center = [self movePoint:southeastFrameCenter
byX:translation.x andY:translation.y];
self.regionToSouthwestScreenshot.center = [self movePoint:southwestFrameCenter
byX:translation.x andY:translation.y];
self.regionToNorthwestScreenshot.center = [self movePoint:northwestFrameCenter
byX:translation.x andY:translation.y];
//[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
else if (recognizer.state == UIGestureRecognizerStateEnded)
{
SFCYRegion* newRegion;
UIView* viewToMoveToCenter;
CGSize slideVector;
NSInteger movedByX = 0;
NSInteger movedByY = 0;
float thresholdPercentage = 0.4;
BOOL isOverThresholdToNorth = translation.y > (mainFrame.size.height * thresholdPercentage);
BOOL isOverThresholdToSouth = -translation.y > (mainFrame.size.height * thresholdPercentage);
BOOL isOverThresholdToEast = -translation.x > (mainFrame.size.width * thresholdPercentage);
BOOL isOverThresholdToWest = translation.x > (mainFrame.size.width * thresholdPercentage);
if (isOverThresholdToNorth && self.region.regionToNorth != nil)
{
movedByY = -1;
if (isOverThresholdToEast && self.region.regionToNorth.regionToEast != nil)
{
//Northeast
newRegion = self.region.regionToNorth.regionToEast;
viewToMoveToCenter = self.regionToNortheastScreenshot;
movedByX = 1;
}
else if (isOverThresholdToWest && self.region.regionToNorth.regionToWest != nil)
{
//Northwest
newRegion = self.region.regionToNorth.regionToWest;
viewToMoveToCenter = self.regionToNorthwestScreenshot;
movedByX = -1;
}
else
{
//North
newRegion = self.region.regionToNorth;
viewToMoveToCenter = self.regionToNorthScreenshot;
}
}
else if (isOverThresholdToSouth && self.region.regionToSouth != nil)
{
movedByY = 1;
if (isOverThresholdToEast && self.region.regionToSouth.regionToEast != nil)
{
//Southeast
newRegion = self.region.regionToSouth.regionToEast;
viewToMoveToCenter = self.regionToSoutheastScreenshot;
movedByX = 1;
}
else if (isOverThresholdToWest && self.region.regionToSouth.regionToWest != nil)
{
//Southwest
newRegion = self.region.regionToSouth.regionToWest;
viewToMoveToCenter = self.regionToSouthwestScreenshot;
movedByX = -1;
}
else
{
//South
newRegion = self.region.regionToSouth;
viewToMoveToCenter = self.regionToSouthScreenshot;
}
}
else if (isOverThresholdToEast && self.region.regionToEast != nil)
{
//East
newRegion = self.region.regionToEast;
viewToMoveToCenter = self.regionToEastScreenshot;
movedByX = 1;
}
else if (isOverThresholdToWest && self.region.regionToWest != nil)
{
//West
newRegion = self.region.regionToWest;
viewToMoveToCenter = self.regionToWestScreenshot;
movedByX = -1;
}
else
{
//None, so return to start:
newRegion = self.region;
viewToMoveToCenter = self.regionScreenshot;
}
slideVector = CGSizeMake(mainFrameCenter.x - viewToMoveToCenter.center.x,
mainFrameCenter.y - viewToMoveToCenter.center.y);
[UIView animateWithDuration:0.2
animations:^
{
viewToMoveToCenter.alpha = 1;
if (![self.regionScreenshot isEqual:viewToMoveToCenter])
{
self.regionScreenshot.alpha = transparencyLevel;
}
self.regionScreenshot.center = [self movePoint:self.regionScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToNorthScreenshot.center = [self movePoint:self.regionToNorthScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToEastScreenshot.center = [self movePoint:self.regionToEastScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToSouthScreenshot.center = [self movePoint:self.regionToSouthScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToWestScreenshot.center = [self movePoint:self.regionToWestScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToNortheastScreenshot.center = [self movePoint:self.regionToNortheastScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToSoutheastScreenshot.center = [self movePoint:self.regionToSoutheastScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToSouthwestScreenshot.center = [self movePoint:self.regionToSouthwestScreenshot.center
byX:slideVector.width andY:slideVector.height];
self.regionToNorthwestScreenshot.center = [self movePoint:self.regionToNorthwestScreenshot.center
byX:slideVector.width andY:slideVector.height];
}
completion:^(BOOL finished)
{
if (finished)
{
//Remove the old views:
self.collectionView.alpha = 1;
[self.regionScreenshot removeFromSuperview];
[self.regionToNorthScreenshot removeFromSuperview];
[self.regionToEastScreenshot removeFromSuperview];
[self.regionToSouthScreenshot removeFromSuperview];
[self.regionToWestScreenshot removeFromSuperview];
[self.regionToNortheastScreenshot removeFromSuperview];
[self.regionToSoutheastScreenshot removeFromSuperview];
[self.regionToSouthwestScreenshot removeFromSuperview];
[self.regionToNorthwestScreenshot removeFromSuperview];
self.regionScreenshot = nil;
self.regionToNorthScreenshot = nil;
self.regionToEastScreenshot = nil;
self.regionToSouthScreenshot = nil;
self.regionToWestScreenshot = nil;
self.regionToNortheastScreenshot = nil;
self.regionToSoutheastScreenshot = nil;
self.regionToSouthwestScreenshot = nil;
self.regionToNorthwestScreenshot = nil;
}
}];
if (![self.regionScreenshot isEqual:viewToMoveToCenter])
{
self.region = newRegion;
[self reloadRegion];
[self movedRegionByX:movedByX andY:movedByY];
}
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
}
Here is an image demonstrating the issue. I perform a selection on the "Suburb" cell, then pan, and then am no longer able to perform a selection on that cell, but can still select others:
Update 3: All Gestures
This occurs when I do swipe gestures and pinch gestures as well. If I add in two-finger swipe gestures, both cells under the origin points are affected.
Make sure that regionScreenshot and any other view's you add to the view hierarchy have userInteractionEnabled set to NO.
Also set your cell and its content's clipsToBounds set to YES. Sometimes views look OK but actually they are "much smaller than they appear".
When I was panning, I called [self.collectionView reloadData] in the process of generating the screenshots to use for the adjacent regions. Reloading the cells while a gesture was active seemed to interfere with that individual cell's ability to handle gestures.
As a workaround, I instead added a second, hidden UICollectionView to the controller and load the data into that view and take screenshots of it instead of the main view. The main collection view never has to reload the data until the gestures are complete and a new region is selected.
UIView* aScreenshot = [self.secondaryCollectionView snapshotViewAfterScreenUpdates:YES];
I am drawing a bunch of MKPolygons in my MKMapView. Some of them lay on top of each other. How can I bring a selected polygon to the top/front?
I tried bringSubviewToFront: on a MKPolygonView I create from the polygon layer:
MKPolygonView *view = (MKPolygonView *)[self.mapView viewForOverlay:polygon];
view.strokeColor = [UIColor orangeColor];
[self.mapView bringSubviewToFront:view];
SOLUTION:
I removed
MKPolygonView *view = (MKPolygonView *)[self.mapView viewForOverlay:polygon];
view.strokeColor = [UIColor orangeColor];
[self.mapView bringSubviewToFront:view];
and replaced it with what Craig suggested:
[self.mapView insertOverlay:polygon atIndex:self.mapView.overlays.count];
which then calls the MKMapKit delegate mapView:viewForOverlay: and then I handle the color change there:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolygon class]] && !((MKPolygon *)overlay).isSelected) {
MKPolygonView* aView = [[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay];
aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
aView.strokeColor = [UIColor yellowColor];
aView.lineWidth = 3;
return aView;
}
else if ([overlay isKindOfClass:[MKPolygon class]] && ((MKPolygon *)overlay).isSelected) {
MKPolygonView* aView = [[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay];
aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2];
aView.strokeColor = [UIColor orangeColor];
aView.lineWidth = 3;
return aView;
}
}
When you add an overlay to a mapView you can choose where to place it in the list of overlays. Since an overlay can only be in the list once you can move it just by inserting again at the desired location. Since you want it at the top, this should work:
[mapView insertOverlay:overlay atIndex:[mapView.overlays count]];
You should not be calling viewForOverlay. Leave that to iOS. If you need to colour the overlay do it within viewForOverlay because iOS can and will call that when ever it wants and if you return a non-coloured overlay that's what it will draw.
I have a mapView with 2 circles. When I try to customize the large one the small one seems to follow the large one. For example if I customize the fill color for the large one the smaller one gets the same color. How do I make the smaller one a different color? Note: I use reusable identifiers. Thank you.. this is my working code but when i try to edit my smaller circle, the one with radius 100 it doesn't. note: this is my WORKING code as anything else i tried it failed.
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
static NSString *CircleOverlayIdentifier = #"Circle";
_mapView.delegate = self;
if ([overlay isKindOfClass:[CircleOverlay class]]) {
CircleOverlay *circleOverlay = (CircleOverlay *)overlay;
MKCircleView *annotationView =
(MKCircleView *)[mapView dequeueReusableAnnotationViewWithIdentifier:CircleOverlayIdentifier];
if (!annotationView) {
MKCircle *circle = [MKCircle
circleWithCenterCoordinate:circleOverlay.coordinate
radius:circleOverlay.radius];
annotationView = [[MKCircleView alloc] initWithCircle:circle];
//this one
}
if (overlay == self.targetOverlay) {
//adjustable
annotationView.fillColor = [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:0.3f];
annotationView.strokeColor = [UIColor redColor];
annotationView.lineWidth = 1.0f;
} else {
//fixed
annotationView.fillColor = [UIColor colorWithWhite:0.3f alpha:0.3f];
annotationView.strokeColor = [UIColor purpleColor];
annotationView.lineWidth = 2.0f;
}
return annotationView;
}
return nil;
}
- (void)configureOverlay {
if (self.location) {
[self.mapView removeAnnotations:[self.mapView annotations]];
[self.mapView removeOverlays:[self.mapView overlays]];
CircleOverlay *overlaysmall = [[CircleOverlay alloc] initWithCoordinate:self.location.coordinate radius:100];
[self.mapView addOverlay:overlaysmall];
_targetOverlaySmall = overlaysmall;
CircleOverlay *overlay = [[CircleOverlay alloc] initWithCoordinate:self.location.coordinate radius:self.radius];
[self.mapView addOverlay:overlay];
GeoQueryAnnotation *annotation = [[GeoQueryAnnotation alloc] initWithCoordinate:self.location.coordinate radius:self.radius];
[self.mapView addAnnotation:annotation];
[self updateLocations];
}
}
I have a MKMapView with some pins on it. I connect the pins with a MKPolyline view. But the MKPolyline is only shown when I move the map (when the MapView is updated?). I want to see the MKPolyline from the beginning on.
Please inspect the following code:
-(void)plotSnapPosition {
for (id<MKAnnotation> annotation in myMapView.annotations) {
[myMapView removeAnnotation:annotation];
}
for (id<MKOverlay> overlay in myMapView.overlays) {
[myMapView removeOverlay:overlay];
}
NSArray *snaps = self.entry.snapsArray;
CLLocationCoordinate2D *locations = malloc(sizeof(CLLocationCoordinate2D) * snaps.count);
NSInteger counter = 0;
for (Snap *snap in snaps) {
locations[counter] = [snap coordinates];
CLLocationCoordinate2D c = [snap coordinates];
CAHAnnotation *annotation = [[CAHAnnotation alloc] initWithDate:snap.timeAsString coordinate:c counter:counter];
[myMapView addAnnotation:annotation];
counter++;
}
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:locations count:snaps.count];
MKPolylineView *routeLineView = [[MKPolylineView alloc] initWithPolyline:polyline];
routeLineView.fillColor = [UIColor redColor];
routeLineView.strokeColor = [UIColor redColor];
routeLineView.lineWidth = 5;
[myMapView setVisibleMapRect:polyline.boundingMapRect];
[self.myMapView addOverlay:polyline];
}
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolylineView *routeLineView = [[MKPolylineView alloc] initWithPolyline:overlay];
routeLineView.fillColor = [UIColor blueColor];
routeLineView.strokeColor = [UIColor blueColor];
routeLineView.lineWidth = 3;
return routeLineView;
}
return nil;
}
For testing issues I have set the color of the MKPolyline in the method -(void)plotSnapPosition to red. In the delegate I set it to blue. Only the blue one is shown, after moving the map around.
can someone help me out of this? I think it is only a small mistake. Thank you.
here are the screenshots:
the two pins
after moving the map:
the path after moving the map
Make sure you set the mapView's delegate before adding the overlay. So, in your case
mapView.delegate = self;
[self plotSnapPosition];
Have you tried adding a [overlayView setNeedsDisplay] call when you finish drawing?