From 96923efd9ae86b4349198ded0e852a5cc0f05f21 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Sun, 4 May 2025 14:27:20 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix/#132:=20=EC=83=90=20=EC=9E=AC=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=A9=EC=96=B4=20=EB=B0=8F=20=EC=BA=90=EC=8B=B1?= =?UTF-8?q?=20=ED=9E=88=ED=8A=B8=20=EC=8B=9C=EC=A0=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extension/UIImageView+.swift | 131 ++++++++++++++++-- 1 file changed, 117 insertions(+), 14 deletions(-) diff --git a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift index cacd212c..f526f8a1 100644 --- a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift +++ b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift @@ -1,34 +1,137 @@ +import ObjectiveC import UIKit +private var currentURLKey: UInt8 = 0 +private var placeholderImageKey: UInt8 = 0 + public extension UIImageView { + + private var currentImageURL: String? { + get { objc_getAssociatedObject(self, ¤tURLKey) as? String } + set { objc_setAssociatedObject(self, ¤tURLKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } + } + + private var placeholderImage: UIImage? { + get { objc_getAssociatedObject(self, &placeholderImageKey) as? UIImage } + set { objc_setAssociatedObject(self, &placeholderImageKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } + } + func setPPImage(path: String?) { - guard let path = path else { - self.image = UIImage(named: "image_default") + // 기본 이미지 저장 + if placeholderImage == nil { + placeholderImage = UIImage(named: "image_default") + } + + guard let path = path, !path.isEmpty else { + image = placeholderImage + currentImageURL = nil return } + let imageURLString = Secrets.popPoolS3BaseURL + path - if let cenvertimageURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { - ImageLoader.shared.loadImage(with: cenvertimageURL, defaultImage: UIImage(named: "image_default"), imageQuality: .origin) { [weak self] image in - DispatchQueue.main.async { - self?.image = image + guard let encodedURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { + image = placeholderImage + currentImageURL = nil + return + } + + // 이미 같은 URL을 로딩했고 이미지가 있으면 재로딩 방지 + if currentImageURL == encodedURL && self.image != nil && self.image != placeholderImage { + return + } + + // 현재 이미지 URL을 업데이트 + currentImageURL = encodedURL + + // 먼저 메모리 캐시 확인 + if let cachedImage = MemoryStorage.shared.fetchImage(url: encodedURL) { + self.image = cachedImage + return + } + + // 다음으로 디스크 캐시 확인 + if let diskImage = DiskStorage.shared.fetchImage(url: encodedURL) { + MemoryStorage.shared.store(image: diskImage, url: encodedURL) + self.image = diskImage + return + } + + ImageLoader.shared.loadImage(with: encodedURL, defaultImage: placeholderImage, imageQuality: .origin) { [weak self] image in + guard let self else { return } + + DispatchQueue.main.async { + // 현재 요청 ID와 캡처된 ID가 일치하는지 확인 (다른 이미지로 변경되었으면 무시) + if self.currentImageURL == encodedURL { + if let image = image { + self.image = image + } else if self.image == nil { + // 이미지 로드 실패 시 기본 이미지 표시 + self.image = self.placeholderImage + } } } } } func setPPImage(path: String?, completion: @escaping () -> Void) { - guard let path = path else { - self.image = UIImage(named: "image_default") + // 기본 이미지 저장 + if placeholderImage == nil { + placeholderImage = UIImage(named: "image_default") + } + + guard let path = path, !path.isEmpty else { + image = placeholderImage + currentImageURL = nil completion() return } + let imageURLString = Secrets.popPoolS3BaseURL + path - if let cenvertimageURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { - let imageURL = URL(string: cenvertimageURL) - ImageLoader.shared.loadImage(with: cenvertimageURL, defaultImage: UIImage(named: "image_default"), imageQuality: .origin) { [weak self] image in - DispatchQueue.main.async { - completion() - self?.image = image + guard let encodedURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { + image = placeholderImage + currentImageURL = nil + completion() + return + } + + // 이미 같은 URL을 로딩했고 이미지가 있으면 재로딩 방지 + if currentImageURL == encodedURL && self.image != nil && self.image != placeholderImage { + completion() + return + } + + // 현재 이미지 URL을 업데이트 + currentImageURL = encodedURL + + // 먼저 메모리 캐시 확인 + if let cachedImage = MemoryStorage.shared.fetchImage(url: encodedURL) { + self.image = cachedImage + completion() + return + } + + // 다음으로 디스크 캐시 확인 + if let diskImage = DiskStorage.shared.fetchImage(url: encodedURL) { + MemoryStorage.shared.store(image: diskImage, url: encodedURL) + self.image = diskImage + completion() + return + } + + ImageLoader.shared.loadImage(with: encodedURL, defaultImage: placeholderImage, imageQuality: .origin) { [weak self] image in + DispatchQueue.main.async { + defer { completion() } + + guard let self else { return } + + // 현재 요청 ID와 캡처된 ID가 일치하는지 확인 (다른 이미지로 변경되었으면 무시) + if self.currentImageURL == encodedURL { + if let image = image { + self.image = image + } else if self.image == nil { + // 이미지 로드 실패 시 기본 이미지 표시 + self.image = self.placeholderImage + } } } } From 5eaa06d82929029a57769ca21094f23680300796 Mon Sep 17 00:00:00 2001 From: JunYoung Date: Sun, 4 May 2025 14:36:49 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix/#132:=20=EB=B0=98=EB=B3=B5=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=A1=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extension/UIImageView+.swift | 76 ++++--------------- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift index f526f8a1..cfe9e1f8 100644 --- a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift +++ b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift @@ -17,72 +17,24 @@ public extension UIImageView { } func setPPImage(path: String?) { - // 기본 이미지 저장 - if placeholderImage == nil { - placeholderImage = UIImage(named: "image_default") - } - - guard let path = path, !path.isEmpty else { - image = placeholderImage - currentImageURL = nil - return - } - - let imageURLString = Secrets.popPoolS3BaseURL + path - guard let encodedURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { - image = placeholderImage - currentImageURL = nil - return - } - - // 이미 같은 URL을 로딩했고 이미지가 있으면 재로딩 방지 - if currentImageURL == encodedURL && self.image != nil && self.image != placeholderImage { - return - } - - // 현재 이미지 URL을 업데이트 - currentImageURL = encodedURL - - // 먼저 메모리 캐시 확인 - if let cachedImage = MemoryStorage.shared.fetchImage(url: encodedURL) { - self.image = cachedImage - return - } - - // 다음으로 디스크 캐시 확인 - if let diskImage = DiskStorage.shared.fetchImage(url: encodedURL) { - MemoryStorage.shared.store(image: diskImage, url: encodedURL) - self.image = diskImage - return - } - - ImageLoader.shared.loadImage(with: encodedURL, defaultImage: placeholderImage, imageQuality: .origin) { [weak self] image in - guard let self else { return } - - DispatchQueue.main.async { - // 현재 요청 ID와 캡처된 ID가 일치하는지 확인 (다른 이미지로 변경되었으면 무시) - if self.currentImageURL == encodedURL { - if let image = image { - self.image = image - } else if self.image == nil { - // 이미지 로드 실패 시 기본 이미지 표시 - self.image = self.placeholderImage - } - } - } - } + loadImageFromImageLoader(path: path, completion: nil) } func setPPImage(path: String?, completion: @escaping () -> Void) { + loadImageFromImageLoader(path: path, completion: completion) + } + + func loadImageFromImageLoader(path: String?, completion: (() -> Void)? = nil) { // 기본 이미지 저장 if placeholderImage == nil { placeholderImage = UIImage(named: "image_default") + completion?() } guard let path = path, !path.isEmpty else { image = placeholderImage currentImageURL = nil - completion() + completion?() return } @@ -90,13 +42,13 @@ public extension UIImageView { guard let encodedURL = imageURLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { image = placeholderImage currentImageURL = nil - completion() + completion?() return } // 이미 같은 URL을 로딩했고 이미지가 있으면 재로딩 방지 if currentImageURL == encodedURL && self.image != nil && self.image != placeholderImage { - completion() + completion?() return } @@ -106,7 +58,7 @@ public extension UIImageView { // 먼저 메모리 캐시 확인 if let cachedImage = MemoryStorage.shared.fetchImage(url: encodedURL) { self.image = cachedImage - completion() + completion?() return } @@ -114,16 +66,14 @@ public extension UIImageView { if let diskImage = DiskStorage.shared.fetchImage(url: encodedURL) { MemoryStorage.shared.store(image: diskImage, url: encodedURL) self.image = diskImage - completion() + completion?() return } ImageLoader.shared.loadImage(with: encodedURL, defaultImage: placeholderImage, imageQuality: .origin) { [weak self] image in + guard let self else { return } + defer { completion?() } DispatchQueue.main.async { - defer { completion() } - - guard let self else { return } - // 현재 요청 ID와 캡처된 ID가 일치하는지 확인 (다른 이미지로 변경되었으면 무시) if self.currentImageURL == encodedURL { if let image = image { From 5ba98dd1a3bd0f54aa099fec02f5de2bcdf2917c Mon Sep 17 00:00:00 2001 From: JunYoung Date: Sun, 4 May 2025 14:38:42 +0900 Subject: [PATCH 3/3] =?UTF-8?q?style/#132:=20lint=20=EB=A3=B0=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Infrastructure/Infrastructure/Extension/UIImageView+.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift index cfe9e1f8..b1c65770 100644 --- a/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift +++ b/Poppool/CoreLayer/Infrastructure/Infrastructure/Extension/UIImageView+.swift @@ -23,7 +23,7 @@ public extension UIImageView { func setPPImage(path: String?, completion: @escaping () -> Void) { loadImageFromImageLoader(path: path, completion: completion) } - + func loadImageFromImageLoader(path: String?, completion: (() -> Void)? = nil) { // 기본 이미지 저장 if placeholderImage == nil {