Kingfisher3.x의 분석과 학습(二)
ImageProcessor
//이미지 프로세서, 정의public enum ImageProcessItem {
case image(Image)
case data(Data)
}
/// An `ImageProcessor` would be used to convert some downloaded data to an image.
public protocol ImageProcessor {
var identifier: String { get }
func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image?
}
typealias ProcessorImp = ((ImageProcessItem, KingfisherOptionsInfo) -> Image?)
public extension ImageProcessor {
/// Append an `ImageProcessor` to another. The identifier of the new `ImageProcessor`
/// will be "\(self.identifier)|>\(another.identifier)".
///
/// - parameter another: An `ImageProcessor` you want to append to `self`.
///
/// - returns: The new `ImageProcessor`. It will process the image in the order
/// of the two processors concatenated.
public func append(another: ImageProcessor) -> ImageProcessor {
let newIdentifier = identifier.appending("|>\(another.identifier)")
return GeneralProcessor(identifier: newIdentifier) {
item, options in
// ImageProcessor , another another
if let image = self.process(item: item, options: options) {
return another.process(item: .image(image), options: options)
} else {
return nil
}
}
}
}
fileprivate struct GeneralProcessor: ImageProcessor {
let identifier: String
let p: ProcessorImp
func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
return p(item, options)
}
}
/// The default processor. It convert the input data to a valid image.
/// Images of .PNG, .JPEG and .GIF format are supported.
/// If an image is given, `DefaultImageProcessor` will do nothing on it and just return that image.
public struct DefaultImageProcessor: ImageProcessor {
/// A default `DefaultImageProcessor` could be used across.
public static let `default` = DefaultImageProcessor()
public let identifier = ""
/// Initialize a `DefaultImageProcessor`
///
/// - returns: An initialized `DefaultImageProcessor`.
public init() {}
//
public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
switch item {
case .image(let image):
return image
case .data(let data):
return Kingfisher.image(
data: data,
scale: options.scaleFactor,
preloadAllGIFData: options.preloadAllGIFData,
onlyFirstFrame: options.onlyLoadFirstFrame)
}
}
}
이미지 프로세서의 구체적인 기능은 모두 Image 클래스에서 실현되고 그들은 모두 ImageProcessor를 준수하고 실현했다//
public struct RoundCornerImageProcessor: ImageProcessor {
public let identifier: String
//
public let targetSize: CGSize?
public init(cornerRadius: CGFloat, targetSize: CGSize? = nil) {
self.cornerRadius = cornerRadius
self.targetSize = targetSize
if let size = targetSize {
self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)_\(size))"
} else {
self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius))"
}
}
public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
switch item {
case .image(let image):
let size = targetSize ?? image.kf.size
return image.kf.image(withRoundRadius: cornerRadius, fit: size)
case .data(_):
// image,
return (DefaultImageProcessor.default >> self).process(item: item, options: options)
}
}
}
//resize
ResizingImageProcessor
//
BlurImageProcessor
//
OverlayImageProcessor
//tint
TintImageProcessor
// 、
ColorControlsProcessor
image
연관 또는 별칭 새 속성// MARK: - Image Properties
extension Kingfisher where Base: Image {
// animatedImageData
fileprivate(set) var animatedImageData: Data? {
get {
return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
}
set {
//OBJC_ASSOCIATION_RETAIN_NONATOMIC,
objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var cgImage: CGImage? {
return base.cgImage
}
var scale: CGFloat {
return base.scale
}
var images: [Image]? {
return base.images
}
var duration: TimeInterval {
return base.duration
}
fileprivate(set) var imageSource: ImageSource? {
get {
return objc_getAssociatedObject(base, &imageSourceKey) as? ImageSource
}
set {
objc_setAssociatedObject(base, &imageSourceKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var size: CGSize {
return base.size
}
}
Kingfisher에서 정의한 unknow 이미지 다시 그리기public var normalized: Image {
// prevent animated image (GIF) lose it's images
guard images == nil else { return base }
// No need to do anything if already up
guard base.imageOrientation != .up else { return base }
return draw(cgImage: nil, to: size) {
base.draw(in: CGRect(origin: CGPoint.zero, size: size))
}
}
이미지에서 데이터와 이미지의 상호 전환// MARK: - Image Representation
extension Kingfisher where Base: Image {
// MARK: - PNG
public func pngRepresentation() -> Data? {
// PNG image data
return UIImagePNGRepresentation(base)
}
// MARK: - JPEG
public func jpegRepresentation(compressionQuality: CGFloat) -> Data? {
// JPEG image data,compressionQuality
return UIImageJPEGRepresentation(base, compressionQuality)
}
// MARK: - GIF
public func gifRepresentation() -> Data? {
return animatedImageData
}
}
static func image(data: Data, scale: CGFloat, preloadAllGIFData: Bool, onlyFirstFrame: Bool) -> Image? {
var image: Image?
switch data.kf.imageFormat {
case .JPEG:
image = Image(data: data, scale: scale)
case .PNG:
image = Image(data: data, scale: scale)
case .GIF:
image = Kingfisher.animated(
with: data,
scale: scale,
duration: 0.0,
preloadAll: preloadAllGIFData,
onlyFirstFrame: onlyFirstFrame)
case .unknown:
image = Image(data: data, scale: scale)
}
return image
}
그림 처리//
public func image(withRoundRadius radius: CGFloat, fit size: CGSize) -> Image
//resize
public func resize(to size: CGSize) -> Image
public func resize(to size: CGSize, for contentMode: ContentMode) -> Image
//
public func blurred(withRadius radius: CGFloat) -> Image
//
public func overlaying(with color: Color, fraction: CGFloat) -> Image
//tint
public func tinted(with color: Color) -> Image
// 、
public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image
디코딩 var decoded: Image? {
return decoded(scale: scale)
}
func decoded(scale: CGFloat) -> Image {
if images != nil { return base }
guard let imageRef = self.cgImage else {
assertionFailure("[Kingfisher] Decoding only works for CG-based image.")
return base
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let context = beginContext() else {
assertionFailure("[Kingfisher] Decoding fails to create a valid context.")
return base
}
defer { endContext() }
let rect = CGRect(x: 0, y: 0, width: imageRef.width, height: imageRef.height)
context.draw(imageRef, in: rect)
let decompressedImageRef = context.makeImage()
return Kingfisher.image(cgImage: decompressedImageRef!, scale: scale, refImage: base)
}
그림 형식 및 크기/// Reference the source image reference
class ImageSource {
var imageRef: CGImageSource?
init(ref: CGImageSource) {
self.imageRef = ref
}
}
// MARK: - Image format
private struct ImageHeaderData {
static var PNG: [UInt8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
static var JPEG_SOI: [UInt8] = [0xFF, 0xD8]
static var JPEG_IF: [UInt8] = [0xFF]
static var GIF: [UInt8] = [0x47, 0x49, 0x46]
}
enum ImageFormat {
case unknown, PNG, JPEG, GIF
}
// MARK: - Misc Helpers
public struct DataProxy {
fileprivate let base: Data
init(proxy: Data) {
base = proxy
}
}
extension Data: KingfisherCompatible {
public typealias CompatibleType = DataProxy
public var kf: DataProxy {
return DataProxy(proxy: self)
}
}
extension DataProxy {
// image
var imageFormat: ImageFormat {
var buffer = [UInt8](repeating: 0, count: 8)
(base as NSData).getBytes(&buffer, length: 8)
if buffer == ImageHeaderData.PNG {
return .PNG
} else if buffer[0] == ImageHeaderData.JPEG_SOI[0] &&
buffer[1] == ImageHeaderData.JPEG_SOI[1] &&
buffer[2] == ImageHeaderData.JPEG_IF[0]
{
return .JPEG
} else if buffer[0] == ImageHeaderData.GIF[0] &&
buffer[1] == ImageHeaderData.GIF[1] &&
buffer[2] == ImageHeaderData.GIF[2]
{
return .GIF
}
return .unknown
}
}
public struct CGSizeProxy {
fileprivate let base: CGSize
init(proxy: CGSize) {
base = proxy
}
}
extension CGSize: KingfisherCompatible {
public typealias CompatibleType = CGSizeProxy
public var kf: CGSizeProxy {
return CGSizeProxy(proxy: self)
}
}
extension CGSizeProxy {
func constrained(_ size: CGSize) -> CGSize {
let aspectWidth = round(aspectRatio * size.height)
let aspectHeight = round(size.width / aspectRatio)
return aspectWidth > size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
}
func filling(_ size: CGSize) -> CGSize {
let aspectWidth = round(aspectRatio * size.height)
let aspectHeight = round(size.width / aspectRatio)
return aspectWidth < size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
}
private var aspectRatio: CGFloat {
return base.height == 0.0 ? 1.0 : base.width / base.height
}
}
Indicator // , none。 UIActivityIndicatorView,
// gif, imageData , Indicator。
// Indicator ,
public enum IndicatorType {
/// No indicator.
case none
/// Use system activity indicator.
case activity
/// Use an image as indicator. GIF is supported.
case image(imageData: Data)
/// Use a custom indicator, which conforms to the `Indicator` protocol.
case custom(indicator: Indicator)
}
// MARK: - Indicator Protocol
public protocol Indicator {
func startAnimatingView()
func stopAnimatingView()
var viewCenter: CGPoint { get set }
var view: IndicatorView { get }
}
extension Indicator {
public var viewCenter: CGPoint {
get {
return view.center
}
set {
view.center = newValue
}
}
}
Indicator Protocol의 구체적인 구현 준수// MARK: - ActivityIndicator
// Displays a NSProgressIndicator / UIActivityIndicatorView
struct ActivityIndicator: Indicator {
private let activityIndicatorView: UIActivityIndicatorView
var view: IndicatorView {
return activityIndicatorView
}
func startAnimatingView() {
activityIndicatorView.startAnimating()
activityIndicatorView.isHidden = false
}
func stopAnimatingView() {
activityIndicatorView.stopAnimating()
activityIndicatorView.isHidden = true
}
init() {
let indicatorStyle = UIActivityIndicatorViewStyle.gray
activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle:indicatorStyle)
activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleTopMargin]
}
}
// MARK: - ImageIndicator
// Displays an ImageView. Supports gif
struct ImageIndicator: Indicator {
private let animatedImageIndicatorView: ImageView
var view: IndicatorView {
return animatedImageIndicatorView
}
init?(imageData data: Data, processor: ImageProcessor = DefaultImageProcessor.default, options: KingfisherOptionsInfo = KingfisherEmptyOptionsInfo) {
var options = options
// Use normal image view to show gif, so we need to preload all gif data.
if !options.preloadAllGIFData {
options.append(.preloadAllGIFData)
}
guard let image = processor.process(item: .data(data), options: options) else {
return nil
}
animatedImageIndicatorView = ImageView()
animatedImageIndicatorView.image = image
animatedImageIndicatorView.contentMode = .center
animatedImageIndicatorView.autoresizingMask = [.flexibleLeftMargin,
.flexibleRightMargin,
.flexibleBottomMargin,
.flexibleTopMargin]
}
func startAnimatingView() {
animatedImageIndicatorView.startAnimating()
animatedImageIndicatorView.isHidden = false
}
func stopAnimatingView() {
animatedImageIndicatorView.stopAnimating()
animatedImageIndicatorView.isHidden = true
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
public enum ImageProcessItem {
case image(Image)
case data(Data)
}
/// An `ImageProcessor` would be used to convert some downloaded data to an image.
public protocol ImageProcessor {
var identifier: String { get }
func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image?
}
typealias ProcessorImp = ((ImageProcessItem, KingfisherOptionsInfo) -> Image?)
public extension ImageProcessor {
/// Append an `ImageProcessor` to another. The identifier of the new `ImageProcessor`
/// will be "\(self.identifier)|>\(another.identifier)".
///
/// - parameter another: An `ImageProcessor` you want to append to `self`.
///
/// - returns: The new `ImageProcessor`. It will process the image in the order
/// of the two processors concatenated.
public func append(another: ImageProcessor) -> ImageProcessor {
let newIdentifier = identifier.appending("|>\(another.identifier)")
return GeneralProcessor(identifier: newIdentifier) {
item, options in
// ImageProcessor , another another
if let image = self.process(item: item, options: options) {
return another.process(item: .image(image), options: options)
} else {
return nil
}
}
}
}
fileprivate struct GeneralProcessor: ImageProcessor {
let identifier: String
let p: ProcessorImp
func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
return p(item, options)
}
}
/// The default processor. It convert the input data to a valid image.
/// Images of .PNG, .JPEG and .GIF format are supported.
/// If an image is given, `DefaultImageProcessor` will do nothing on it and just return that image.
public struct DefaultImageProcessor: ImageProcessor {
/// A default `DefaultImageProcessor` could be used across.
public static let `default` = DefaultImageProcessor()
public let identifier = ""
/// Initialize a `DefaultImageProcessor`
///
/// - returns: An initialized `DefaultImageProcessor`.
public init() {}
//
public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
switch item {
case .image(let image):
return image
case .data(let data):
return Kingfisher.image(
data: data,
scale: options.scaleFactor,
preloadAllGIFData: options.preloadAllGIFData,
onlyFirstFrame: options.onlyLoadFirstFrame)
}
}
}
//
public struct RoundCornerImageProcessor: ImageProcessor {
public let identifier: String
//
public let targetSize: CGSize?
public init(cornerRadius: CGFloat, targetSize: CGSize? = nil) {
self.cornerRadius = cornerRadius
self.targetSize = targetSize
if let size = targetSize {
self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)_\(size))"
} else {
self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius))"
}
}
public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
switch item {
case .image(let image):
let size = targetSize ?? image.kf.size
return image.kf.image(withRoundRadius: cornerRadius, fit: size)
case .data(_):
// image,
return (DefaultImageProcessor.default >> self).process(item: item, options: options)
}
}
}
//resize
ResizingImageProcessor
//
BlurImageProcessor
//
OverlayImageProcessor
//tint
TintImageProcessor
// 、
ColorControlsProcessor
연관 또는 별칭 새 속성
// MARK: - Image Properties
extension Kingfisher where Base: Image {
// animatedImageData
fileprivate(set) var animatedImageData: Data? {
get {
return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
}
set {
//OBJC_ASSOCIATION_RETAIN_NONATOMIC,
objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var cgImage: CGImage? {
return base.cgImage
}
var scale: CGFloat {
return base.scale
}
var images: [Image]? {
return base.images
}
var duration: TimeInterval {
return base.duration
}
fileprivate(set) var imageSource: ImageSource? {
get {
return objc_getAssociatedObject(base, &imageSourceKey) as? ImageSource
}
set {
objc_setAssociatedObject(base, &imageSourceKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var size: CGSize {
return base.size
}
}
Kingfisher에서 정의한 unknow 이미지 다시 그리기
public var normalized: Image {
// prevent animated image (GIF) lose it's images
guard images == nil else { return base }
// No need to do anything if already up
guard base.imageOrientation != .up else { return base }
return draw(cgImage: nil, to: size) {
base.draw(in: CGRect(origin: CGPoint.zero, size: size))
}
}
이미지에서 데이터와 이미지의 상호 전환
// MARK: - Image Representation
extension Kingfisher where Base: Image {
// MARK: - PNG
public func pngRepresentation() -> Data? {
// PNG image data
return UIImagePNGRepresentation(base)
}
// MARK: - JPEG
public func jpegRepresentation(compressionQuality: CGFloat) -> Data? {
// JPEG image data,compressionQuality
return UIImageJPEGRepresentation(base, compressionQuality)
}
// MARK: - GIF
public func gifRepresentation() -> Data? {
return animatedImageData
}
}
static func image(data: Data, scale: CGFloat, preloadAllGIFData: Bool, onlyFirstFrame: Bool) -> Image? {
var image: Image?
switch data.kf.imageFormat {
case .JPEG:
image = Image(data: data, scale: scale)
case .PNG:
image = Image(data: data, scale: scale)
case .GIF:
image = Kingfisher.animated(
with: data,
scale: scale,
duration: 0.0,
preloadAll: preloadAllGIFData,
onlyFirstFrame: onlyFirstFrame)
case .unknown:
image = Image(data: data, scale: scale)
}
return image
}
그림 처리
//
public func image(withRoundRadius radius: CGFloat, fit size: CGSize) -> Image
//resize
public func resize(to size: CGSize) -> Image
public func resize(to size: CGSize, for contentMode: ContentMode) -> Image
//
public func blurred(withRadius radius: CGFloat) -> Image
//
public func overlaying(with color: Color, fraction: CGFloat) -> Image
//tint
public func tinted(with color: Color) -> Image
// 、
public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image
디코딩
var decoded: Image? {
return decoded(scale: scale)
}
func decoded(scale: CGFloat) -> Image {
if images != nil { return base }
guard let imageRef = self.cgImage else {
assertionFailure("[Kingfisher] Decoding only works for CG-based image.")
return base
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let context = beginContext() else {
assertionFailure("[Kingfisher] Decoding fails to create a valid context.")
return base
}
defer { endContext() }
let rect = CGRect(x: 0, y: 0, width: imageRef.width, height: imageRef.height)
context.draw(imageRef, in: rect)
let decompressedImageRef = context.makeImage()
return Kingfisher.image(cgImage: decompressedImageRef!, scale: scale, refImage: base)
}
그림 형식 및 크기
/// Reference the source image reference
class ImageSource {
var imageRef: CGImageSource?
init(ref: CGImageSource) {
self.imageRef = ref
}
}
// MARK: - Image format
private struct ImageHeaderData {
static var PNG: [UInt8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
static var JPEG_SOI: [UInt8] = [0xFF, 0xD8]
static var JPEG_IF: [UInt8] = [0xFF]
static var GIF: [UInt8] = [0x47, 0x49, 0x46]
}
enum ImageFormat {
case unknown, PNG, JPEG, GIF
}
// MARK: - Misc Helpers
public struct DataProxy {
fileprivate let base: Data
init(proxy: Data) {
base = proxy
}
}
extension Data: KingfisherCompatible {
public typealias CompatibleType = DataProxy
public var kf: DataProxy {
return DataProxy(proxy: self)
}
}
extension DataProxy {
// image
var imageFormat: ImageFormat {
var buffer = [UInt8](repeating: 0, count: 8)
(base as NSData).getBytes(&buffer, length: 8)
if buffer == ImageHeaderData.PNG {
return .PNG
} else if buffer[0] == ImageHeaderData.JPEG_SOI[0] &&
buffer[1] == ImageHeaderData.JPEG_SOI[1] &&
buffer[2] == ImageHeaderData.JPEG_IF[0]
{
return .JPEG
} else if buffer[0] == ImageHeaderData.GIF[0] &&
buffer[1] == ImageHeaderData.GIF[1] &&
buffer[2] == ImageHeaderData.GIF[2]
{
return .GIF
}
return .unknown
}
}
public struct CGSizeProxy {
fileprivate let base: CGSize
init(proxy: CGSize) {
base = proxy
}
}
extension CGSize: KingfisherCompatible {
public typealias CompatibleType = CGSizeProxy
public var kf: CGSizeProxy {
return CGSizeProxy(proxy: self)
}
}
extension CGSizeProxy {
func constrained(_ size: CGSize) -> CGSize {
let aspectWidth = round(aspectRatio * size.height)
let aspectHeight = round(size.width / aspectRatio)
return aspectWidth > size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
}
func filling(_ size: CGSize) -> CGSize {
let aspectWidth = round(aspectRatio * size.height)
let aspectHeight = round(size.width / aspectRatio)
return aspectWidth < size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
}
private var aspectRatio: CGFloat {
return base.height == 0.0 ? 1.0 : base.width / base.height
}
}
Indicator // , none。 UIActivityIndicatorView,
// gif, imageData , Indicator。
// Indicator ,
public enum IndicatorType {
/// No indicator.
case none
/// Use system activity indicator.
case activity
/// Use an image as indicator. GIF is supported.
case image(imageData: Data)
/// Use a custom indicator, which conforms to the `Indicator` protocol.
case custom(indicator: Indicator)
}
// MARK: - Indicator Protocol
public protocol Indicator {
func startAnimatingView()
func stopAnimatingView()
var viewCenter: CGPoint { get set }
var view: IndicatorView { get }
}
extension Indicator {
public var viewCenter: CGPoint {
get {
return view.center
}
set {
view.center = newValue
}
}
}
Indicator Protocol의 구체적인 구현 준수// MARK: - ActivityIndicator
// Displays a NSProgressIndicator / UIActivityIndicatorView
struct ActivityIndicator: Indicator {
private let activityIndicatorView: UIActivityIndicatorView
var view: IndicatorView {
return activityIndicatorView
}
func startAnimatingView() {
activityIndicatorView.startAnimating()
activityIndicatorView.isHidden = false
}
func stopAnimatingView() {
activityIndicatorView.stopAnimating()
activityIndicatorView.isHidden = true
}
init() {
let indicatorStyle = UIActivityIndicatorViewStyle.gray
activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle:indicatorStyle)
activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleTopMargin]
}
}
// MARK: - ImageIndicator
// Displays an ImageView. Supports gif
struct ImageIndicator: Indicator {
private let animatedImageIndicatorView: ImageView
var view: IndicatorView {
return animatedImageIndicatorView
}
init?(imageData data: Data, processor: ImageProcessor = DefaultImageProcessor.default, options: KingfisherOptionsInfo = KingfisherEmptyOptionsInfo) {
var options = options
// Use normal image view to show gif, so we need to preload all gif data.
if !options.preloadAllGIFData {
options.append(.preloadAllGIFData)
}
guard let image = processor.process(item: .data(data), options: options) else {
return nil
}
animatedImageIndicatorView = ImageView()
animatedImageIndicatorView.image = image
animatedImageIndicatorView.contentMode = .center
animatedImageIndicatorView.autoresizingMask = [.flexibleLeftMargin,
.flexibleRightMargin,
.flexibleBottomMargin,
.flexibleTopMargin]
}
func startAnimatingView() {
animatedImageIndicatorView.startAnimating()
animatedImageIndicatorView.isHidden = false
}
func stopAnimatingView() {
animatedImageIndicatorView.stopAnimating()
animatedImageIndicatorView.isHidden = true
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
// , none。 UIActivityIndicatorView,
// gif, imageData , Indicator。
// Indicator ,
public enum IndicatorType {
/// No indicator.
case none
/// Use system activity indicator.
case activity
/// Use an image as indicator. GIF is supported.
case image(imageData: Data)
/// Use a custom indicator, which conforms to the `Indicator` protocol.
case custom(indicator: Indicator)
}
// MARK: - Indicator Protocol
public protocol Indicator {
func startAnimatingView()
func stopAnimatingView()
var viewCenter: CGPoint { get set }
var view: IndicatorView { get }
}
extension Indicator {
public var viewCenter: CGPoint {
get {
return view.center
}
set {
view.center = newValue
}
}
}
// MARK: - ActivityIndicator
// Displays a NSProgressIndicator / UIActivityIndicatorView
struct ActivityIndicator: Indicator {
private let activityIndicatorView: UIActivityIndicatorView
var view: IndicatorView {
return activityIndicatorView
}
func startAnimatingView() {
activityIndicatorView.startAnimating()
activityIndicatorView.isHidden = false
}
func stopAnimatingView() {
activityIndicatorView.stopAnimating()
activityIndicatorView.isHidden = true
}
init() {
let indicatorStyle = UIActivityIndicatorViewStyle.gray
activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle:indicatorStyle)
activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleTopMargin]
}
}
// MARK: - ImageIndicator
// Displays an ImageView. Supports gif
struct ImageIndicator: Indicator {
private let animatedImageIndicatorView: ImageView
var view: IndicatorView {
return animatedImageIndicatorView
}
init?(imageData data: Data, processor: ImageProcessor = DefaultImageProcessor.default, options: KingfisherOptionsInfo = KingfisherEmptyOptionsInfo) {
var options = options
// Use normal image view to show gif, so we need to preload all gif data.
if !options.preloadAllGIFData {
options.append(.preloadAllGIFData)
}
guard let image = processor.process(item: .data(data), options: options) else {
return nil
}
animatedImageIndicatorView = ImageView()
animatedImageIndicatorView.image = image
animatedImageIndicatorView.contentMode = .center
animatedImageIndicatorView.autoresizingMask = [.flexibleLeftMargin,
.flexibleRightMargin,
.flexibleBottomMargin,
.flexibleTopMargin]
}
func startAnimatingView() {
animatedImageIndicatorView.startAnimating()
animatedImageIndicatorView.isHidden = false
}
func stopAnimatingView() {
animatedImageIndicatorView.stopAnimating()
animatedImageIndicatorView.isHidden = true
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.