From 12970d23d98653efa5d6c8ffb07471307bdbc12b Mon Sep 17 00:00:00 2001 From: Igor Kulman Date: Sun, 12 Nov 2023 12:52:43 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Use=20UIListContentConfigu?= =?UTF-8?q?ration=20for=20all=20the=20cells?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iOSSampleApp.xcodeproj/project.pbxproj | 4 ++ .../Scenarios/About/Cells/AboutCell.swift | 19 ++++--- .../Scenarios/About/Cells/LibraryCell.swift | 16 +++++- .../Scenarios/About/Model/Library.swift | 14 ++++++ .../ViewControllers/AboutViewController.swift | 2 +- .../LibrariesViewController.swift | 5 +- .../About/ViewModels/LibrariesViewModel.swift | 4 +- .../Scenarios/Feed/Cells/FeedCell.swift | 49 ++++--------------- 8 files changed, 55 insertions(+), 58 deletions(-) create mode 100644 Sources/iOSSampleApp/Scenarios/About/Model/Library.swift diff --git a/Sources/iOSSampleApp.xcodeproj/project.pbxproj b/Sources/iOSSampleApp.xcodeproj/project.pbxproj index 39be69a..e45a14c 100644 --- a/Sources/iOSSampleApp.xcodeproj/project.pbxproj +++ b/Sources/iOSSampleApp.xcodeproj/project.pbxproj @@ -74,6 +74,7 @@ F3C71AB72B002A8A00EEAC8E /* SpecLeaks in Frameworks */ = {isa = PBXBuildFile; productRef = F3C71AB62B002A8A00EEAC8E /* SpecLeaks */; }; F3C71ABA2B002B2400EEAC8E /* Nimble in Frameworks */ = {isa = PBXBuildFile; productRef = F3C71AB92B002B2400EEAC8E /* Nimble */; }; F3C71ABD2B002BB500EEAC8E /* Quick in Frameworks */ = {isa = PBXBuildFile; productRef = F3C71ABC2B002BB500EEAC8E /* Quick */; }; + F3C71ABF2B00F26C00EEAC8E /* Library.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C71ABE2B00F26C00EEAC8E /* Library.swift */; }; F3C7CFDD2423AF4C003A961E /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C7CFDC2423AF4C003A961E /* URL+Extensions.swift */; }; F3C8DB3B214EA1B700C1A654 /* DataServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C8DB3A214EA1B700C1A654 /* DataServiceMock.swift */; }; F3C8DB3D214EA1E700C1A654 /* SettingsServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C8DB3C214EA1E700C1A654 /* SettingsServiceMock.swift */; }; @@ -165,6 +166,7 @@ F3C5F35B2961E45000257080 /* AboutCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutCell.swift; sourceTree = ""; }; F3C5F35D2961EADD00257080 /* UIEdgeInsets+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIEdgeInsets+Extensions.swift"; sourceTree = ""; }; F3C5F3622962C56300257080 /* FormFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldView.swift; sourceTree = ""; }; + F3C71ABE2B00F26C00EEAC8E /* Library.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Library.swift; sourceTree = ""; }; F3C7CFDC2423AF4C003A961E /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; F3C8DB3A214EA1B700C1A654 /* DataServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataServiceMock.swift; sourceTree = ""; }; F3C8DB3C214EA1E700C1A654 /* SettingsServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsServiceMock.swift; sourceTree = ""; }; @@ -578,6 +580,7 @@ isa = PBXGroup; children = ( F3C5F3592961E3BB00257080 /* AboutMenuItem.swift */, + F3C71ABE2B00F26C00EEAC8E /* Library.swift */, ); path = Model; sourceTree = ""; @@ -867,6 +870,7 @@ F3A812B81F83740E00A09AAB /* AppDelegate.swift in Sources */, F38CD2371F83AEC70050056C /* UIScrollView+Extensions.swift in Sources */, F3651D22203C1B0D0082A73A /* DataService.swift in Sources */, + F3C71ABF2B00F26C00EEAC8E /* Library.swift in Sources */, F3C5F3542961BD8300257080 /* UIView+Layout.swift in Sources */, F3C5F3632962C56300257080 /* FormFieldView.swift in Sources */, F3C5F35E2961EADD00257080 /* UIEdgeInsets+Extensions.swift in Sources */, diff --git a/Sources/iOSSampleApp/Scenarios/About/Cells/AboutCell.swift b/Sources/iOSSampleApp/Scenarios/About/Cells/AboutCell.swift index 3e1cc41..3ac21c4 100644 --- a/Sources/iOSSampleApp/Scenarios/About/Cells/AboutCell.swift +++ b/Sources/iOSSampleApp/Scenarios/About/Cells/AboutCell.swift @@ -11,17 +11,16 @@ import Reusable import UIKit final class AboutCell: UITableViewCell, Reusable { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setup() - } - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + // MARK: - Properties + + var model: AboutMenuItem? + + // MARK: - Configuration - private func setup() { - textLabel?.font = UIFont.preferredFont(forTextStyle: .body) + override func updateConfiguration(using state: UICellConfigurationState) { + contentConfiguration = defaultContentConfiguration() &> { + $0.text = model?.title + } } } diff --git a/Sources/iOSSampleApp/Scenarios/About/Cells/LibraryCell.swift b/Sources/iOSSampleApp/Scenarios/About/Cells/LibraryCell.swift index 01598af..ee69f82 100644 --- a/Sources/iOSSampleApp/Scenarios/About/Cells/LibraryCell.swift +++ b/Sources/iOSSampleApp/Scenarios/About/Cells/LibraryCell.swift @@ -10,4 +10,18 @@ import Foundation import Reusable import UIKit -final class LibraryCell: UITableViewCell, Reusable { } +final class LibraryCell: UITableViewCell, Reusable { + + // MARK: - Properties + + var model: Library? + + // MARK: - Configuration + + override func updateConfiguration(using state: UICellConfigurationState) { + contentConfiguration = UIListContentConfiguration.subtitleCell() &> { + $0.text = model?.title + $0.secondaryText = model?.license + } + } +} diff --git a/Sources/iOSSampleApp/Scenarios/About/Model/Library.swift b/Sources/iOSSampleApp/Scenarios/About/Model/Library.swift new file mode 100644 index 0000000..08751fd --- /dev/null +++ b/Sources/iOSSampleApp/Scenarios/About/Model/Library.swift @@ -0,0 +1,14 @@ +// +// Library.swift +// iOSSampleApp +// +// Created by Igor Kulman on 12.11.2023. +// Copyright © 2023 Igor Kulman. All rights reserved. +// + +import Foundation + +struct Library { + let title: String + let license: String +} diff --git a/Sources/iOSSampleApp/Scenarios/About/ViewControllers/AboutViewController.swift b/Sources/iOSSampleApp/Scenarios/About/ViewControllers/AboutViewController.swift index 1d66478..25ae204 100644 --- a/Sources/iOSSampleApp/Scenarios/About/ViewControllers/AboutViewController.swift +++ b/Sources/iOSSampleApp/Scenarios/About/ViewControllers/AboutViewController.swift @@ -103,7 +103,7 @@ final class AboutViewController: UITableViewController { tableView.register(cellType: AboutCell.self) Observable.just(AboutMenuItem.allCases).bind(to: tableView.rx.items(cellIdentifier: AboutCell.reuseIdentifier, cellType: AboutCell.self)) { _, element, cell in - cell.textLabel?.text = element.title + cell.model = element }.disposed(by: disposeBag) tableView.rx.modelSelected(AboutMenuItem.self).withUnretained(self).bind { owner, menuItem in diff --git a/Sources/iOSSampleApp/Scenarios/About/ViewControllers/LibrariesViewController.swift b/Sources/iOSSampleApp/Scenarios/About/ViewControllers/LibrariesViewController.swift index 876db8f..03c74b8 100644 --- a/Sources/iOSSampleApp/Scenarios/About/ViewControllers/LibrariesViewController.swift +++ b/Sources/iOSSampleApp/Scenarios/About/ViewControllers/LibrariesViewController.swift @@ -45,11 +45,10 @@ final class LibrariesViewController: UITableViewController { private func setupData() { tableView.dataSource = nil tableView.register(cellType: LibraryCell.self) + tableView.allowsSelection = false viewModel.libraries.bind(to: tableView.rx.items(cellIdentifier: LibraryCell.reuseIdentifier, cellType: LibraryCell.self)) { _, element, cell in - let (name, licenseName) = element - cell.textLabel?.text = name - cell.detailTextLabel?.text = licenseName + cell.model = element }.disposed(by: disposeBag) } } diff --git a/Sources/iOSSampleApp/Scenarios/About/ViewModels/LibrariesViewModel.swift b/Sources/iOSSampleApp/Scenarios/About/ViewModels/LibrariesViewModel.swift index 672897e..0489cbe 100644 --- a/Sources/iOSSampleApp/Scenarios/About/ViewModels/LibrariesViewModel.swift +++ b/Sources/iOSSampleApp/Scenarios/About/ViewModels/LibrariesViewModel.swift @@ -9,8 +9,6 @@ import Foundation import RxSwift -typealias Library = (String, String) - final class LibrariesViewModel { // MARK: - Properties @@ -25,7 +23,7 @@ final class LibrariesViewModel { libraries = Observable.just(array.map { let title = $0["title"] as! String let license = $0["license"] as! String - return (title, license) + return Library(title: title, license: license) }) } } diff --git a/Sources/iOSSampleApp/Scenarios/Feed/Cells/FeedCell.swift b/Sources/iOSSampleApp/Scenarios/Feed/Cells/FeedCell.swift index c790dc5..f7bc496 100644 --- a/Sources/iOSSampleApp/Scenarios/Feed/Cells/FeedCell.swift +++ b/Sources/iOSSampleApp/Scenarios/Feed/Cells/FeedCell.swift @@ -11,51 +11,20 @@ import UIKit final class FeedCell: UITableViewCell, Reusable { - // MARK: - UI - - private lazy var titleLabel: UILabel = .init() &> { - $0.font = UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: 17, weight: .semibold)) - $0.adjustsFontForContentSizeCategory = true - } - - private lazy var descriptionLabel: UILabel = .init() &> { - $0.font = UIFont.preferredFont(forTextStyle: .subheadline) - $0.numberOfLines = 3 - } - // MARK: - Properties - var model: RssItem? { - didSet { - guard let model = model else { - return - } + var model: RssItem? - titleLabel.text = model.title - descriptionLabel.text = model.description?.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) - } - } + // MARK: - Configuration - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setup() - } - - @available(*, unavailable) - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override func updateConfiguration(using state: UICellConfigurationState) { + contentConfiguration = UIListContentConfiguration.subtitleCell() &> { + $0.text = model?.title + $0.secondaryText = model?.description?.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil) - // MARK: - Setup - - private func setup() { - preservesSuperviewLayoutMargins = true - contentView.preservesSuperviewLayoutMargins = true - - let stackView: UIStackView = .init(arrangedSubviews: [titleLabel, descriptionLabel]) &> { - $0.axis = .vertical + $0.textProperties.font = UIFontMetrics.default.scaledFont(for: UIFont.systemFont(ofSize: 17, weight: .semibold)) + $0.secondaryTextProperties.font = UIFont.preferredFont(forTextStyle: .subheadline) + $0.secondaryTextProperties.numberOfLines = 3 } - - stackView.pin(to: self, guide: layoutMarginsGuide) } }