jsdw_ios/QuickLocation/Plugin/ImagePlugin.swift

275 lines
9.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ImagePlugin.swift
// DLSDK
//
// Created by osell on 2023/4/14.
//
import UIKit
import Kingfisher
import CoreMedia
nonisolated(unsafe) let kBrokenNetworkImage = UIImage(named: "Common/image_broken") ?? UIImage()
extension UIImage {
static var brokenNetworkImage: UIImage { kBrokenNetworkImage }
}
private let kNetworkImageFailureOptions: KingfisherOptionsInfo = [
.onFailureImage(kBrokenNetworkImage)
]
public protocol ImageSource {
/// URL
var imageURL: URL? { get }
///
var imageStr: String? { get }
}
extension ImageSource {
var imageURL: URL? { nil }
var imageStr: String? { nil }
}
extension String: ImageSource {
public var imageURL: URL? { URL(string: self.urlEncodingWithQueryAllowedCharacters) }
public var imageStr: String? { self }
}
extension URL: ImageSource {
public var imageURL: URL? { self }
public var imageStr: String? { self.absoluteString.urlDecoded }
}
// MARK: - UIImageView
extension DLWrapper where Base: UIImageView {
///
/// - Parameters:
/// - url: /, URL or String
/// - placeholder: nil
/// - completionHandler: nil
@MainActor public func setImage(with url: ImageSource?,
placeholder: UIImage? = nil,
completionHandler: ((UIImage?, Error?) -> Void)? = nil) {
guard let imageURL = url?.imageURL else {
let imageStr = url?.imageStr ?? ""
// ,
if let image = UIImage(named: imageStr) {
base.image = image
return
}
// SDKSDK
if let image = UIImage(named: imageStr) {
base.image = image
return
}
base.image = placeholder ?? .brokenNetworkImage
return
}
// ,
if imageURL.imageStr?.contains(".mp4") == true {
let source = AVAssetImageDataProvider(assetURL: imageURL, time: CMTimeMakeWithSeconds(0.0, preferredTimescale: 1))
base.kf.setImage(
with: source.convertToSource(),
placeholder: placeholder,
options: kNetworkImageFailureOptions
) { result in
switch result {
case let .success(imageinfo):
completionHandler?(imageinfo.image, nil)
case let .failure(error):
completionHandler?(nil, error)
}
}
} else {
base.kf.setImage(
with: imageURL,
placeholder: placeholder,
options: kNetworkImageFailureOptions
) { result in
switch result {
case let .success(imageinfo):
completionHandler?(imageinfo.image, nil)
case let .failure(error):
completionHandler?(nil, error)
}
}
}
}
}
// MARK: - Button
extension DLWrapper where Base: UIButton {
///
/// - Parameters:
/// - url: , URL or String
/// - placeholder: nil
/// - completionHandler: nil
@MainActor public func setImage(with url: ImageSource?,
for state: UIControl.State,
placeholder: UIImage? = nil,
completionHandler: ((UIImage?, Error?) -> Void)? = nil) {
guard let imageURL = url?.imageURL else {
let imageStr = url?.imageStr ?? ""
// ,
if let image = UIImage(named: imageStr) {
base.setImage(image, for: state)
return
}
// SDKSDK
if let image = UIImage(named: imageStr) {
base.setImage(image, for: state)
return
}
// nil
base.setImage(placeholder ?? .brokenNetworkImage, for: state)
return
}
base.kf.setImage(
with: imageURL,
for: state,
placeholder: placeholder,
options: kNetworkImageFailureOptions,
completionHandler: { result in
switch result {
case let .success(imageinfo):
completionHandler?(imageinfo.image, nil)
case let .failure(error):
completionHandler?(nil, error)
}
}
)
}
///
/// - Parameters:
/// - url: , URL or String
/// - placeholder: nil
/// - completionHandler: nil
@MainActor public func setBackgroundImage(with url: ImageSource?,
for state: UIControl.State,
placeholder: UIImage? = nil,
completionHandler: ((UIImage?, Error?) -> Void)? = nil) {
guard let imageURL = url?.imageURL else {
let imageStr = url?.imageStr ?? ""
// ,
if let image = UIImage(named: imageStr) {
base.setBackgroundImage(image, for: state)
return
}
// SDKSDK
if let image = UIImage(named: imageStr) {
base.setBackgroundImage(image, for: state)
return
}
// nil
base.setBackgroundImage(placeholder ?? .brokenNetworkImage, for: state)
return
}
base.kf.setBackgroundImage(
with: imageURL,
for: state,
placeholder: placeholder,
options: kNetworkImageFailureOptions,
completionHandler: { result in
switch result {
case let .success(imageinfo):
completionHandler?(imageinfo.image, nil)
case let .failure(error):
completionHandler?(nil, error)
}
}
)
}
}
enum HeadPic {
static let placeholder = UIImage(named: "UserIcon/1") ?? UIImage()
static func isRemote(_ value: String) -> Bool {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
return trimmed.hasPrefix("http://") || trimmed.hasPrefix("https://")
}
static func resolved(_ values: String?...) -> String {
let trimmed = values
.compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
if let remote = trimmed.first(where: { isRemote($0) }) {
return remote
}
return trimmed.first ?? ""
}
static func localImage(_ value: String) -> UIImage {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return placeholder }
return UIImage(named: "UserIcon/\(trimmed)") ?? placeholder
}
static func remoteURL(for value: String) -> URL? {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
guard isRemote(trimmed) else { return nil }
return trimmed.imageURL ?? URL(string: trimmed)
}
static func image(for value: String) -> UIImage {
guard let url = remoteURL(for: value) else {
return localImage(value)
}
let key = url.cacheKey
if let cached = ImageCache.default.retrieveImageInMemoryCache(forKey: key) {
return cached
}
return UIImage()
}
static func load(_ value: String, completion: @escaping (UIImage) -> Void) {
guard let url = remoteURL(for: value) else {
completion(localImage(value))
return
}
KingfisherManager.shared.retrieveImage(with: url) { result in
let image: UIImage
switch result {
case let .success(value):
image = value.image
case .failure:
image = .brokenNetworkImage
}
DispatchQueue.main.async {
completion(image)
}
}
}
}
extension UIImageView {
func setHeadPic(_ value: String?) {
let trimmed = (value ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
kf.cancelDownloadTask()
image = HeadPic.placeholder
return
}
if let url = HeadPic.remoteURL(for: trimmed) {
kf.cancelDownloadTask()
kf.setImage(with: url, placeholder: nil, options: kNetworkImageFailureOptions)
} else {
kf.cancelDownloadTask()
image = HeadPic.localImage(trimmed)
}
}
}