美文网首页
iOS 截取长图及分享、拼接图片、优化内存问题

iOS 截取长图及分享、拼接图片、优化内存问题

作者: L一N | 来源:发表于2018-06-01 13:50 被阅读3250次

    我们先来看看分享的长图效果及高度:


    屏幕快照 2018-06-01 上午11.07.47.png

    本文是以tableView、collectionView等scrollView的截取长图,webView的原理大致一样。

    大体流程:
    1、保存scrollView截取前的偏移量及Frame;
    2、计算出你要截取的长图的高度及宽度,即scrollView的contentSize,将scrollView.frame设成scrollView.contentSize;
    3、渲染出scrollView整体(上下文),截取当前scrollView生成Image;
    4、恢复scrollView的偏移量及Frame;
    5、可选步骤:将得到的长Image与其他image拼接;
    6、设置友盟分享消息内容、分享;
    7、渲染的内存问题的优化。
    
    
    Talk is cheap. Show my code:

    1、保存scrollView截取前的偏移量及Frame:

        //保存scrollView当前的偏移量
        CGPoint savedContentOffset = scrollView.contentOffset;
        CGRect saveFrame = scrollView.frame;
    

    2、将scrollView.frame设成scrollView.contentSize:

    //将scrollView的偏移量设置为(0,0)
        scrollView.contentOffset = CGPointZero;
    //scrollView.frame设成scrollView.contentSize
        scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
    

    3、渲染出scrollView整体(上下文),截取当前scrollView生成Image:

    //渲染出scrollView整体(上下文)
        [scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
    //    scrollView.layer.contents = nil;
        //截取当前上下文生成Image
        UIImage*image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    

    4、恢复scrollView的偏移量及Frame:

        scrollView.contentOffset = savedContentOffset;
        scrollView.frame = saveFrame;
    

    5、【图片拼接】
    //此处以截取的长图拼接头尾视图为例:

    /* Image 拼接
     * masterImage  主图片
     * headImage   头图片
     * footImage   尾图片
     */
    + (UIImage *)addHeadImage:(UIImage *)headImage footImage:(UIImage *)footImage toMasterImage:(UIImage *)masterImage {
        
        CGSize size;
        size.width = masterImage.size.width;
        
        CGFloat headHeight = !headImage? 0:headImage.size.height/2.0;
        CGFloat footHeight = !footImage? 0:footImage.size.height/2.0;
        
        size.height = masterImage.size.height + headHeight + footHeight;
        
        UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
        
        if (headImage)
            [headImage drawInRect:CGRectMake(0, 0, masterImage.size.width, headHeight)];
        
            
        [masterImage drawInRect:CGRectMake(0, headHeight, masterImage.size.width, masterImage.size.height)];
        
        if (footImage)
            [footImage drawInRect:CGRectMake(0, masterImage.size.height + headHeight, masterImage.size.width, footHeight)];
        
        UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
        
        UIGraphicsEndImageContext();
        return resultImage;
        
    }
    

    6、友盟分享代码:

    //1、设置分享内容:
    UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
        //设置文本
        messageObject.text = @" ";
        
        //创建图片内容对象
        UMShareImageObject *shareObject = [[UMShareImageObject alloc] init];
        //如果有缩略图,则设置缩略图
        shareObject.thumbImage = image;
        [shareObject setShareImage:image];
        //分享消息对象设置分享内容对象
        messageObject.shareObject = shareObject;
        int platType = 0;  //0,微博
        //其他分享途径:
        //UMSocialPlatformType_WechatSession      = 1, //微信聊天
        //UMSocialPlatformType_WechatTimeLine     = 2,//微信朋友圈
        //UMSocialPlatformType_QQ                 = 4,//QQ聊天页面
        //UMSocialPlatformType_Qzone              = 5,//qq空间
    
    //2、发起分享:
    [[UMSocialManager defaultManager] shareToPlatform:platType messageObject:messageObject currentViewController:self.vc completion:^(id data, NSError *error) {
            if (error) {
                NSLog(@"************Share fail with error %@*********",error);
                if (error.code == 2008){
                    kShowMessage(@"未安装该应用");
                }else if(error.code == 2009){
                    kShowMessage(@"取消分享");
                }else
                     kShowMessage(@"分享失败");
                [self removeSelf];
                
            }else
            {
                NSLog(@"response data is %@",data);
                kShowMessage(@"分享成功");
                [self removeSelf];
            }
        }];
    
    内存的优化问题:

    在渲染长度较长的scrollView [6Plus:长度>大约20000像素] 时
    使用[scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];方法把view绘到画布上,功能实现后检测内存使用情况,发现这个方法会导致内存使用直线上升,然后崩溃闪退。

    一、baidu的解决办法基本大致一样:
    //实测感觉作用不大,但还是贴上供参考
    1、将renderInContext 替换用:drawViewHierarchyInRect: afterScreenUpdates;
    2、使用AutoReleasePool.

    二、研究了一下:
    在[view.layer renderInContext:context]之后加上一句:view.layer.contents = nil; 渲染的内存会及时释放,截取长度不过长的的图片时观察内存下降效果尤为明显。据stackoverflow里说这样是用来清除 layer绘制过后产生的缓存。

    但是 ,即便如此,在较老旧的设备中:6s之前,依然会因为运行内存不足以支撑较大尺寸的View渲染而导致应用crash掉。

    有一个大体的思路,抛转引玉一下,
    循环体里把要截图的scrollView分成多个等份,然后渲染出每一个等份,再将view.layer.contents = nil;释放等份后的内存,最后将所有等份拼接得到主Image。
    希望有更好的方法的朋友可以留言分享出来。

    相关文章

      网友评论

          本文标题:iOS 截取长图及分享、拼接图片、优化内存问题

          本文链接:https://www.haomeiwen.com/subject/ltmhsftx.html