ios - 将 MKMapSnapshotter 作为 NSData 保存在内存中 - Swift

标签 ios objective-c swift mkmapview mkmapsnapshotter

我正在尝试截取我的 MKMapView 的屏幕截图。我通常使用 Objective C 中的以下代码实现此目的。

我想知道如何将 NSData 对象保存在内存中,而不是保存图像,然后立即从中读取。

我也想知道这如何用 Swift 编写 - 特别是 completion handler 部分。我看过文档 - 但不确定语法:https://developer.apple.com/library/prerelease/iOS/documentation/MapKit/Reference/MKMapSnapshotter_class/index.html#//apple_ref/c/tdef/MKMapSnapshotCompletionHandler

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];
}];

最佳答案

就将其“保存”在内存中而言,您可以通过 Objective-C 完成 block (或 Swift 闭包)返回 NSData。从那里,您可以将 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,我可能会更改这些 block /闭包参数以使用 UIImage 而不是 NSData ,但希望这能说明这个想法。

关于ios - 将 MKMapSnapshotter 作为 NSData 保存在内存中 - Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25471657/

相关文章:

iphone - 在 MKAnnotationView 中更新图像

ios - 向玩家添加观察者时出错

objective-c - 正在跳过详细 View Controller 中的第一个方法

ios - 如何在 View 横向移动的情况下创建横向滑动?使用 Swift 使用 Xcode

ios - 可点击的标签或可写的按钮

ios - react-native iOS 原生模块 : calling method that activates network indicator asynchronously

swift - 如何分享图片和链接?

string - Swift 如何使字符串右对齐

iOS startUpdatingLocation 从未调用过

iphone - 特定月份和年份的 NSFetchRequest