Skip to content

Commit d340126

Browse files
author
Marek Fořt
committed
Add UIKit detail.
1 parent 03f50cf commit d340126

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import Foundation
2+
import UIKit
3+
import ComposableArchitecture
4+
import ComposableTuistArchitectureSupport
5+
import Combine
6+
import SwiftUI
7+
8+
public struct UIKit_RecipeDetailView: UIViewControllerRepresentable {
9+
private let store: Store<RecipeDetailState, RecipeDetailAction>
10+
11+
public init(store: Store<RecipeDetailState, RecipeDetailAction>) {
12+
self.store = store
13+
}
14+
15+
public func makeUIViewController(context: Context) -> RecipeDetailViewController {
16+
RecipeDetailViewController(store: store)
17+
}
18+
19+
public func updateUIViewController(_ uiViewController: RecipeDetailViewController, context: Context) {
20+
21+
}
22+
}
23+
24+
public final class RecipeDetailViewController: UIViewController {
25+
struct State: Equatable {
26+
let recipe: Recipe
27+
}
28+
29+
enum Action {
30+
case loadRecipe
31+
}
32+
33+
// MARK: - Private properties
34+
35+
private weak var nameLabel: UILabel!
36+
private weak var descriptionLabel: UILabel!
37+
38+
private let store: Store<RecipeDetailState, RecipeDetailAction>
39+
private let viewStore: ViewStore<State, Action>
40+
private var cancellables: Set<AnyCancellable> = []
41+
42+
init(store: Store<RecipeDetailState, RecipeDetailAction>) {
43+
self.store = store
44+
viewStore = ViewStore(
45+
store
46+
.scope(state: State.init, action: RecipeDetailAction.init)
47+
)
48+
super.init(nibName: nil, bundle: nil)
49+
}
50+
51+
@available(*, unavailable)
52+
required init?(coder aDecoder: NSCoder) {
53+
fatalError("init(coder:) has not been implemented")
54+
}
55+
56+
public override func loadView() {
57+
super.loadView()
58+
59+
let vStack = UIStackView()
60+
vStack.axis = .vertical
61+
vStack.alignment = .center
62+
vStack.spacing = 10
63+
view.addSubview(vStack)
64+
vStack.translatesAutoresizingMaskIntoConstraints = false
65+
NSLayoutConstraint.activate([
66+
vStack.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor),
67+
vStack.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor),
68+
vStack.centerYAnchor.constraint(equalTo: view.centerYAnchor)
69+
])
70+
71+
let nameLabel = UILabel()
72+
nameLabel.textAlignment = .center
73+
vStack.addArrangedSubview(nameLabel)
74+
self.nameLabel = nameLabel
75+
76+
let descriptionLabel = UILabel()
77+
descriptionLabel.textAlignment = .center
78+
vStack.addArrangedSubview(descriptionLabel)
79+
self.descriptionLabel = descriptionLabel
80+
}
81+
82+
public override func viewDidLoad() {
83+
super.viewDidLoad()
84+
85+
viewStore.publisher
86+
.map(\.recipe)
87+
.map(\.name)
88+
.sink(receiveValue: { [weak self] in self?.nameLabel.text = $0 })
89+
.store(in: &self.cancellables)
90+
91+
viewStore.publisher
92+
.map(\.recipe)
93+
.map(\.description)
94+
.sink(receiveValue: { [weak self] in self?.descriptionLabel.text = $0 })
95+
.store(in: &self.cancellables)
96+
97+
viewStore.send(.loadRecipe)
98+
}
99+
}
100+
101+
102+
extension RecipeDetailViewController.State {
103+
init(state: RecipeDetailState) {
104+
recipe = state.recipe
105+
}
106+
}
107+
108+
extension RecipeDetailAction {
109+
init(action: RecipeDetailViewController.Action) {
110+
switch action {
111+
case .loadRecipe:
112+
self = .loadDetail
113+
}
114+
}
115+
}

Diff for: Projects/Features/RecipeList/Sources/RecipeList.swift

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct RecipeListView: View {
4242
destination: IfLetStore(
4343
self.store.scope(state: { $0.selectionRecipe?.value }, action: RecipeListFeatureAction.recipeDetail),
4444
then: RecipeDetailView.init
45+
// then: UIKit_RecipeDetailView.init
4546
),
4647
tag: recipe.id,
4748
selection: viewStore.binding(

0 commit comments

Comments
 (0)