Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AsyncDisplayKit/ASMapNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@interface ASMapNode : ASImageNode

/**
The current region of ASMapNode. This can be set at any time and ASMapNode will animate the change.
The current region of ASMapNode. This can be set at any time and ASMapNode will animate the change. This property may be set from a background thread before the node is loaded, and will automatically be applied to define the region of the static snapshot (if .liveMap = NO) or the internal MKMapView (otherwise).
*/
@property (nonatomic, assign) MKCoordinateRegion region;

Expand All @@ -22,7 +22,7 @@
@property (nonatomic, readonly) MKMapView *mapView;

/**
Set this to YES to turn the snapshot into an interactive MKMapView and vice versa. Defaults to NO.
Set this to YES to turn the snapshot into an interactive MKMapView and vice versa. Defaults to NO. This property may be set on a background thread before the node is loaded, and will automatically be actioned, once the node is loaded.
*/
@property (nonatomic, assign, getter=isLiveMap) BOOL liveMap;

Expand Down
119 changes: 64 additions & 55 deletions AsyncDisplayKit/ASMapNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ @implementation ASMapNode
@synthesize needsMapReloadOnBoundsChange = _needsMapReloadOnBoundsChange;
@synthesize mapDelegate = _mapDelegate;
@synthesize region = _region;
@synthesize liveMap = _liveMap;

#pragma mark - Lifecycle
- (instancetype)init
Expand All @@ -37,9 +38,11 @@ - (instancetype)init
self.clipsToBounds = YES;

_needsMapReloadOnBoundsChange = YES;

_liveMap = NO;
_centerCoordinateOfMap = kCLLocationCoordinate2DInvalid;
_region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(43.432858, 13.183671), MKCoordinateSpanMake(0.2, 0.2));

//Default world-scale view
_region = MKCoordinateRegionForMapRect(MKMapRectWorld);

_options = [[MKMapSnapshotOptions alloc] init];
_options.region = _region;
Expand All @@ -50,26 +53,31 @@ - (instancetype)init
- (void)didLoad
{
[super didLoad];
if ([self wasLiveMapPreviously]) {
if (self.isLiveMap) {
self.userInteractionEnabled = YES;
[self addLiveMap];
}
}

- (void)setLayerBacked:(BOOL)layerBacked
{
ASDisplayNodeAssert(!self.isLiveMap, @"ASMapNode can not be layer backed whilst .liveMap = YES, set .liveMap = NO to use layer backing.");
[super setLayerBacked:layerBacked];
}

- (void)fetchData
{
[super fetchData];
if ([self wasLiveMapPreviously]) {
if (self.isLiveMap) {
[self addLiveMap];
} else {
[self setUpSnapshotter];
[self takeSnapshot];
}
}

- (void)clearFetchedData
- (void)clearContents
{
[super clearFetchedData];
[super clearContents];
if (self.isLiveMap) {
[self removeLiveMap];
}
Expand All @@ -79,17 +87,21 @@ - (void)clearFetchedData

- (BOOL)isLiveMap
{
return (_mapView != nil);
ASDN::MutexLocker l(_propertyLock);
return _liveMap;
}

- (void)setLiveMap:(BOOL)liveMap
{
liveMap ? [self addLiveMap] : [self removeLiveMap];
}

- (BOOL)wasLiveMapPreviously
{
return CLLocationCoordinate2DIsValid(_centerCoordinateOfMap);
ASDisplayNodeAssert(!self.isLayerBacked, @"ASMapNode can not use the interactive map feature whilst .isLayerBacked = YES, set .layerBacked = NO to use the interactive map feature.");
ASDN::MutexLocker l(_propertyLock);
if (liveMap == _liveMap) {
return;
}
_liveMap = liveMap;
if (self.nodeLoaded) {
liveMap ? [self addLiveMap] : [self removeLiveMap];
}
}

- (BOOL)needsMapReloadOnBoundsChange
Expand Down Expand Up @@ -127,63 +139,62 @@ - (void)setRegion:(MKCoordinateRegion)region

- (void)takeSnapshot
{
if (!_snapshotter.isLoading) {
[_snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
if (!error) {
UIImage *image = snapshot.image;
CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height);

UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
[image drawAtPoint:CGPointMake(0, 0)];

if (_annotations.count > 0 ) {
// Get a standard annotation view pin. Future implementations should use a custom annotation image property.
MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""];
UIImage *pinImage = pin.image;
for (id<MKAnnotation>annotation in _annotations)
if (!_snapshotter) {
[self setUpSnapshotter];
}
[_snapshotter cancel];
[_snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
if (!error) {
UIImage *image = snapshot.image;
CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height);

UIGraphicsBeginImageContextWithOptions(image.size, YES, image.scale);
[image drawAtPoint:CGPointMake(0, 0)];

if (_annotations.count > 0 ) {
// Get a standard annotation view pin. Future implementations should use a custom annotation image property.
MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""];
UIImage *pinImage = pin.image;
for (id<MKAnnotation>annotation in _annotations)
{
CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
if (CGRectContainsPoint(finalImageRect, point))
{
CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
if (CGRectContainsPoint(finalImageRect, point))
{
CGPoint pinCenterOffset = pin.centerOffset;
point.x -= pin.bounds.size.width / 2.0;
point.y -= pin.bounds.size.height / 2.0;
point.x += pinCenterOffset.x;
point.y += pinCenterOffset.y;
[pinImage drawAtPoint:point];
}
CGPoint pinCenterOffset = pin.centerOffset;
point.x -= pin.bounds.size.width / 2.0;
point.y -= pin.bounds.size.height / 2.0;
point.x += pinCenterOffset.x;
point.y += pinCenterOffset.y;
[pinImage drawAtPoint:point];
}
}

UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.image = finalImage;
}
}];
}

UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.image = finalImage;
}
}];
}

- (void)setUpSnapshotter
{
if (!_snapshotter) {
ASDisplayNodeAssert(!CGSizeEqualToSize(CGSizeZero, self.calculatedSize), @"self.calculatedSize can not be zero. Make sure that you are setting a preferredFrameSize or wrapping ASMapNode in a ASRatioLayoutSpec or similar.");
_options.size = self.calculatedSize;
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}
ASDisplayNodeAssert(!CGSizeEqualToSize(CGSizeZero, self.calculatedSize), @"self.calculatedSize can not be zero. Make sure that you are setting a preferredFrameSize or wrapping ASMapNode in a ASRatioLayoutSpec or similar.");
_options.size = self.calculatedSize;
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}

- (void)resetSnapshotter
{
if (!_snapshotter.isLoading) {
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}
[_snapshotter cancel];
_snapshotter = [[MKMapSnapshotter alloc] initWithOptions:_options];
}

#pragma mark - Actions
- (void)addLiveMap
{
ASDisplayNodeAssertMainThread();
if (!self.isLiveMap) {
if (!_mapView) {
__weak ASMapNode *weakSelf = self;
_mapView = [[MKMapView alloc] initWithFrame:CGRectZero];
_mapView.delegate = weakSelf.mapDelegate;
Expand All @@ -194,8 +205,6 @@ - (void)addLiveMap

if (CLLocationCoordinate2DIsValid(_centerCoordinateOfMap)) {
[_mapView setCenterCoordinate:_centerCoordinateOfMap];
} else {
_centerCoordinateOfMap = _options.region.center;
}
}
}
Expand Down