Advance UIKit rewrite with AMap integration and core UI modules.
Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -7,64 +7,81 @@ import SnapKit
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
// MARK: - Diffable 标识
|
||||
|
||||
/// 设置页行标识。
|
||||
private enum SettingsRowID {
|
||||
static let about = "settings:about"
|
||||
static let version = "settings:version"
|
||||
static let download = "settings:download"
|
||||
static let userAgreement = "settings:userAgreement"
|
||||
static let privacyPolicy = "settings:privacyPolicy"
|
||||
}
|
||||
|
||||
/// 设置页行操作类型。
|
||||
private enum SettingsRowAction {
|
||||
case agreement(AgreementPage)
|
||||
case version
|
||||
case download
|
||||
}
|
||||
|
||||
/// 设置中心页面。
|
||||
final class SettingsViewController: UIViewController {
|
||||
final class SettingsViewController: SimpleTableDiffableViewController {
|
||||
|
||||
private var copiedDownloadLink = false
|
||||
|
||||
private lazy var tableView: UITableView = {
|
||||
let table = UITableView(frame: .zero, style: .insetGrouped)
|
||||
table.dataSource = self
|
||||
table.delegate = self
|
||||
return table
|
||||
}()
|
||||
|
||||
private let rows: [(title: String, action: SettingsRowAction)] = [
|
||||
("关于我们", .agreement(.about)),
|
||||
("系统版本", .version),
|
||||
("App下载", .download),
|
||||
("用户协议", .agreement(.userAgreement)),
|
||||
("隐私政策", .agreement(.privacyPolicy))
|
||||
private let rowActions: [String: SettingsRowAction] = [
|
||||
SettingsRowID.about: .agreement(.about),
|
||||
SettingsRowID.version: .version,
|
||||
SettingsRowID.download: .download,
|
||||
SettingsRowID.userAgreement: .agreement(.userAgreement),
|
||||
SettingsRowID.privacyPolicy: .agreement(.privacyPolicy)
|
||||
]
|
||||
|
||||
private enum SettingsRowAction {
|
||||
case agreement(AgreementPage)
|
||||
case version
|
||||
case download
|
||||
}
|
||||
private let rowTitles: [String: String] = [
|
||||
SettingsRowID.about: "关于我们",
|
||||
SettingsRowID.version: "系统版本",
|
||||
SettingsRowID.download: "App下载",
|
||||
SettingsRowID.userAgreement: "用户协议",
|
||||
SettingsRowID.privacyPolicy: "隐私政策"
|
||||
]
|
||||
|
||||
/// 视图加载完成后的 UI 初始化与数据绑定。
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
title = "设置"
|
||||
view.addSubview(tableView)
|
||||
tableView.snp.makeConstraints { make in make.edges.equalToSuperview() }
|
||||
}
|
||||
|
||||
private var downloadLink: String {
|
||||
APIEnvironment.current.baseURL.appending(path: "/h5/app/download").absoluteString
|
||||
/// 构建 Diffable snapshot。
|
||||
override func buildSnapshot() -> NSDiffableDataSourceSnapshot<SimpleTableSection, SimpleTableRow> {
|
||||
var snapshot = NSDiffableDataSourceSnapshot<SimpleTableSection, SimpleTableRow>()
|
||||
snapshot.appendSections([0])
|
||||
snapshot.appendItems([
|
||||
SettingsRowID.about,
|
||||
SettingsRowID.version,
|
||||
SettingsRowID.download,
|
||||
SettingsRowID.userAgreement,
|
||||
SettingsRowID.privacyPolicy
|
||||
], toSection: 0)
|
||||
return snapshot
|
||||
}
|
||||
|
||||
private func copyDownloadLink() {
|
||||
UIPasteboard.general.string = downloadLink
|
||||
copiedDownloadLink = true
|
||||
showToast("下载链接已复制")
|
||||
tableView.reloadRows(at: [IndexPath(row: 2, section: 0)], with: .none)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
|
||||
self?.copiedDownloadLink = false
|
||||
self?.tableView.reloadRows(at: [IndexPath(row: 2, section: 0)], with: .none)
|
||||
}
|
||||
/// section 页脚文案。
|
||||
override func sectionFooter(for section: SimpleTableSection) -> String? {
|
||||
"Copyright © 2025 All Rights Reserved\n苏ICP备2025157647号"
|
||||
}
|
||||
}
|
||||
|
||||
extension SettingsViewController: UITableViewDataSource, UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { rows.count }
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
|
||||
let row = rows[indexPath.row]
|
||||
cell.textLabel?.text = row.title
|
||||
/// 配置 Cell 展示内容。
|
||||
override func configureCell(_ cell: UITableViewCell, row: SimpleTableRow, at indexPath: IndexPath) {
|
||||
cell.textLabel?.text = rowTitles[row]
|
||||
cell.textLabel?.textColor = UIColor(hex: 0x4B5563)
|
||||
switch row.action {
|
||||
cell.detailTextLabel?.text = nil
|
||||
cell.detailTextLabel?.textColor = nil
|
||||
cell.accessoryType = .none
|
||||
cell.selectionStyle = .default
|
||||
|
||||
guard let action = rowActions[row] else { return }
|
||||
switch action {
|
||||
case .version:
|
||||
cell.detailTextLabel?.text = SettingsDisplayPolicy.versionText()
|
||||
cell.selectionStyle = .none
|
||||
@ -74,12 +91,12 @@ extension SettingsViewController: UITableViewDataSource, UITableViewDelegate {
|
||||
case .agreement:
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
switch rows[indexPath.row].action {
|
||||
/// 处理行选中。
|
||||
override func didSelectRow(_ row: SimpleTableRow, at indexPath: IndexPath) {
|
||||
guard let action = rowActions[row] else { return }
|
||||
switch action {
|
||||
case .agreement(let page):
|
||||
HomeMenuRouting.pushProfile(.agreement(page), from: self)
|
||||
case .download:
|
||||
@ -89,8 +106,25 @@ extension SettingsViewController: UITableViewDataSource, UITableViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
"Copyright © 2025 All Rights Reserved\n苏ICP备2025157647号"
|
||||
private var downloadLink: String {
|
||||
APIEnvironment.current.baseURL.appending(path: "/h5/app/download").absoluteString
|
||||
}
|
||||
|
||||
/// 复制下载链接并刷新对应行展示。
|
||||
private func copyDownloadLink() {
|
||||
UIPasteboard.general.string = downloadLink
|
||||
copiedDownloadLink = true
|
||||
showToast("下载链接已复制")
|
||||
var snapshot = tableDataSource.snapshot()
|
||||
snapshot.reconfigureItems([SettingsRowID.download])
|
||||
tableDataSource.apply(snapshot, animatingDifferences: false)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
|
||||
guard let self else { return }
|
||||
self.copiedDownloadLink = false
|
||||
var snapshot = self.tableDataSource.snapshot()
|
||||
snapshot.reconfigureItems([SettingsRowID.download])
|
||||
self.tableDataSource.apply(snapshot, animatingDifferences: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,6 +135,7 @@ final class AgreementViewController: UIViewController {
|
||||
private let webView = WKWebView(frame: .zero)
|
||||
private let loadingIndicator = UIActivityIndicatorView(style: .large)
|
||||
|
||||
/// 初始化实例。
|
||||
init(page: AgreementPage) {
|
||||
self.page = page
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
@ -109,6 +144,7 @@ final class AgreementViewController: UIViewController {
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) { fatalError() }
|
||||
|
||||
/// 视图加载完成后的 UI 初始化与数据绑定。
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
title = page.title
|
||||
@ -124,10 +160,12 @@ final class AgreementViewController: UIViewController {
|
||||
}
|
||||
|
||||
extension AgreementViewController: WKNavigationDelegate {
|
||||
/// web视图相关逻辑。
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
loadingIndicator.stopAnimating()
|
||||
}
|
||||
|
||||
/// web视图相关逻辑。
|
||||
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
||||
loadingIndicator.stopAnimating()
|
||||
showToast(error.localizedDescription)
|
||||
|
||||
Reference in New Issue
Block a user