Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

iOS/macOS snapshotter #9891

Merged
merged 4 commits into from
Sep 5, 2017
Merged

iOS/macOS snapshotter #9891

merged 4 commits into from
Sep 5, 2017

Conversation

ivovandongen
Copy link
Contributor

@ivovandongen ivovandongen commented Aug 30, 2017

iOS/macOS companion for #9748

TODO:

  • Work out options class
  • Extend test view
  • Documentation

@ivovandongen ivovandongen added the iOS Mapbox Maps SDK for iOS label Aug 30, 2017
@ivovandongen ivovandongen self-assigned this Aug 30, 2017
@ivovandongen ivovandongen requested a review from frederoni August 31, 2017 15:55
@ivovandongen ivovandongen force-pushed the ivd-ios-snapshotter branch 3 times, most recently from 4cfb29f to 28a84a7 Compare September 1, 2017 14:32
@param mapCamera the camera settings
@param size the image size
*/
- (instancetype )initWithStyleURL:(NSURL* )styleURL mapCamera:(MGLMapCamera*) mapCamera size:(CGSize) size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Inconsistent formatting. (only spaces before *)
Drop map from mapCamera. (×3)

@property (nonatomic) MGLMapCamera* mapCamera;

/**
(Optionally) a region to capture. Overrides the center coordinate
Copy link
Contributor

@frederoni frederoni Sep 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop optional since region is invalid empty by default and Obj-C doesn't support optional structs.

/**
A block to processes the result or error of a snapshot request.

The result will be either an `MGLImage*` or a `NSError*`
Copy link
Contributor

@frederoni frederoni Sep 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: s/MGLImage*/MGLImage/NSError*/NSError (I don't think jazzy will link otherwise)

- (void)cancel;

/**
Indicates wether as snapshot is currently being generated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: s/wether/whether

[self startWithQueue:dispatch_get_main_queue() completionHandler:completion];
}

- (void)startWithQueue:(dispatch_queue_t)queue completionHandler: (MGLMapSnapshotCompletionHandler)completion;
Copy link
Contributor

@frederoni frederoni Sep 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slightly confusing. startWithQueue implies that we generate the snapshot on the given queue but here we're calling the completion on the given queue. This is usually called handlerQueue or delegateQueue.
I think we should dispatch to the given queue before handing off to core so we can decide if we want to snapshot in parallel or serial.

std::unique_ptr<mbgl::MapSnapshotter> mbglMapSnapshotter;
std::unique_ptr<mbgl::Actor<mbgl::MapSnapshotter::Callback>> snapshotCallback;

BOOL loading;
Copy link
Contributor

@frederoni frederoni Sep 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: loading is already synthesized. This can be dropped. Use _loading to bypass readonly when you set the variable.

mbglMapSnapshotter.reset();
}

-(BOOL)isLoading;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: already synthesized. Drop this method.

@ivovandongen ivovandongen force-pushed the ivd-ios-snapshotter branch 2 times, most recently from 6a6957e to f4ee3fb Compare September 5, 2017 07:54
@ivovandongen
Copy link
Contributor Author

ivovandongen commented Sep 5, 2017

@frederoni Thanks for the review! I've fixed up the comments and made sure the work is now all done on the provided queue (or the main queue).

I also added some code to add the logo on the image in a work queue (https://github.com/mapbox/mapbox-gl-native/pull/9891/files#diff-56bc5c1e41273957efd873aa83e6c522R116). Could you check if that is the right queue to do this on?

@ivovandongen ivovandongen force-pushed the ivd-ios-snapshotter branch 2 times, most recently from 61159dd to 4ad3a56 Compare September 5, 2017 09:31
@ivovandongen ivovandongen added the macOS Mapbox Maps SDK for macOS label Sep 5, 2017
@ivovandongen ivovandongen changed the title iOS snapshotter iOS/macOS snapshotter Sep 5, 2017
@ivovandongen ivovandongen merged commit d736429 into master Sep 5, 2017
@ivovandongen ivovandongen deleted the ivd-ios-snapshotter branch September 5, 2017 13:29
@friedbunny friedbunny added this to the ios-v3.7.0 milestone Sep 5, 2017
Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for implementing this feature so swiftly! It’s certainly going to be well received. I left some comments below that the team will need to address as tail work, ideally before the first v3.7.0 beta.

In addition to the comments below, we’ll probably want to add MGLMapSnapshotter and MGLMapSnapshotOptions to the jazzy table of contents in jazzy.yml and update the changelog to mention the new feature, both for iOS and macOS.

*/
- (instancetype)initWithStyleURL:(NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize)size;

#pragma mark - Configuring the map
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For our public headers, we use Title Case in marks, since jazzy uses the marks to produce section headings in the generated documentation. We could move to sentence case for that, but it would be nice to do it consistently across all the headers when we make that decision.

/**
The style URL for these options.
*/
@property (nonatomic, readonly) NSURL* styleURL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, the predominant style in our Objective-C code is to place the space before the asterisk. I realize this is different than the predominant style for our C++ code.

/**
The zoom. Default is 0.
*/
@property (nonatomic) double zoom;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The iOS/macOS APIs consistently use the term “zoom level” rather than “zoom” for this concept. The main reason is that “zoom” is also a verb; in Objective-C, [mapView zoom] looks like a call to an action method rather than a reference to a property getter.

A region to capture. Overrides the center coordinate
in the mapCamera options if set
*/
@property (nonatomic) MGLCoordinateBounds region;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the API uses the term “coordinate bounds” instead of “region”, although there is some holdover from MapKit in the delegate methods. It’s a confusing situation overall, but I think it would be slightly less confusing to use coordinateBounds here, to align with MGLMapView.visibleCoordinateBounds.

#pragma mark - Configuring the image

/**
The size of the output image. Minimum is 64x64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this size measured in points or pixels?

MGLMapCamera* mapCamera = [[MGLMapCamera alloc] init];
mapCamera.pitch = 20;
mapCamera.centerCoordinate = coordinates;
MGLMapSnapshotOptions* options = [[MGLMapSnapshotOptions alloc] initWithStyleURL:[NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"] camera:mapCamera size:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MGLStyle has factory methods for style URLs. We use them whenever possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the traffic style is deprecated, even tho it has not yet merged into master. Our recommendation is create an URL with this string mapbox://styles/mapbox/traffic-day-v2.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the demo doesn’t depend on the traffic congestion information displayed by the Traffic Day style, so I’d recommend choosing a non-deprecated method like +[MGLStyle satelliteStreets].


}

NSString *extension = [[fileURL pathExtension] lowercaseString];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File name extensions aren’t especially reliable on Apple platforms, since a file’s canonical type is represented by a UTI. The save panel even lets you save without an extension unless you restrict the allowed file types to those that can be represented as images:

panel.allowedFileTypes = [NSImage imageTypes];

Here’s a more robust way to go from a file extension to a UTI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative to looking at file extensions:

  1. The save panel tells us the file path. use NSFileManager to determine the UTI at that path. (Not sure if this only works for existing files or if it would work for unsaved files as well.)
  2. Use UTTypeConformsTo() to determine whether the UTI at that path conforms to public.jpeg etc.
  3. Avoid hard-coding UTIs like public.jpeg by iterating over +[NSImage imageTypes].

@param camera the camera settings
@param size the image size
*/
- (instancetype)initWithStyleURL:(NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize)size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to allow the style URL to be nil and default to Mapbox Streets, as MGLMapView and MGLOfflineStorage do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1ec5 could you please help me understand why defaulting to Mapbox streets is a good option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you create an MGLMapView or MGLOfflineRegion with a nil style URL, we default to the current version of Mapbox Streets:

styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];

styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];

For consistency with these APIs, I think we should treat a nil style URL here the same way.


/**
Creates a set of options with the minimum required information
@param styleURL the style url to use
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Start with a capital letter and end with a period. This makes things more consistent in the event that we have to cram more than one sentence in a parameter description, which isn’t uncommon.

- (void)startWithQueue:(dispatch_queue_t)queue completionHandler:(MGLMapSnapshotCompletionHandler)completion;
{
if ([self isLoading]) {
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Already started this snapshotter"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string should be localizable, since it can be presented to the user.

@boundsj
Copy link
Contributor

boundsj commented Sep 5, 2017

update the changelog to mention the new feature

For iOS: #9919

@1ec5 1ec5 mentioned this pull request Sep 5, 2017
@1ec5
Copy link
Contributor

1ec5 commented Sep 5, 2017

Filed #9920 so we can better track the fit-and-finish detailed in #9891 (review).

@@ -128,6 +128,12 @@
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem title="Save snapshot" id="vjX-0E-kLO">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use title case on menu items.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants