182 lines
5.9 KiB
Swift
182 lines
5.9 KiB
Swift
//
|
|
// ZLFetchImageOperation.swift
|
|
// ZLPhotoBrowser
|
|
//
|
|
// Created by long on 2020/8/18.
|
|
//
|
|
// Copyright (c) 2020 Long Zhang <495181165@qq.com>
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
import UIKit
|
|
import Photos
|
|
|
|
class ZLFetchImageOperation: Operation {
|
|
private let model: ZLPhotoModel
|
|
|
|
private let isOriginal: Bool
|
|
|
|
private let progress: ((CGFloat, Error?, UnsafeMutablePointer<ObjCBool>, [AnyHashable: Any]?) -> Void)?
|
|
|
|
private let completion: (UIImage?, PHAsset?) -> Void
|
|
|
|
private var pri_isExecuting = false {
|
|
willSet {
|
|
self.willChangeValue(forKey: "isExecuting")
|
|
}
|
|
didSet {
|
|
self.didChangeValue(forKey: "isExecuting")
|
|
}
|
|
}
|
|
|
|
override var isExecuting: Bool {
|
|
return pri_isExecuting
|
|
}
|
|
|
|
private var pri_isFinished = false {
|
|
willSet {
|
|
self.willChangeValue(forKey: "isFinished")
|
|
}
|
|
didSet {
|
|
self.didChangeValue(forKey: "isFinished")
|
|
}
|
|
}
|
|
|
|
override var isFinished: Bool {
|
|
return pri_isFinished
|
|
}
|
|
|
|
private var pri_isCancelled = false {
|
|
willSet {
|
|
willChangeValue(forKey: "isCancelled")
|
|
}
|
|
didSet {
|
|
didChangeValue(forKey: "isCancelled")
|
|
}
|
|
}
|
|
|
|
private var requestImageID: PHImageRequestID = PHInvalidImageRequestID
|
|
|
|
override var isCancelled: Bool {
|
|
return pri_isCancelled
|
|
}
|
|
|
|
init(
|
|
model: ZLPhotoModel,
|
|
isOriginal: Bool,
|
|
progress: ((CGFloat, Error?, UnsafeMutablePointer<ObjCBool>, [AnyHashable: Any]?) -> Void)? = nil,
|
|
completion: @escaping ((UIImage?, PHAsset?) -> Void)
|
|
) {
|
|
self.model = model
|
|
self.isOriginal = isOriginal
|
|
self.progress = progress
|
|
self.completion = completion
|
|
super.init()
|
|
}
|
|
|
|
override func start() {
|
|
if isCancelled {
|
|
fetchFinish()
|
|
return
|
|
}
|
|
zl_debugPrint("---- start fetch")
|
|
pri_isExecuting = true
|
|
|
|
// 存在编辑的图片
|
|
if let editImage = model.editImage {
|
|
if ZLPhotoConfiguration.default().saveNewImageAfterEdit {
|
|
ZLPhotoManager.saveImageToAlbum(image: editImage) { [weak self] _, asset in
|
|
self?.completion(editImage, asset)
|
|
self?.fetchFinish()
|
|
}
|
|
} else {
|
|
ZLMainAsync {
|
|
self.completion(editImage, nil)
|
|
self.fetchFinish()
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if ZLPhotoConfiguration.default().allowSelectGif, model.type == .gif {
|
|
requestImageID = ZLPhotoManager.fetchOriginalImageData(for: model.asset) { [weak self] data, _, isDegraded in
|
|
if !isDegraded {
|
|
let image = UIImage.zl.animateGifImage(data: data)
|
|
self?.completion(image, nil)
|
|
self?.fetchFinish()
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if isOriginal {
|
|
requestImageID = ZLPhotoManager.fetchOriginalImage(for: model.asset, progress: progress) { [weak self] image, isDegraded in
|
|
if !isDegraded {
|
|
zl_debugPrint("---- 原图加载完成 \(String(describing: self?.isCancelled))")
|
|
self?.completion(image?.zl.fixOrientation(), nil)
|
|
self?.fetchFinish()
|
|
}
|
|
}
|
|
} else {
|
|
requestImageID = ZLPhotoManager.fetchImage(for: model.asset, size: model.previewSize, progress: progress) { [weak self] image, isDegraded in
|
|
if !isDegraded {
|
|
zl_debugPrint("---- 加载完成 isCancelled: \(String(describing: self?.isCancelled))")
|
|
self?.completion(self?.scaleImage(image?.zl.fixOrientation()), nil)
|
|
self?.fetchFinish()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override func cancel() {
|
|
super.cancel()
|
|
zl_debugPrint("---- cancel \(isExecuting) \(requestImageID)")
|
|
PHImageManager.default().cancelImageRequest(requestImageID)
|
|
pri_isCancelled = true
|
|
if isExecuting {
|
|
fetchFinish()
|
|
}
|
|
}
|
|
|
|
private func scaleImage(_ image: UIImage?) -> UIImage? {
|
|
guard let i = image else {
|
|
return nil
|
|
}
|
|
guard let data = i.jpegData(compressionQuality: 1) else {
|
|
return i
|
|
}
|
|
let mUnit: CGFloat = 1024 * 1024
|
|
|
|
if data.count < Int(0.2 * mUnit) {
|
|
return i
|
|
}
|
|
let scale: CGFloat = (data.count > Int(mUnit) ? 0.6 : 0.8)
|
|
|
|
guard let d = i.jpegData(compressionQuality: scale) else {
|
|
return i
|
|
}
|
|
return UIImage(data: d)
|
|
}
|
|
|
|
private func fetchFinish() {
|
|
pri_isExecuting = false
|
|
pri_isFinished = true
|
|
}
|
|
}
|