iOS -网页生成长图并分享

1,523 阅读2分钟

项目中需要将网页生成长图并保存到本地或者分享的功能

废话不多说,这里上相关逻辑的代码:

由于网页并不一定只是一屏幕的高度,一般都是超出屏幕高度,这里就需要去判断增加高度.

// 生成长图
- (UIImage *)snapshotViewFromRect:(CGRect)rect withCapInsets:(UIEdgeInsets)capInsets {
    
    CGFloat scale = [UIScreen mainScreen].scale;
    
    CGSize boundsSize = self.web.bounds.size;
    CGFloat boundsWidth = boundsSize.width;
    CGFloat boundsHeight = boundsSize.height;
    
    CGSize contentSize = self.web.scrollView.contentSize;
    CGFloat contentHeight = contentSize.height;
    CGFloat contentWidth = contentSize.width;
    
    CGPoint offset = self.web.scrollView.contentOffset;

    [self.web.scrollView setContentOffset:CGPointMake(0, 0)];
    
    NSMutableArray *images = [NSMutableArray array];
    while (contentHeight > 0) {
        UIGraphicsBeginImageContextWithOptions(boundsSize, NO, [UIScreen mainScreen].scale);
        // 在当前上下文中渲染出webView
        // 如果取webView.scrollView.layer则会超出一屏的数据不能显示,只能显示白色区域块
        [self.web.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [images addObject:image];
        
        CGFloat offsetY = self.web.scrollView.contentOffset.y;
        // 设置webView的偏移量
        [self.web.scrollView setContentOffset:CGPointMake(0, offsetY + boundsHeight)];
        contentHeight -= boundsHeight;
    }
    
    
    [self.web.scrollView setContentOffset:offset];
    
    CGSize imageSize = CGSizeMake(contentSize.width * scale,
                                  contentSize.height * scale);
    UIGraphicsBeginImageContext(imageSize);
    [images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger idx, BOOL *stop) {
        [image drawInRect:CGRectMake(0,
                                     scale * boundsHeight * idx,
                                     scale * boundsWidth,
                                     scale * boundsHeight)];
    }];
    // 截取当前上下文生成Image
    UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *snapshotView = [[UIImageView alloc]initWithFrame:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)];
    
    snapshotView.image = [fullImage resizableImageWithCapInsets:capInsets];
    
    return snapshotView.image;
}

生成长图之后分享图片: 这里是采用的友盟分享,分享图片并不是非得下载存储图片,

@property (nonatomic,strong) UIImage *shareImage; // 生成长图
// 图片分享
- (void)shareImageToPlatformType:(UMSocialPlatformType)platformType {
    //创建分享消息对象
    UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
    
    //创建图片内容对象
    UMShareImageObject *shareObject = [[UMShareImageObject alloc] init];
    //如果有缩略图,则设置缩略图
//    shareObject.thumbImage = [UIImage imageNamed:@"AppIcon"];
    // 设置分享上图中的图片
    [shareObject setShareImage:self.shareImage];
    
    //分享消息对象设置分享内容对象
    messageObject.shareObject = shareObject;
    
    //调用分享接口
    [[UMSocialManager defaultManager] shareToPlatform:platformType messageObject:messageObject currentViewController:self completion:^(id data, NSError *error) {
        if (error) {
            ZLLog(@"************Share fail with error %@*********",error);
        }else{
            ZLLog(@"response data is %@",data);
        }
    }];
}

生成长图之后也有需求是需要保存在本地:

- (void)screenshotPic {
    
    CGRect snapshotFrame = CGRectMake(0, 0, _web.scrollView.contentSize.width, _web.scrollView.contentSize.height);
    UIEdgeInsets snapshotEdgeInsets = UIEdgeInsetsZero;
    UIImage *shareImage = [self snapshotViewFromRect:snapshotFrame withCapInsets:snapshotEdgeInsets];
    self.shareImage = shareImage;
    
    // 存储到相册
    UIImageWriteToSavedPhotosAlbum(shareImage, self, nil, NULL);
    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 延时0.7s
        [MBProgressHUD showSuccess:@"已保存至相册"];
//    });
    
}

这里一点击保存相册就发现闪退了。发现 Xcode 报以下错误:

This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

问题跟 iOS 10 保存图片、调用相机一样, Info.plist 里面要涉及隐私数据时要添加提示语。 打开 Info.plist,点击 + 号,在 Key 中输入:Privacy - Photo Library Additions Usage Description,Type 选择 String,Value 中输入你的提示语。

这是 iOS 11 新出的一条隐私规则,说明如下: iOS11下,苹果对相册的权限key做了调整,原来NSPhotoLibraryUsageDescription,在iOS11之后,改成了NSPhotoLibraryAddUsageDescription

iOS 11 新增的隐私设置 iOS 11 中新加的还有一个跟 NFC 设备有关 NFCReaderUsageDescription,不过暂时没接触到。