Хранить MKMapSnapshotter как NSData в памяти - Swift
Я пытаюсь сделать скриншот моего MKMapView. Я обычно достигал этого, используя приведенный ниже код в Objective C.
Мне интересно, как бы я сохранил объект NSData в памяти, вместо того, чтобы сохранить изображение, а затем сразу прочитать его.
Мне также интересно, как это можно написать в Swift - в частности, часть обработчика завершения. Я посмотрел на документы - но не уверен в синтаксисе: https://developer.apple.com/library/prerelease/iOS/documentation/MapKit/Reference/MKMapSnapshotter_class/index.html
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
options.region = self.mapView.region;
options.size = self.mapView.frame.size;
options.scale = [[UIScreen mainScreen] scale];
NSURL *fileURL = [NSURL fileURLWithPath:@"path/to/snapshot.png"];
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
if (error) {
NSLog(@"[Error] %@", error);
return;
}
UIImage *image = snapshot.image;
NSData *data = UIImagePNGRepresentation(image);
[data writeToURL:fileURL atomically:YES];
}];
1 ответ
С точки зрения "хранения" в памяти, вы можете вернуть NSData
через блок завершения Objective C (или закрытие Swift). Оттуда вы можете передать NSData
в другой метод или сохранить его в свойстве класса.
Например, в Objective-C:
/** Request NSData of PNG representation of map snapshot.
*
* @param mapView The MKMapView for which we're capturing the snapshot
* @param completion The completion block that will be called when the asynchronous snapshot is done. This takes two parameters, the resulting NSData upon success and an NSError if there was an error.
*/
- (void)requestSnapshotDataForMapView:(MKMapView *)mapView completion:(void (^)(NSData *data, NSError *error))completion
{
MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
options.region = mapView.region;
options.size = mapView.frame.size;
options.scale = [[UIScreen mainScreen] scale];
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
if (error) {
if (completion) {
completion(nil, error);
}
return;
}
UIImage *image = snapshot.image;
NSData *data = UIImagePNGRepresentation(image);
if (completion) {
completion(data, nil);
}
}];
}
- (IBAction)didTouchUpInsideButton:(id)sender
{
[self requestSnapshotDataForMapView:self.mapView completion:^(NSData *data, NSError *error) {
if (error) {
NSLog(@"requestSnapshotDataForMapView error: %@", error);
return;
}
// do whatever you want with the `data` parameter here, for example,
// if you had some `@property (nonatomic, strong) NSData *snapshotData;`,
// you might do:
//
// self.snapshotData = data
// now initiate the next step of the process in which you're presumably
// going to use the `data` provided by this block.
}];
}
Эквивалент Swift:
/// Request NSData of PNG representation of map snapshot.
///
/// - parameter mapView: The MKMapView for which we're capturing the snapshot
/// - parameter completion: The closure that will be called when the asynchronous snapshot is done. This takes two parameters, the resulting NSData upon success and an NSError if there was an error.
func requestSnapshotData(mapView: MKMapView, completion: (NSData?, NSError?) -> ()) {
let options = MKMapSnapshotOptions()
options.region = mapView.region
options.size = mapView.frame.size
options.scale = UIScreen.mainScreen().scale
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.startWithCompletionHandler() { snapshot, error in
guard snapshot != nil else {
completion(nil, error)
return
}
let image = snapshot!.image
let data = UIImagePNGRepresentation(image)
completion(data, nil)
}
}
@IBAction func didTouchUpInsideButton(sender: AnyObject) {
requestSnapshotData(mapView) { data, error in
guard data != nil else {
print("requestSnapshotData error: \(error)")
return
}
// do whatever you want with the `data` parameter here, for example,
// if you had some `var snapshotData: NSData?` class property, you might do:
//
// self.snapshotData = data
// now initiate the next step of the process in which you're presumably
// going to use the `data` provided by this closure.
}
}
Честно говоря, если вы пытаетесь использовать UIImage
где-то еще, я мог бы изменить эти параметры блока / закрытия, чтобы использовать UIImage
а не NSData
, но, надеюсь, это иллюстрирует идею.