From bc47ebeb37dbc2be523369e7d42e195d8f3d96cf Mon Sep 17 00:00:00 2001 From: longitachi Date: Tue, 28 Jun 2022 14:36:22 +0800 Subject: [PATCH] Code optimization --- Sources/Edit/ZLEditImageViewController.swift | 34 +++++++++++++++-- .../Extensions/UIImage+ZLPhotoBrowser.swift | 37 ++++++++++++------- Sources/General/ZLGeneralDefine.swift | 2 +- Sources/General/ZLPhotoModel.swift | 2 +- .../General/ZLPhotoPreviewController.swift | 25 +++++++------ Sources/General/ZLPhotoPreviewSheet.swift | 18 ++++----- .../General/ZLThumbnailViewController.swift | 18 ++++----- 7 files changed, 86 insertions(+), 50 deletions(-) diff --git a/Sources/Edit/ZLEditImageViewController.swift b/Sources/Edit/ZLEditImageViewController.swift index d8dc6674..f8f67855 100644 --- a/Sources/Edit/ZLEditImageViewController.swift +++ b/Sources/Edit/ZLEditImageViewController.swift @@ -206,6 +206,8 @@ open class ZLEditImageViewController: UIViewController { return pan }() + private var toolViewStateTimer: Timer? + // 第一次进入界面时,布局后frame,裁剪dimiss动画使用 var originalFrame: CGRect = .zero @@ -306,6 +308,7 @@ open class ZLEditImageViewController: UIViewController { } deinit { + cleanToolViewStateTimer() zl_debugPrint("ZLEditImageViewController deinit") } @@ -948,7 +951,7 @@ open class ZLEditImageViewController: UIViewController { path?.addLine(to: point) drawLine() } else if pan.state == .cancelled || pan.state == .ended { - setToolView(show: true) + setToolView(show: true, delay: 0.5) revokeBtn.isEnabled = drawPaths.count > 0 } } else if selectedTool == .mosaic { @@ -973,7 +976,7 @@ open class ZLEditImageViewController: UIViewController { path?.addLine(to: point) mosaicImageLayerMaskLayer?.path = path?.path.cgPath } else if pan.state == .cancelled || pan.state == .ended { - setToolView(show: true) + setToolView(show: true, delay: 0.5) revokeBtn.isEnabled = mosaicPaths.count > 0 generateNewMosaicImage() } @@ -1029,11 +1032,27 @@ open class ZLEditImageViewController: UIViewController { } } - private func setToolView(show: Bool) { + private func setToolView(show: Bool, delay: TimeInterval? = nil) { + cleanToolViewStateTimer() + if let delay = delay { + toolViewStateTimer = Timer.scheduledTimer(timeInterval: delay, target: ZLWeakProxy(target: self), selector: #selector(setToolViewShow_timerFunc(show:)), userInfo: ["show": show], repeats: false) + RunLoop.current.add(toolViewStateTimer!, forMode: .common) + } else { + setToolViewShow_timerFunc(show: show) + } + } + + @objc private func setToolViewShow_timerFunc(show: Bool) { + var flag = show + if let toolViewStateTimer = toolViewStateTimer { + let userInfo = toolViewStateTimer.userInfo as? [String: Any] + flag = userInfo?["show"] as? Bool ?? true + cleanToolViewStateTimer() + } topShadowView.layer.removeAllAnimations() bottomShadowView.layer.removeAllAnimations() adjustSlider?.layer.removeAllAnimations() - if show { + if flag { UIView.animate(withDuration: 0.25) { self.topShadowView.alpha = 1 self.bottomShadowView.alpha = 1 @@ -1048,6 +1067,11 @@ open class ZLEditImageViewController: UIViewController { } } + private func cleanToolViewStateTimer() { + toolViewStateTimer?.invalidate() + toolViewStateTimer = nil + } + private func showInputTextVC(_ text: String? = nil, textColor: UIColor? = nil, bgColor: UIColor? = nil, completion: @escaping ((String, UIColor, UIColor) -> Void)) { // Calculate image displayed frame on the screen. var r = mainScrollView.convert(view.frame, to: containerView) @@ -1230,6 +1254,8 @@ open class ZLEditImageViewController: UIViewController { midImage = UIImage(cgImage: midCgImage, scale: editImage.scale, orientation: .up) UIGraphicsBeginImageContextWithOptions(originalImage.size, false, originalImage.scale) + // 由于生成的mosaic图片可能在边缘区域出现空白部分,导致合成后会有黑边,所以在最下面先画一张原图 + originalImage.draw(in: renderRect) (inputMosaicImage ?? mosaicImage)?.draw(in: renderRect) midImage?.draw(in: renderRect) diff --git a/Sources/Extensions/UIImage+ZLPhotoBrowser.swift b/Sources/Extensions/UIImage+ZLPhotoBrowser.swift index 0415109d..2b418bd9 100644 --- a/Sources/Extensions/UIImage+ZLPhotoBrowser.swift +++ b/Sources/Extensions/UIImage+ZLPhotoBrowser.swift @@ -190,16 +190,15 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { var transform = CGAffineTransform.identity - let size = base.size switch base.imageOrientation { case .down, .downMirrored: - transform = CGAffineTransform(translationX: size.width, y: size.height) + transform = CGAffineTransform(translationX: width, y: height) transform = transform.rotated(by: .pi) case .left, .leftMirrored: - transform = CGAffineTransform(translationX: size.width, y: 0) + transform = CGAffineTransform(translationX: width, y: 0) transform = transform.rotated(by: CGFloat.pi / 2) case .right, .rightMirrored: - transform = CGAffineTransform(translationX: 0, y: size.height) + transform = CGAffineTransform(translationX: 0, y: height) transform = transform.rotated(by: -CGFloat.pi / 2) default: break @@ -207,10 +206,10 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { switch base.imageOrientation { case .upMirrored, .downMirrored: - transform = transform.translatedBy(x: size.width, y: 0) + transform = transform.translatedBy(x: width, y: 0) transform = transform.scaledBy(x: -1, y: 1) case .leftMirrored, .rightMirrored: - transform = transform.translatedBy(x: size.height, y: 0) + transform = transform.translatedBy(x: height, y: 0) transform = transform.scaledBy(x: -1, y: 1) default: break @@ -221,8 +220,8 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { } let context = CGContext( data: nil, - width: Int(size.width), - height: Int(size.height), + width: Int(width), + height: Int(height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, @@ -231,9 +230,9 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { context?.concatenate(transform) switch base.imageOrientation { case .left, .leftMirrored, .right, .rightMirrored: - context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width)) + context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: height, height: width)) default: - context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) + context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height)) } guard let newCgImage = context?.makeImage() else { @@ -316,8 +315,7 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { return base } - let size = base.size - let rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height)) + let rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: width, height: height)) let t = CGAffineTransform(rotationAngle: degress) rotatedViewBox.transform = t let rotatedSize = rotatedViewBox.frame.size @@ -329,7 +327,7 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { bitmap?.rotate(by: degress) bitmap?.scaleBy(x: 1.0, y: -1.0) - bitmap?.draw(cgImage, in: CGRect(x: -size.width / 2, y: -size.height / 2, width: size.width, height: size.height)) + bitmap?.draw(cgImage, in: CGRect(x: -width / 2, y: -height / 2, width: width, height: height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() @@ -342,10 +340,11 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { return nil } + let scale = 8 * width / UIScreen.main.bounds.width let currCiImage = CIImage(cgImage: cgImage) let filter = CIFilter(name: "CIPixellate") filter?.setValue(currCiImage, forKey: kCIInputImageKey) - filter?.setValue(15, forKey: kCIInputScaleKey) + filter?.setValue(scale, forKey: kCIInputScaleKey) guard let outputImage = filter?.outputImage else { return nil } let context = CIContext() @@ -508,6 +507,16 @@ public extension ZLPhotoBrowserWrapper where Base: UIImage { } } +public extension ZLPhotoBrowserWrapper where Base: UIImage { + var width: CGFloat { + base.size.width + } + + var height: CGFloat { + base.size.height + } +} + public extension ZLPhotoBrowserWrapper where Base: CIImage { func toUIImage() -> UIImage? { let context = CIContext() diff --git a/Sources/General/ZLGeneralDefine.swift b/Sources/General/ZLGeneralDefine.swift index bb841d08..8fa0afdc 100644 --- a/Sources/General/ZLGeneralDefine.swift +++ b/Sources/General/ZLGeneralDefine.swift @@ -26,7 +26,7 @@ import UIKit -let ZLMaxImageWidth: CGFloat = 600 +let ZLMaxImageWidth: CGFloat = 500 enum ZLLayout { static let navTitleFont = getFont(17) diff --git a/Sources/General/ZLPhotoModel.swift b/Sources/General/ZLPhotoModel.swift index d8d4e2bf..4571f072 100644 --- a/Sources/General/ZLPhotoModel.swift +++ b/Sources/General/ZLPhotoModel.swift @@ -78,7 +78,7 @@ public class ZLPhotoModel: NSObject { } public var previewSize: CGSize { - let scale: CGFloat = 2 // UIScreen.main.scale + let scale: CGFloat = UIScreen.main.scale if whRatio > 1 { let h = min(UIScreen.main.bounds.height, ZLMaxImageWidth) * scale let w = h * whRatio diff --git a/Sources/General/ZLPhotoPreviewController.swift b/Sources/General/ZLPhotoPreviewController.swift index e4edd688..02ffdc82 100644 --- a/Sources/General/ZLPhotoPreviewController.swift +++ b/Sources/General/ZLPhotoPreviewController.swift @@ -515,11 +515,19 @@ class ZLPhotoPreviewController: UIViewController { @objc private func editBtnClick() { let config = ZLPhotoConfiguration.default() let model = arrDataSources[currentIndex] + + var requestAvAssetID: PHImageRequestID? let hud = ZLProgressHUD(style: ZLPhotoUIConfiguration.default().hudStyle) + hud.timeoutBlock = { [weak self] in + showAlertView(localLanguageTextValue(.timeout), self) + if let requestAvAssetID = requestAvAssetID { + PHImageManager.default().cancelImageRequest(requestAvAssetID) + } + } if model.type == .image || (!config.allowSelectGif && model.type == .gif) || (!config.allowSelectLivePhoto && model.type == .livePhoto) { - hud.show() - ZLPhotoManager.fetchImage(for: model.asset, size: model.previewSize) { [weak self] image, isDegraded in + hud.show(timeout: ZLPhotoConfiguration.default().timeout) + requestAvAssetID = ZLPhotoManager.fetchImage(for: model.asset, size: model.previewSize) { [weak self] image, isDegraded in if !isDegraded { if let image = image { self?.showEditImageVC(image: image) @@ -530,19 +538,12 @@ class ZLPhotoPreviewController: UIViewController { } } } else if model.type == .video || config.allowEditVideo { - var requestAvAssetID: PHImageRequestID? - hud.show(timeout: 20) - hud.timeoutBlock = { [weak self] in - showAlertView(localLanguageTextValue(.timeout), self) - if let _ = requestAvAssetID { - PHImageManager.default().cancelImageRequest(requestAvAssetID!) - } - } + hud.show(timeout: ZLPhotoConfiguration.default().timeout) // fetch avasset requestAvAssetID = ZLPhotoManager.fetchAVAsset(forVideo: model.asset) { [weak self] avAsset, _ in hud.hide() - if let av = avAsset { - self?.showEditVideoVC(model: model, avAsset: av) + if let avAsset = avAsset { + self?.showEditVideoVC(model: model, avAsset: avAsset) } else { showAlertView(localLanguageTextValue(.timeout), self) } diff --git a/Sources/General/ZLPhotoPreviewSheet.swift b/Sources/General/ZLPhotoPreviewSheet.swift index d82f8a43..82d8fa6f 100644 --- a/Sources/General/ZLPhotoPreviewSheet.swift +++ b/Sources/General/ZLPhotoPreviewSheet.swift @@ -686,21 +686,21 @@ public class ZLPhotoPreviewSheet: UIView { var requestAvAssetID: PHImageRequestID? - hud.show(timeout: 20) + hud.show(timeout: ZLPhotoConfiguration.default().timeout) hud.timeoutBlock = { [weak self] in showAlertView(localLanguageTextValue(.timeout), self?.sender) - if let _ = requestAvAssetID { - PHImageManager.default().cancelImageRequest(requestAvAssetID!) + if let requestAvAssetID = requestAvAssetID { + PHImageManager.default().cancelImageRequest(requestAvAssetID) } } func inner_showEditVideoVC(_ avAsset: AVAsset) { let vc = ZLEditVideoViewController(avAsset: avAsset) vc.editFinishBlock = { [weak self] url in - if let u = url { - ZLPhotoManager.saveVideoToAlbum(url: u) { [weak self] suc, asset in - if suc, asset != nil { - let m = ZLPhotoModel(asset: asset!) + if let url = url { + ZLPhotoManager.saveVideoToAlbum(url: url) { [weak self] suc, asset in + if suc, let asset = asset { + let m = ZLPhotoModel(asset: asset) m.isSelected = true self?.arrSelectedModels.removeAll() self?.arrSelectedModels.append(m) @@ -722,8 +722,8 @@ public class ZLPhotoPreviewSheet: UIView { // 提前fetch一下 avasset requestAvAssetID = ZLPhotoManager.fetchAVAsset(forVideo: model.asset) { [weak self] avAsset, _ in hud.hide() - if let _ = avAsset { - inner_showEditVideoVC(avAsset!) + if let avAsset = avAsset { + inner_showEditVideoVC(avAsset) } else { showAlertView(localLanguageTextValue(.timeout), self?.sender) } diff --git a/Sources/General/ZLThumbnailViewController.swift b/Sources/General/ZLThumbnailViewController.swift index c7fdedc2..5a4c87cb 100644 --- a/Sources/General/ZLThumbnailViewController.swift +++ b/Sources/General/ZLThumbnailViewController.swift @@ -880,21 +880,21 @@ class ZLThumbnailViewController: UIViewController { var requestAvAssetID: PHImageRequestID? - hud.show(timeout: 20) + hud.show(timeout: ZLPhotoConfiguration.default().timeout) hud.timeoutBlock = { [weak self] in showAlertView(localLanguageTextValue(.timeout), self) - if let _ = requestAvAssetID { - PHImageManager.default().cancelImageRequest(requestAvAssetID!) + if let requestAvAssetID = requestAvAssetID { + PHImageManager.default().cancelImageRequest(requestAvAssetID) } } func inner_showEditVideoVC(_ avAsset: AVAsset) { let vc = ZLEditVideoViewController(avAsset: avAsset) vc.editFinishBlock = { [weak self, weak nav] url in - if let u = url { - ZLPhotoManager.saveVideoToAlbum(url: u) { [weak self, weak nav] suc, asset in - if suc, asset != nil { - let m = ZLPhotoModel(asset: asset!) + if let url = url { + ZLPhotoManager.saveVideoToAlbum(url: url) { [weak self, weak nav] suc, asset in + if suc, let asset = asset { + let m = ZLPhotoModel(asset: asset) m.isSelected = true nav?.arrSelectedModels.append(m) nav?.selectImageBlock?() @@ -914,8 +914,8 @@ class ZLThumbnailViewController: UIViewController { // 提前fetch一下 avasset requestAvAssetID = ZLPhotoManager.fetchAVAsset(forVideo: model.asset) { [weak self] avAsset, _ in hud.hide() - if let _ = avAsset { - inner_showEditVideoVC(avAsset!) + if let avAsset = avAsset { + inner_showEditVideoVC(avAsset) } else { showAlertView(localLanguageTextValue(.timeout), self) }