Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] #260 - 무한 스크롤 과정에서 발생한 메모리 사용량 개선 및 레이아웃 계산 최적화 #261

Merged
merged 6 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions GEON-PPANG-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,6 @@
3E35432F2AAC700600BD926A /* SignUpRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpRequestDTO.swift; sourceTree = "<group>"; };
3E3543312AAC707200BD926A /* PlatformEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformEnum.swift; sourceTree = "<group>"; };
3E3543332AAD594E00BD926A /* SignUpResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpResponseDTO.swift; sourceTree = "<group>"; };
3E36D7D22A8E15C200B2C1CC /* GEON-PPANG-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "GEON-PPANG-iOS.entitlements"; sourceTree = "<group>"; };
3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = "<group>"; };
3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = "<group>"; };
3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -533,13 +532,6 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
0905561C2A51DAF900752067 /* Design */ = {
isa = PBXGroup;
children = (
);
path = Design;
sourceTree = "<group>";
};
090556232A51DB7A00752067 /* UI */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -812,7 +804,6 @@
isa = PBXGroup;
children = (
090556232A51DB7A00752067 /* UI */,
0905561C2A51DAF900752067 /* Design */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -859,7 +850,6 @@
isa = PBXGroup;
children = (
09E30E892BFF123C001E107B /* Config.xcconfig */,
3E36D7D22A8E15C200B2C1CC /* GEON-PPANG-iOS.entitlements */,
098F32EE2A4200FE0092D09A /* Info.plist */,
094392CE2A84E68700984310 /* GoogleService-Info.plist */,
0961C36F2A501F4C0031A822 /* Storyboard */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ final class LogInViewController: BaseViewController {

private var loginEmail: String = ""
private var loginPassword: String = ""
private var IsEmailValid: Bool = false
private var IsPasswordValid: Bool = false
private var isEmailValid: Bool = false
private var isPasswordValid: Bool = false
private var isValid: Bool = false {
didSet {
configureButtonUI(self.isValid)
Expand Down Expand Up @@ -182,15 +182,15 @@ extension LogInViewController: UITextFieldDelegate {
switch textField {
case emailTextField.configureTextField():
self.loginEmail = text
self.IsEmailValid = (text.isValidEmail() && !emailTextField.fetchText().isEmpty) ? true : false
self.isEmailValid = (text.isValidEmail() && !emailTextField.fetchText().isEmpty) ? true : false
case passwordTextField.configureTextField():
self.loginPassword = text
self.IsPasswordValid = !passwordTextField.fetchText().isEmpty ? true : false
self.isPasswordValid = !passwordTextField.fetchText().isEmpty ? true : false
default:
break
}

self.isValid = IsEmailValid && IsPasswordValid
self.isValid = isEmailValid && isPasswordValid
configureButtonUI(self.isValid)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ final class BakeryCommonCollectionViewCell: UICollectionViewCell {

private var breadTypeTag: [String] = []
private var ingredientList: [BakeryCommonListResponseDTO] = []

private var itemSizeCache: [Int: CGSize] = [:]

// MARK: - UI Property

private let markStackView = MarkStackView()
Expand All @@ -32,13 +33,14 @@ final class BakeryCommonCollectionViewCell: UICollectionViewCell {

override func prepareForReuse() {
super.prepareForReuse()

ingredientList = []
bakeryImage.kf.cancelDownloadTask()
bakeryImage.image = nil
itemSizeCache.removeAll()
}

override init(frame: CGRect) {
super.init(frame: .zero)

super.init(frame: frame)
setLayout()
setUI()
setRegistration()
Expand All @@ -58,7 +60,6 @@ final class BakeryCommonCollectionViewCell: UICollectionViewCell {
$0.top.equalToSuperview().offset(24)
$0.leading.equalToSuperview().inset(24)
$0.bottom.equalToSuperview().inset(24)

}

contentView.addSubview(bookmarkCount)
Expand Down Expand Up @@ -123,45 +124,53 @@ final class BakeryCommonCollectionViewCell: UICollectionViewCell {
}

func configureReviewsUI() {

bookmarkCount.removeFromSuperview()
}

func configureCellUI<T: BakeryListProtocol>(data: T) {

bakeryTitle.setLineHeight(by: 1.05, with: data.name)
bakeryTitle.lineBreakMode = .byTruncatingTail

bookmarkCount.configureHomeCell(count: data.bookmarkCount)
bookmarkCount.setContentHuggingPriority(UILayoutPriority(751), for: .horizontal)
bookmarkCount.setContentCompressionResistancePriority(UILayoutPriority(751), for: .horizontal)

guard let url = URL(string: data.picture) else { return }
bakeryImage.kf.setImage(with: url, placeholder: UIImage.loading_small)

regionStackView.configureListUI(text: data.station)
markStackView.getMarkStatus(data.isHACCP, data.isVegan, data.isNonGMO)

breadTypeTag = []
data.breadTypeList.forEach {
breadTypeTag.append($0.toString())
}
collectionView.reloadData()
setupCellUI(name: data.name,
pictureURL: data.picture,
station: data.station,
isHACCP: data.isHACCP,
isVegan: data.isVegan,
isNonGMO: data.isNonGMO,
breadTypeList: data.breadTypeList)
}

func configureCellUI(data: MyReviewsResponseDTO) {
bakeryTitle.setLineHeight(by: 1.05, with: data.name)
setupCellUI(name: data.name,
pictureURL: data.picture,
station: data.station,
isHACCP: data.isHACCP,
isVegan: data.isVegan,
isNonGMO: data.isNonGMO,
breadTypeList: data.breadTypeList)
}

private func setupCellUI(name: String, pictureURL: String, station: String, isHACCP: Bool, isVegan: Bool, isNonGMO: Bool, breadTypeList: [BreadType]) {
bakeryTitle.setLineHeight(by: 1.05, with: name)
bakeryTitle.lineBreakMode = .byTruncatingTail

guard let url = URL(string: data.picture) else { return }
bakeryImage.kf.setImage(with: url, placeholder: UIImage.loading_small)

regionStackView.configureListUI(text: data.station)
markStackView.getMarkStatus(data.isHACCP, data.isVegan, data.isNonGMO)

breadTypeTag = []
data.breadTypeList.forEach {
breadTypeTag.append($0.toString())
}
guard let url = URL(string: pictureURL) else { return }
bakeryImage.kf.setImage(
with: url,
placeholder: UIImage.loading_small,
options: [
.processor(DownsamplingImageProcessor(size: CGSize(width: 86, height: 86))),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아주 필요한 기능을 알잘딱깔센으로다가 잘 넣고 있군요 !!!!

코드 보다가 문득 든 생각이 ... 요 DownsamplingImageProcessor 녀석을 셀마다 인스턴스로 만들지 않고
collectionview마다 만들거나 더 좋은 방법으로 재사용할 수는 없을까에 대한 생각이 들었습니다 !!

셀마다 주입하는건 어떨지 ... 아니면 kingfisher extension으로 어떻게 할 방법은 없을지 고민해보죠 !!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 좋습니당 :)

.scaleFactor(UIScreen.main.scale),
.cacheOriginalImage
])

regionStackView.configureListUI(text: station)
markStackView.getMarkStatus(isHACCP, isVegan, isNonGMO)

breadTypeTag = breadTypeList.map { $0.toString() }
itemSizeCache.removeAll()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 itemSizeCache도 Cell마다 인스턴스로 갖고 있기 보다는
어차피 모든 BakeryCommonCollectionViewCell 에서 쓰일테니까 한 곳에서 관리하는것도 괜찮지 않을까 싶네요 !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 한 곳에서 관리하는 것도 좋은 방법인 것 같슴돠 !!! 이 부분도 같이 고민하는걸로 ,

collectionView.reloadData()
}
}
Expand All @@ -170,7 +179,6 @@ final class BakeryCommonCollectionViewCell: UICollectionViewCell {

extension BakeryCommonCollectionViewCell {
private func setRegistration() {

collectionView.register(cell: DescriptionCollectionViewCell.self)
}
}
Expand All @@ -179,12 +187,10 @@ extension BakeryCommonCollectionViewCell {

extension BakeryCommonCollectionViewCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

return breadTypeTag.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell: DescriptionCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath)
cell.cellColor = .sub
cell.configureTagTitle(self.breadTypeTag[indexPath.item])
Expand All @@ -196,9 +202,15 @@ extension BakeryCommonCollectionViewCell: UICollectionViewDataSource {

extension BakeryCommonCollectionViewCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tagTitle = breadTypeTag[indexPath.item]

guard let cachedSize = itemSizeCache[tagTitle.count] else {
let itemSize = tagTitle.size(withAttributes: [NSAttributedString.Key.font: UIFont.captionM2])
let finalSize = CGSize(width: itemSize.width + 12, height: itemSize.height)
itemSizeCache[tagTitle.count] = finalSize
return finalSize
}

let tagTitle = self.breadTypeTag[indexPath.item]
let itemSize = tagTitle.size(withAttributes: [NSAttributedString.Key.font: UIFont.captionM2!])
return CGSize(width: itemSize.width + 12, height: itemSize.height)
return cachedSize
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ final class BakeryListViewController: BaseViewController {
$0.tappedCheckBox = { [weak self] tapped in
guard let self else { return }
guard KeychainService.readKeychain(of: .role) == UserRole.member.rawValue
else {
else {
Utils.showLoginRequiredSheet(on: self, type: .recommendation)
bakerySortView.tappedButton(false)
return
Expand All @@ -162,6 +162,7 @@ final class BakeryListViewController: BaseViewController {
bakeryListCollectionView.do {
$0.delegate = self
$0.refreshControl = refreshControl
$0.prefetchDataSource = self
}
}

Expand Down Expand Up @@ -259,11 +260,18 @@ extension BakeryListViewController: UICollectionViewDelegate {
Utils.setDetailSourceType(.LIST)
Utils.push(self.navigationController, nextViewController)
}

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
}

extension BakeryListViewController: UICollectionViewDataSourcePrefetching {
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {

if indexPath.item == bakeryList.count - 1, !self.isLast {
getMoreBakeryList()
let serialQueue = DispatchQueue(label: "Decode queue")
for indexPath in indexPaths {
serialQueue.async {
if self.bakeryList.count - 1 == indexPath.item, !self.isLast {
self.getMoreBakeryList()
}
}
}
}
}
Expand Down
Loading