Skip to content

Commit

Permalink
Added scoped store and remove view on context
Browse files Browse the repository at this point in the history
  • Loading branch information
sergdort committed Jun 13, 2021
1 parent 7c3e78b commit 31083d2
Show file tree
Hide file tree
Showing 14 changed files with 712 additions and 593 deletions.
22 changes: 17 additions & 5 deletions CombineFeedback.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/* Begin PBXBuildFile section */
2510CDDF242BD9FF004A6422 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2510CDDE242BD9FF004A6422 /* Log.swift */; };
2510CDE1242BED63004A6422 /* ContextExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2510CDE0242BED63004A6422 /* ContextExtensions.swift */; };
2510CDE1242BED63004A6422 /* StoreExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2510CDE0242BED63004A6422 /* StoreExtensions.swift */; };
251445E724086A400062EE04 /* TrafficLightView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 251445E624086A400062EE04 /* TrafficLightView.swift */; };
252BF08422BAE05700BC4265 /* SignIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 252BF08322BAE05700BC4265 /* SignIn.swift */; };
253D324122B185FA002F3B7F /* ViewContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 253D323F22B1858C002F3B7F /* ViewContext.swift */; };
254B4DB726755AE200653BB8 /* StoreBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 254B4DB626755AE200653BB8 /* StoreBox.swift */; };
25C57B2C22BC2C33007CB4D6 /* Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25C57B2B22BC2C33007CB4D6 /* Activity.swift */; };
25EBC08C23FD61B100719826 /* Reducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585CD878239AC7D3004BE9CC /* Reducer.swift */; };
25F23C2922CA984E00894863 /* TrafficLight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F23C2822CA984E00894863 /* TrafficLight.swift */; };
Expand Down Expand Up @@ -135,10 +136,11 @@

/* Begin PBXFileReference section */
2510CDDE242BD9FF004A6422 /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
2510CDE0242BED63004A6422 /* ContextExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextExtensions.swift; sourceTree = "<group>"; };
2510CDE0242BED63004A6422 /* StoreExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreExtensions.swift; sourceTree = "<group>"; };
251445E624086A400062EE04 /* TrafficLightView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficLightView.swift; sourceTree = "<group>"; };
252BF08322BAE05700BC4265 /* SignIn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignIn.swift; sourceTree = "<group>"; };
253D323F22B1858C002F3B7F /* ViewContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewContext.swift; sourceTree = "<group>"; };
254B4DB626755AE200653BB8 /* StoreBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreBox.swift; sourceTree = "<group>"; };
25C57B2B22BC2C33007CB4D6 /* Activity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Activity.swift; sourceTree = "<group>"; };
25F23C2822CA984E00894863 /* TrafficLight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrafficLight.swift; sourceTree = "<group>"; };
5800001422A9DEEA005A860B /* WithViewContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WithViewContext.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -248,6 +250,15 @@
path = SignIn;
sourceTree = "<group>";
};
254B4DB526755AD300653BB8 /* Store */ = {
isa = PBXGroup;
children = (
583971C422ADFA1F00139CC0 /* Store.swift */,
254B4DB626755AE200653BB8 /* StoreBox.swift */,
);
path = Store;
sourceTree = "<group>";
};
25F23C2722CA982400894863 /* TrafficLight */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -358,10 +369,10 @@
5800FFEB22A9DDE5005A860B /* CombineFeedbackUI */ = {
isa = PBXGroup;
children = (
254B4DB526755AD300653BB8 /* Store */,
5800FFEC22A9DDE5005A860B /* CombineFeedbackUI.h */,
5800FFED22A9DDE5005A860B /* Info.plist */,
253D323F22B1858C002F3B7F /* ViewContext.swift */,
583971C422ADFA1F00139CC0 /* Store.swift */,
5800001422A9DEEA005A860B /* WithViewContext.swift */,
);
path = CombineFeedbackUI;
Expand Down Expand Up @@ -451,7 +462,7 @@
children = (
58C6E5E622AB14DB005A9685 /* AsyncImage.swift */,
25C57B2B22BC2C33007CB4D6 /* Activity.swift */,
2510CDE0242BED63004A6422 /* ContextExtensions.swift */,
2510CDE0242BED63004A6422 /* StoreExtensions.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -763,7 +774,7 @@
5800FFB922A8CDA5005A860B /* AppDelegate.swift in Sources */,
5800FFBB22A8CDA5005A860B /* SceneDelegate.swift in Sources */,
583971C322ADBA9900139CC0 /* PublisherExtensions.swift in Sources */,
2510CDE1242BED63004A6422 /* ContextExtensions.swift in Sources */,
2510CDE1242BED63004A6422 /* StoreExtensions.swift in Sources */,
58C6E5E722AB14DB005A9685 /* AsyncImage.swift in Sources */,
5800FFBD22A8CDA5005A860B /* Counter.swift in Sources */,
25F23C2922CA984E00894863 /* TrafficLight.swift in Sources */,
Expand All @@ -786,6 +797,7 @@
5800001522A9DEEA005A860B /* WithViewContext.swift in Sources */,
583971C522ADFA1F00139CC0 /* Store.swift in Sources */,
253D324122B185FA002F3B7F /* ViewContext.swift in Sources */,
254B4DB726755AE200653BB8 /* StoreBox.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
37 changes: 19 additions & 18 deletions Example/CounterExample/Counter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,31 @@ struct CounterView: View {
typealias State = Counter.State
typealias Event = Counter.Event

@StateObject
var context: ViewContext<State, Event>
let store: Store<State, Event>

init(context: ViewContext<State, Event>) {
self._context = StateObject(wrappedValue: context)
init(store: Store<State, Event>) {
self.store = store
logInit(of: self)
}

var body: some View {
logBody(of: self)
return Form {
Button(action: {
self.context.send(event: .decrement)
}) {
Text("-").font(.largeTitle)
}
Button(action: {
self.context.send(event: .increment)
}) {
Text("+").font(.largeTitle)
}
if context.count >= 0 {
ForEach((0 ..< context.count).reversed(), id: \.self) { item in
Text("\(item)")
return WithViewContext(store: store) { context in
Form {
Button(action: {
context.send(event: .decrement)
}) {
Text("-").font(.largeTitle)
}
Button(action: {
context.send(event: .increment)
}) {
Text("+").font(.largeTitle)
}
if context.count >= 0 {
ForEach((0 ..< context.count).reversed(), id: \.self) { item in
Text("\(item)")
}
}
}
}
Expand Down
29 changes: 14 additions & 15 deletions Example/MoviesExample/Movies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,36 +43,35 @@ extension Movies {

@available(iOS 15.0, *)
private static func whenLoadingIOS15() -> Feedback<State, Event> {
.lensing(state: \.nextPage) { page in
do {
return Event.didLoad(try await URLSession.shared.movies(page: page))
} catch {
return Event.didFail(error as NSError)
}
.lensing(state: \.nextPage) { page in
do {
return Event.didLoad(try await URLSession.shared.movies(page: page))
} catch {
return Event.didFail(error as NSError)
}
}
}
}
}

struct MoviesView: View {
typealias State = Movies.State
typealias Event = Movies.Event
@StateObject
var context: ViewContext<State, Event>
let store: Store<State, Event>

init(context: ViewContext<State, Event>) {
self._context = StateObject(wrappedValue: context)
init(store: Store<State, Event>) {
self.store = store
logInit(of: self)
}

var body: some View {
logBody(of: self)
return List {
ForEach(context.movies) { movie in
NavigationLink(destination: MoviesView(context: self.context)) {
return WithViewContext(store: store) { context in
List {
ForEach(context.movies) { movie in
MovieCell(movie: movie).onAppear {
if self.context.movies.last == movie {
self.context.send(event: .fetchNext)
if context.movies.last == movie {
context.send(event: .fetchNext)
}
}
}
Expand Down
144 changes: 71 additions & 73 deletions Example/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,90 @@ import SwiftUI
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
return
}
let window = UIWindow(windowScene: windowScene)
window.rootViewController = makeSingleStoreExample()
self.window = window
window.makeKeyAndVisible()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
return
}
let window = UIWindow(windowScene: windowScene)
window.rootViewController = makeSingleStoreExample()
self.window = window
window.makeKeyAndVisible()
}

private func makeSingleStoreExample() -> UIViewController {
return UIHostingController(
rootView: Widget(
store: Store(
initial: State(),
feedbacks: [
moviesFeedback,
signInFeedback,
trafficLightFeedback
],
reducer: appReducer
),
content: SingleStoreExampleView.init
)
private func makeSingleStoreExample() -> UIViewController {
return UIHostingController(
rootView: SingleStoreExampleView(
store: Store(
initial: State(),
feedbacks: [
moviesFeedback,
signInFeedback,
trafficLightFeedback
],
reducer: appReducer
)
}
)
)
}

private func makeMultiStoreExample() -> UIViewController {
let tabbarController = UITabBarController()
private func makeMultiStoreExample() -> UIViewController {
let tabbarController = UITabBarController()

let counter = UIHostingController(
rootView: NavigationView {
Widget(store: Counter.ViewModel(), content: CounterView.init)
.navigationBarTitle(Text("Counter"))
}
)
let counter = UIHostingController(
rootView: NavigationView {
CounterView(store: Counter.ViewModel())
}
)

counter.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "eye"),
selectedImage: UIImage(systemName: "eye.fill")
)
counter.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "eye"),
selectedImage: UIImage(systemName: "eye.fill")
)

let movies = UIHostingController(
rootView: NavigationView {
return Widget(store: Movies.ViewModel(), content: MoviesView.init)
.navigationBarTitle(Text("Movies"))
}
)
let movies = UIHostingController(
rootView: NavigationView {
MoviesView(store: Movies.ViewModel())
.navigationBarTitle(Text("Movies"))
}
)

movies.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "film"),
selectedImage: UIImage(systemName: "film.fill")
)
movies.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "film"),
selectedImage: UIImage(systemName: "film.fill")
)

let signIn = UIHostingController(
rootView: NavigationView {
return Widget(store: SignIn.ViewModel(), content: SignInView.init)
.navigationBarTitle(Text("Sign In"))
}
)
let signIn = UIHostingController(
rootView: NavigationView {
SignInView(store: SignIn.ViewModel())
.navigationBarTitle(Text("Sign In"))
}
)

signIn.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "person"),
selectedImage: UIImage(systemName: "person.fill")
)
signIn.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "person"),
selectedImage: UIImage(systemName: "person.fill")
)

let trafficLight = UIHostingController(
rootView: NavigationView {
return Widget(store: TrafficLight.ViewModel(), content: TrafficLightView.init)
.navigationBarTitle(Text("Traffic Light"))
}
)
let trafficLight = UIHostingController(
rootView: NavigationView {
TrafficLightView(store: TrafficLight.ViewModel())
.navigationBarTitle(Text("Traffic Light"))
}
)

trafficLight.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "tortoise"),
selectedImage: UIImage(systemName: "tortoise.fill")
)
trafficLight.tabBarItem = UITabBarItem(
title: nil,
image: UIImage(systemName: "tortoise"),
selectedImage: UIImage(systemName: "tortoise.fill")
)

tabbarController.viewControllers = [counter, movies, signIn, trafficLight]
tabbarController.viewControllers = [counter, movies, signIn, trafficLight]

return tabbarController
}
return tabbarController
}
}
Loading

0 comments on commit 31083d2

Please sign in to comment.