iOS/macOS snapshotter#9891
Conversation
625715b to
3a9c31b
Compare
4cfb29f to
28a84a7
Compare
| @param mapCamera the camera settings | ||
| @param size the image size | ||
| */ | ||
| - (instancetype )initWithStyleURL:(NSURL* )styleURL mapCamera:(MGLMapCamera*) mapCamera size:(CGSize) size; |
There was a problem hiding this comment.
Nit: Inconsistent formatting. (only spaces before *)
Drop map from mapCamera. (×3)
| @property (nonatomic) MGLMapCamera* mapCamera; | ||
|
|
||
| /** | ||
| (Optionally) a region to capture. Overrides the center coordinate |
There was a problem hiding this comment.
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*` |
There was a problem hiding this comment.
Nit: s/MGLImage*/MGLImage/NSError*/NSError (I don't think jazzy will link otherwise)
| - (void)cancel; | ||
|
|
||
| /** | ||
| Indicates wether as snapshot is currently being generated. |
| [self startWithQueue:dispatch_get_main_queue() completionHandler:completion]; | ||
| } | ||
|
|
||
| - (void)startWithQueue:(dispatch_queue_t)queue completionHandler: (MGLMapSnapshotCompletionHandler)completion; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Nit: loading is already synthesized. This can be dropped. Use _loading to bypass readonly when you set the variable.
| mbglMapSnapshotter.reset(); | ||
| } | ||
|
|
||
| -(BOOL)isLoading; |
There was a problem hiding this comment.
Nit: already synthesized. Drop this method.
6a6957e to
f4ee3fb
Compare
|
@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? |
61159dd to
4ad3a56
Compare
b6a46f4 to
3337f0c
Compare
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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)]; |
There was a problem hiding this comment.
MGLStyle has factory methods for style URLs. We use them whenever possible.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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]; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
An alternative to looking at file extensions:
- 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.)
- Use
UTTypeConformsTo()to determine whether the UTI at that path conforms topublic.jpegetc. - Avoid hard-coding UTIs like
public.jpegby iterating over+[NSImage imageTypes].
| @param camera the camera settings | ||
| @param size the image size | ||
| */ | ||
| - (instancetype)initWithStyleURL:(NSURL*)styleURL camera:(MGLMapCamera*)camera size:(CGSize)size; |
There was a problem hiding this comment.
Do we want to allow the style URL to be nil and default to Mapbox Streets, as MGLMapView and MGLOfflineStorage do?
There was a problem hiding this comment.
@1ec5 could you please help me understand why defaulting to Mapbox streets is a good option.
There was a problem hiding this comment.
When you create an MGLMapView or MGLOfflineRegion with a nil style URL, we default to the current version of Mapbox Streets:
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 |
There was a problem hiding this comment.
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"}; |
There was a problem hiding this comment.
This string should be localizable, since it can be presented to the user.
For iOS: #9919 |
|
Filed #9920 so we can better track the fit-and-finish detailed in #9891 (review). |
| <action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/> | ||
| </connections> | ||
| </menuItem> | ||
| <menuItem title="Save snapshot" id="vjX-0E-kLO"> |
There was a problem hiding this comment.
Use title case on menu items.
iOS/macOS companion for #9748
TODO: