250 lines
8.3 KiB
Swift
250 lines
8.3 KiB
Swift
//
|
||
// ImagePlugin.swift
|
||
// DLSDK
|
||
//
|
||
// Created by osell on 2023/4/14.
|
||
//
|
||
|
||
import UIKit
|
||
import Kingfisher
|
||
import CoreMedia
|
||
|
||
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
|
||
}
|
||
// 如果是SDK中图片,则加载SDK中图片
|
||
if let image = UIImage(named: imageStr) {
|
||
base.image = image
|
||
return
|
||
}
|
||
// 都不存在,则置为nil
|
||
base.image = placeholder
|
||
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) { result in
|
||
switch result {
|
||
case let .success(imageinfo):
|
||
completionHandler?(imageinfo.image, nil)
|
||
case let .failure(error):
|
||
completionHandler?(nil, error)
|
||
}
|
||
}
|
||
} else {
|
||
// 使用kf加载图片
|
||
base.kf.setImage(with: imageURL, placeholder: placeholder) { 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
|
||
}
|
||
// 如果是SDK中图片,则加载SDK中图片
|
||
if let image = UIImage(named: imageStr) {
|
||
base.setImage(image, for: state)
|
||
return
|
||
}
|
||
// 都不存在,则置为nil
|
||
base.setImage(placeholder, for: state)
|
||
return
|
||
}
|
||
// 使用kf加载图片
|
||
base.kf.setImage(with: imageURL, for: state, placeholder: placeholder, 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
|
||
}
|
||
// 如果是SDK中图片,则加载SDK中图片
|
||
if let image = UIImage(named: imageStr) {
|
||
base.setBackgroundImage(image, for: state)
|
||
return
|
||
}
|
||
// 都不存在,则置为nil
|
||
base.setBackgroundImage(placeholder, for: state)
|
||
return
|
||
}
|
||
// 使用kf加载图片
|
||
base.kf.setBackgroundImage(with: imageURL, for: state, placeholder: placeholder, 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 = UIImage()
|
||
}
|
||
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()
|
||
image = nil
|
||
kf.setImage(with: url, placeholder: nil)
|
||
} else {
|
||
kf.cancelDownloadTask()
|
||
image = HeadPic.localImage(trimmed)
|
||
}
|
||
}
|
||
}
|