Ios 如何在不丢失模糊效果的情况下将UIImageView转换为UIImage

Ios 如何在不丢失模糊效果的情况下将UIImageView转换为UIImage,ios,swift,uiimageview,uiimage,Ios,Swift,Uiimageview,Uiimage,我正在使用Swift 4.0制作一个应用程序。它是一种社交媒体应用程序。我的应用程序有一个collectionView,用户可以使用多个collectionViewCells进行订阅。但问题是,对于我拥有的每一个细胞,我都会模糊图像的一部分,有时甚至是全部。这会导致设备在几次滚动到几乎无法使用时出现严重延迟 为了解决这个问题,我认为这会更有意义,而不是模糊细胞图像,当用户上传到sql数据库时,我会模糊它,当它出现在其他用户的feed/timeline中时,他们的iPhone将不必模糊图像,因为他

我正在使用Swift 4.0制作一个应用程序。它是一种社交媒体应用程序。我的应用程序有一个collectionView,用户可以使用多个collectionViewCells进行订阅。但问题是,对于我拥有的每一个细胞,我都会模糊图像的一部分,有时甚至是全部。这会导致设备在几次滚动到几乎无法使用时出现严重延迟

为了解决这个问题,我认为这会更有意义,而不是模糊细胞图像,当用户上传到sql数据库时,我会模糊它,当它出现在其他用户的feed/timeline中时,他们的iPhone将不必模糊图像,因为他们从数据库中提取的图像已经被提取

我有幸将UIImageView转换为UIImages,但每当我将其渲染为图像时,模糊效果就会失真,基本上会变成具有一定透明度的白色覆盖层

将UIImageView转换为UIImages的代码:

extension UIImage {
    convenience init(view: UIView) {
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in:UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.init(cgImage: image!.cgImage!)
    }
}
在那之后,我简单地称之为

let background = UIImageView(frame: CGRect(x: 0, y: 0, width: cell.frame.width, height: 200))
background.image = profileImage
let label = UIBlurEffect(style: UIBlurEffectStyle.prominent)
let blurEffectView = UIVisualEffectView(effect: label)
blurEffectView.frame = CGRect(x: 0, y: 0, width: background.frame.width, height: background.frame.height)
background.addSubview(blurEffectView)
let secondImage = UIImage(view: background)

可能很难看到,但第一张图像中没有模糊,它只是一个透明的白色覆盖层

应用视觉效果视图后,您需要拍摄容器视图的快照。我将演示一个可行的流程

您的控制器:

class PreviewController: UIViewController,VisualEffectCustomDelegate{
@IBOutlet weak var screenshotView: UIView!
@IBOutlet weak var previewImageView: UIImageView!


override func viewDidLoad() {
    super.viewDidLoad()


    addBlur()
}

func addBlur(){
    let label = UIBlurEffect(style: UIBlurEffectStyle.prominent)
    let blurEffectView = CustomVisualEffect(effect: label)
    blurEffectView.frame = CGRect(x: 0, y: 0, width: screenshotView.frame.width, height: screenshotView.frame.height)
    blurEffectView.delegate = self
    screenshotView.addSubview(blurEffectView)

}

func viewAppeared() {
    print("Appeared")
    previewImageView.image = screenshotView.screenShot
}


}


extension UIView {

var screenShot: UIImage?  {
    UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1.0);
    if let _ = UIGraphicsGetCurrentContext() {
        drawHierarchy(in: bounds, afterScreenUpdates: true)
        let screenshot = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return screenshot
    }
    return nil
}
}
我们为控制器类实现了VisualEffectCustomDelegate协议

protocol VisualEffectCustomDelegate {

func viewAppeared()
}
创建自己的自定义类作为VisualEffectView类的子类:

class CustomVisualEffect: UIVisualEffectView {

var delegate: VisualEffectCustomDelegate!

override init(effect: UIVisualEffect?) {
    super.init(effect: effect)
}

convenience init(){
    self.init()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func didMoveToWindow() {
    print("Visible Now")
    delegate.viewAppeared()
}
}
上述实施将起作用。 这里发生的情况如下: 控制器类确认协议VisualEffectCustomDelegate,该协议具有名为ViewDelegate的函数。当我们确定视觉效果视图在窗口中可见时,我们将使用此方法。 我们使用UIView类的didMoveToWindow方法来触发协议方法。在控制器中启动CustomVisualEffect视图时,将控制器传递给视图对象。我希望这是清楚的

由于您处理的是UITableView/UICollectionView,请根据需要对代码进行更改

//像这样试试

public extension UIImageView {
public func snapshotImage() -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
    drawHierarchy(in: bounds, afterScreenUpdates: false)
    let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return snapshotImage
}
}


这可能是您的答案,您的屏幕快照视图中必须包含要捕获的图像视图和作为子视图的模糊效果视图。这就是我要检查的最后一个函数createPostCellWell,对不起。快照方法在窗口中显示BlurView之前触发。这就是为什么它没有出现。我将修复这个问题并重写代码。但你必须根据你的要求对代码进行更改。让我试试看,我仍在弄清楚。我检查了你的代码,我们必须在任何其他视图上添加子视图背景视图。在这种情况下,只有它会创建上下文,然后只有你才能获得该视图的屏幕截图
// get image from your imageview 
 let image = background.snapshotImage()