旋转共享扩展中的图像

时间:2019-07-12 14:20:51

标签: ios swift ios-app-extension share-extension

我有此扩展程序,它在应用程序目标中运行完美,但是在尝试旋转相机上捕获的图像时在共享扩展程序中崩溃。如何在共享扩展中旋转图像?或者可能已经从照片库中以正确的方向加载图像。

extension UIImage {

    func fixOrientation() -> UIImage {
        switch imageOrientation {
        case .up:
            return self
        default:
            UIGraphicsBeginImageContextWithOptions(size, false, scale)
            draw(in: CGRect(origin: .zero, size: size)) //Thread 1: EXC_RESOURCE RESOURCE_TYPE_MEMORY (limit=120 MB, unused=0x0)
            let result = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return result!
        }
    }
}


崩溃截图:

crash screenshot #1 crash screenshot #2

3 个答案:

答案 0 :(得分:3)

首先,很明显您的内存崩溃了。根据{{​​3}}:

  

正在运行的应用程序扩展的内存限制明显低于对前台应用程序施加的内存限制。在这两个平台上,系统都可能会主动终止扩展,因为用户希望返回主机应用程序中的主要目标。

从错误中可以明显看出,您超过了120 mb。但是您可能想知道什么占用了如此多的内存。

根据App Extension Programming Guide

  

iOS本质上是从图像的尺寸中获取其内存容量-而实际文件大小与它无关。

因此,如果我们计算尺寸或4032 x 3024照片,它将是... 4位颜色为46mb,8位颜色为79mb。相当大,但还不到极限...

事实是-您有两张图像副本。一种是原始的,另一种是旋转的。

要解决此问题,您仅需要将旋转的图像加载到内存中,而无需原始图像。可以使用Optimizing Images Written by Jordan Morgan

extension UIImage {
    static func imageWithFixedOrientation(at url: URL) -> UIImage? {
        guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) else { return nil }

        guard let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? Dictionary<CFString, Any> else { return nil }

        guard
            let width = imageProperties[kCGImagePropertyPixelWidth] as? CGFloat,
            let height = imageProperties[kCGImagePropertyPixelHeight] as? CGFloat
            else { return nil }

        let options: [NSString: Any] = [
            kCGImageSourceThumbnailMaxPixelSize: max(width, height),
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceCreateThumbnailWithTransform: true
        ]

        guard let cgImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary) else { return nil }

        return UIImage(cgImage: cgImage)
    }
}

在示例应用中:

extension ViewController: UIImagePickerControllerDelegate & UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true)
        guard let url = info[.imageURL] as? URL else { return }

        let image = UIImage.imageWithFixedOrientation(at: url)
    }
}

它将内存峰值从180 + mb降低到仅80mb。

答案 1 :(得分:0)

您是否尝试使用didFinishPicking委托方法中提供的功能?

func photoLibrary() {
    if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
        let myPickerController = UIImagePickerController()
        myPickerController.delegate = self
        myPickerController.sourceType = .photoLibrary
        self.present(myPickerController, animated: true, completion: nil)
    }
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true)

    guard let image = info[.originalImage] as? UIImage else {
        print("No image found")
        return
    }

    // Flip the image here
    self.mainImageView.image = image.fixOrientation()
}

答案 2 :(得分:0)

您可以尝试使用更优化的<div class="header"> <div class="leftSide"> <button>Save</button> <button>Next</button> <button>Back</button> </div> <div class="middle">Some text here - min char 0, max 140</div> <div class="rightSide"> <button>Cancel</button> <button>Other Button</button> </div> </div>而不是旧的UIGraphicsImageRendererFormat,可以在此post中找到更多信息。因此,您的代码将如下所示:

UIGraphicsBeginImageContextWithOptions