From e42de502a14442204269d1ae46285bb12ace7e33 Mon Sep 17 00:00:00 2001 From: Mohammed Rokon Uddin Date: Fri, 16 Feb 2024 11:34:18 +0600 Subject: [PATCH] chore: update template and drop version for iOS 15 --- README.md | 17 +- TCA.xctemplate/TemplateInfo.plist | 4 +- .../___FILEBASENAME___Feature.swift | 70 +++--- .../___FILEBASENAME___View.swift | 25 ++- .../Sources/Authentication/R.generated.swift | 39 +++- .../Common/Package.swift | 2 +- .../Sources/Common/FeatureReducer.swift | 32 +++ .../Domain/Package.swift | 2 +- .../Features/Package.swift | 2 +- .../Features/Sources/App/AppFeature.swift | 211 +++++++++--------- .../Features/Sources/App/AppView.swift | 136 +++++------ .../Sources/Counter/CounterFeature.swift | 88 ++++---- .../Sources/Counter/CounterView.swift | 82 +++---- .../NetworkPlatform/Package.swift | 2 +- .../PersistentPlatform/Package.swift | 2 +- .../PreparePersistentRepository.swift | 1 - .../Utilities/Package.swift | 2 +- .../project.pbxproj | 6 + 18 files changed, 394 insertions(+), 329 deletions(-) diff --git a/README.md b/README.md index 9844844..29535b9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## iOS Project Template for SwiftUI -[![IDE](https://img.shields.io/badge/Xcode-14-blue.svg)](https://developer.apple.com/xcode/) -[![Language](https://img.shields.io/badge/swift-5.5-orange.svg)](https://swift.org) -[![Platform](https://img.shields.io/badge/iOS-15-green.svg)](https://developer.apple.com/ios/) +[![IDE](https://img.shields.io/badge/Xcode-15-blue.svg)](https://developer.apple.com/xcode/) +[![Language](https://img.shields.io/badge/swift-5.9-orange.svg)](https://swift.org) +[![Platform](https://img.shields.io/badge/iOS-16-green.svg)](https://developer.apple.com/ios/) [![Build Status](https://github.com/monstar-lab-oss/swiftui-template-tca/actions/workflows/build.yml/badge.svg)](https://github.com/monstar-lab-oss/swiftui-template-tca/actions/workflows/build.yml) @@ -18,14 +18,11 @@ This template will save those hours and help to follow standard project architec * [R.swift](https://github.com/mac-cain13/R.swift) Get strong typed, autocompleted resources like images, fonts and segues in Swift projects * [Standard gitignore](https://github.com/github/gitignore/blob/master/Swift.gitignore) * [Moya](https://github.com/Moya/Moya) for netwoking layer -* [Swiftlint](https://github.com/realm/SwiftLint) [SwiftLint SPM Plugin showing build error] -* [Swinject](https://github.com/Swinject/Swinject) [Swinject SPM Plugin showing build error] -* Development/Staging/Production app flavours +* [Swift-Format](https://github.com/apple/swift-format) [For doing code formatting transformations] +* Development, Staging and Production app flavours * Separate build configuration for each flavour ### Todo -* Database Platform -* Persistency Platform * Base classes for handling deeplink, notifications and multiple scheme ### Supporting Tools @@ -72,8 +69,8 @@ Please refer to [Contributing Guidelines](https://github.com/monstar-lab-oss/swi ## Acknowledgments -* [iOS project best practices and tools](https://medium.com/@piotr.gorzelany/ios-project-best-practices-and-tools-c46135b8116d) -* [Development/Staging/Production Configs in Xcode](https://medium.com/better-programming/how-to-create-development-staging-and-production-configs-in-xcode-ec58b2cc1df4) +* [iOS Project Best Practices and Tools](https://medium.com/@piotr.gorzelany/ios-project-best-practices-and-tools-c46135b8116d) +* [Development, Staging and Production Configs in Xcode](https://medium.com/better-programming/how-to-create-development-staging-and-production-configs-in-xcode-ec58b2cc1df4) * [iOS Build Management using Custom Build Scheme](https://www.talentica.com/blogs/ios-build-management-using-custom-build-scheme/) ## 👥 Credits diff --git a/TCA.xctemplate/TemplateInfo.plist b/TCA.xctemplate/TemplateInfo.plist index a93c292..a3bcf19 100755 --- a/TCA.xctemplate/TemplateInfo.plist +++ b/TCA.xctemplate/TemplateInfo.plist @@ -2,6 +2,8 @@ + SupportsSwiftPackage + DefaultCompletionName File Summary @@ -63,8 +65,6 @@ static - SupportsSwiftPackage - SortOrder 7 diff --git a/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___Feature.swift b/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___Feature.swift index 88f7730..eb1fb68 100755 --- a/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___Feature.swift +++ b/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___Feature.swift @@ -11,56 +11,60 @@ import ComposableArchitecture import Domain import Foundation -public struct ___VARIABLE_moduleName___Feature: Reducer { +public struct ___VARIABLE_moduleName___Feature: FeatureReducer { - public struct State: Equatable { + public init() {} + + @ObservableState + public struct State: Equatable, Hashable { public init() {} } - public enum Action: BaseAction { + public enum ViewAction { - enum ViewAction: Equatable { - case onAppear + } - } + public enum InternalAction { - enum InlyingAction: Equatable { + } - } + public var body: some ReducerOf { - enum DelegateAction: Equatable { + } - } + public func reduce(into state: inout State, viewAction: ViewAction) -> Effect { + switch viewAction { - case view(ViewAction) - case inlying(InlyingAction) - case delegate(DelegateAction) + } } - public func reduce(into state: inout State, action: Action) -> Effect { - switch action { - case .view(let action): - switch action { - case .onAppear: - return .none + public func reduce(into state: inout State, presentedAction: Destination.Action) -> Effect { - } - case .inlying(let action): - switch action { + } - } - case .delegate(let action): - switch action { + public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { + switch internalAction { - } } } - // Remove commented code if not needed - // public var body: some Reducer { - // - // Reduce { state, action in - // - // } - // } + public struct Destination: DestinationReducer { + + public init() {} + + @dynamicMemberLookup + @CasePathable + public enum State: Hashable { + + } + + @CasePathable + public enum Action { + + } + + public var body: some ReducerOf { + + } + } } diff --git a/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___View.swift b/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___View.swift index bcc2715..e5c6efe 100755 --- a/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___View.swift +++ b/TCA.xctemplate/___FILEBASENAME___/___FILEBASENAME___View.swift @@ -6,24 +6,25 @@ //___COPYRIGHT___ // +import SwiftUI import Commons -import ComposableArchitecture import Resources -import SwiftUI +import ComposableArchitecture public struct ___VARIABLE_moduleName___View: View { - let store: StoreOf<___VARIABLE_moduleName___Feature> + let store: StoreOf<___VARIABLE_moduleName___Feature> - public init(store: StoreOf<___VARIABLE_moduleName___Feature>) { - self.store = store - } + public init(store: StoreOf<___VARIABLE_moduleName___Feature>) { + self.store = store + } - public var body: some View { - WithViewStore(self.store, observe: { $0 }) { viewStore in - Text("Hello World!!!") - .onAppear { - viewStore.send(.onAppear) + public var body: some View { + WithPerceptionTracking { + Text("Hello World!!!") + .onAppear { +// Just for example +// store.send(.onAppear) + } } } - } } diff --git a/{{cookiecutter.app_name}}/ApplicationModules/Sources/Authentication/R.generated.swift b/{{cookiecutter.app_name}}/ApplicationModules/Sources/Authentication/R.generated.swift index 730155a..ceb79ef 100644 --- a/{{cookiecutter.app_name}}/ApplicationModules/Sources/Authentication/R.generated.swift +++ b/{{cookiecutter.app_name}}/ApplicationModules/Sources/Authentication/R.generated.swift @@ -10,7 +10,7 @@ let R = _R(bundle: Bundle.module) struct _R { let bundle: Foundation.Bundle - var color:color { .init(bundle: bundle) } + var color: color { .init(bundle: bundle) } var image: image { .init(bundle: bundle) } func color(bundle: Foundation.Bundle) -> color { @@ -23,19 +23,24 @@ struct _R { } - /// This `_R.color` struct is generated, and contains static references to 3 colors. struct color { let bundle: Foundation.Bundle /// Color `BgColor`. - var bgColor: ColorResource { .init(name: "BgColor", path: [], bundle: bundle) } + var bgColor: ColorResource { + .init(name: "BgColor", path: [], bundle: bundle) + } /// Color `PrimaryColor`. - var primaryColor: ColorResource { .init(name: "PrimaryColor", path: [], bundle: bundle) } + var primaryColor: ColorResource { + .init(name: "PrimaryColor", path: [], bundle: bundle) + } /// Color `TitleTextColor`. - var titleTextColor: ColorResource { .init(name: "TitleTextColor", path: [], bundle: bundle) } + var titleTextColor: ColorResource { + .init(name: "TitleTextColor", path: [], bundle: bundle) + } } /// This `_R.image` struct is generated, and contains static references to 4 images. @@ -43,15 +48,31 @@ struct _R { let bundle: Foundation.Bundle /// Image `apple`. - var apple: ImageResource { .init(name: "apple", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) } + var apple: ImageResource { + .init( + name: "apple", path: [], bundle: bundle, locale: nil, + onDemandResourceTags: nil) + } /// Image `fork_icon`. - var fork_icon: ImageResource { .init(name: "fork_icon", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) } + var fork_icon: ImageResource { + .init( + name: "fork_icon", path: [], bundle: bundle, locale: nil, + onDemandResourceTags: nil) + } /// Image `google`. - var google: ImageResource { .init(name: "google", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) } + var google: ImageResource { + .init( + name: "google", path: [], bundle: bundle, locale: nil, + onDemandResourceTags: nil) + } /// Image `onboard`. - var onboard: ImageResource { .init(name: "onboard", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) } + var onboard: ImageResource { + .init( + name: "onboard", path: [], bundle: bundle, locale: nil, + onDemandResourceTags: nil) + } } } diff --git a/{{cookiecutter.app_name}}/Common/Package.swift b/{{cookiecutter.app_name}}/Common/Package.swift index 7943d5d..a639050 100644 --- a/{{cookiecutter.app_name}}/Common/Package.swift +++ b/{{cookiecutter.app_name}}/Common/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "Common", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ .library( name: "Common", diff --git a/{{cookiecutter.app_name}}/Common/Sources/Common/FeatureReducer.swift b/{{cookiecutter.app_name}}/Common/Sources/Common/FeatureReducer.swift index 524be65..6ba1019 100644 --- a/{{cookiecutter.app_name}}/Common/Sources/Common/FeatureReducer.swift +++ b/{{cookiecutter.app_name}}/Common/Sources/Common/FeatureReducer.swift @@ -116,3 +116,35 @@ public enum EmptyDestination: DestinationReducer { Action > { .none } } + +extension FeatureReducer { + + public func delayedMediumEffect(internal internalAction: InternalAction) + -> Effect + { + self.delayedMediumEffect(for: .internal(internalAction)) + } + + public func delayedMediumEffect( + for action: Action + ) -> Effect { + delayedEffect(delay: .seconds(0.6), for: action) + } + + public func delayedShortEffect( + for action: Action + ) -> Effect { + delayedEffect(delay: .seconds(0.3), for: action) + } + + private func delayedEffect( + delay: Duration, + for action: Action + ) -> Effect { + @Dependency(\.continuousClock) var clock + return .run { send in + try await clock.sleep(for: delay) + await send(action) + } + } +} diff --git a/{{cookiecutter.app_name}}/Domain/Package.swift b/{{cookiecutter.app_name}}/Domain/Package.swift index 6d24114..e0e75c7 100644 --- a/{{cookiecutter.app_name}}/Domain/Package.swift +++ b/{{cookiecutter.app_name}}/Domain/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "Domain", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ .library( name: "Domain", diff --git a/{{cookiecutter.app_name}}/Features/Package.swift b/{{cookiecutter.app_name}}/Features/Package.swift index b794385..250a4d0 100644 --- a/{{cookiecutter.app_name}}/Features/Package.swift +++ b/{{cookiecutter.app_name}}/Features/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "Features", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ .library( name: "App", diff --git a/{{cookiecutter.app_name}}/Features/Sources/App/AppFeature.swift b/{{cookiecutter.app_name}}/Features/Sources/App/AppFeature.swift index c6f8c81..96c0235 100644 --- a/{{cookiecutter.app_name}}/Features/Sources/App/AppFeature.swift +++ b/{{cookiecutter.app_name}}/Features/Sources/App/AppFeature.swift @@ -13,125 +13,128 @@ import Domain public struct AppFeature: FeatureReducer { - @Dependency(\.appClient) var appClient - - public init() {} - - @ObservableState - public struct State: Equatable, Hashable { - public init() {} + @Dependency(\.appClient) var appClient - @Presents var destination: Destination.State? - var product: Product? - } - - public enum ViewAction { - case onAppear - case showSheet - case showFullScreenCover - case save - } + public init() {} - public enum InternalAction { - case dismissDestination - case productResponse(Result) - } + @ObservableState + public struct State: Equatable, Hashable { + public init() {} - public var body: some ReducerOf { - Reduce(core) - .ifLet(\.$destination, action: \.destination) { - Destination() - } - } + @Presents var destination: Destination.State? + var product: Product? + } + + public enum ViewAction { + case onAppear + case showSheet + case showFullScreenCover + case save + } + + public enum InternalAction { + case dismissDestination + case productResponse(Result) + } + + public var body: some ReducerOf { + Reduce(core) + .ifLet(\.$destination, action: \.destination) { + Destination() + } + } + + public func reduce(into state: inout State, viewAction: ViewAction) -> Effect< + Action + > { + switch viewAction { + case .onAppear: + return .run { send in + await appClient.prepare(Void()) + await send( + .internal( + .productResponse( + Result { + try await appClient.product(1) + }))) + } + case .showSheet: + state.destination = .sheet(.init()) + return .none + + case .showFullScreenCover: + state.destination = .fullScreenCover(.init()) + return .none + + case .save: + return .run { [product = state.product] send in + do { + try await appClient.save(product!) + } catch { - public func reduce(into state: inout State, viewAction: ViewAction) -> Effect< - Action - > { - switch viewAction { - case .onAppear: - return .run { send in - await appClient.prepare(Void()) - await send( - .internal( - .productResponse( - Result { - try await appClient.product(1) - }))) - } - case .showSheet: - state.destination = .sheet(.init()) - return .none - - case .showFullScreenCover: - state.destination = .fullScreenCover(.init()) - return .none - - case .save: - return .run { [product = state.product] send in - do { - try await appClient.save(product!) - } catch { - - } - } } + } } + } - public func reduce( - into state: inout State, presentedAction: Destination.Action - ) -> Effect { - switch presentedAction { - case .sheet(.delegate(.close)): - return .send(.internal(.dismissDestination)) + public func reduce( + into state: inout State, presentedAction: Destination.Action + ) -> Effect { + switch presentedAction { + case .sheet(.delegate(.close)): + return .send(.internal(.dismissDestination)) - case .fullScreenCover(.delegate(.close)): - return .send(.internal(.dismissDestination)) + case .fullScreenCover(.delegate(.close)): + return .send(.internal(.dismissDestination)) - default: - return .none - } + default: + return .none } - - public func reduce(into state: inout State, internalAction: InternalAction) - -> Effect - { - switch internalAction { - case let .productResponse(.success(product)): - state.product = product - return .none - case let .productResponse(.failure(error)): - print(error) - return .none - case .dismissDestination: - state.destination = nil - return .none - } + } + + public func reduce(into state: inout State, internalAction: InternalAction) + -> Effect + { + switch internalAction { + case let .productResponse(.success(product)): + state.product = product + return .none + case let .productResponse(.failure(error)) where error is AppError: + print(error) + return .none + case let .productResponse(.failure(error)): + print(error) + return .none + case .dismissDestination: + state.destination = nil + return .none } + } - public struct Destination: DestinationReducer { + public struct Destination: DestinationReducer { - public init() {} + public init() {} - @dynamicMemberLookup - @CasePathable - public enum State: Hashable { - case sheet(Counter.State) - case fullScreenCover(Counter.State) - } + @dynamicMemberLookup + @CasePathable + public enum State: Hashable { + case sheet(Counter.State) + case fullScreenCover(Counter.State) + } - @CasePathable - public enum Action { - case sheet(Counter.Action) - case fullScreenCover(Counter.Action) - } + @CasePathable + public enum Action { + case sheet(Counter.Action) + case fullScreenCover(Counter.Action) + } - public var body: some ReducerOf { - Scope(state: \.sheet, action: \.sheet) { - Counter() - } - Scope(state: \.fullScreenCover, action: \.fullScreenCover) { - Counter() - } - } + public var body: some ReducerOf { + Scope(state: \.sheet, action: \.sheet) { + Counter() + } + Scope(state: \.fullScreenCover, action: \.fullScreenCover) { + Counter() + } } + } } diff --git a/{{cookiecutter.app_name}}/Features/Sources/App/AppView.swift b/{{cookiecutter.app_name}}/Features/Sources/App/AppView.swift index fd040d2..9d9258a 100644 --- a/{{cookiecutter.app_name}}/Features/Sources/App/AppView.swift +++ b/{{cookiecutter.app_name}}/Features/Sources/App/AppView.swift @@ -13,94 +13,96 @@ import SwiftUI @MainActor public struct AppView: View { - let store: StoreOf + let store: StoreOf - public init(store: StoreOf) { - self.store = store - } + public init(store: StoreOf) { + self.store = store + } - public var body: some View { - WithPerceptionTracking { - VStack { - VStack { - Text("\(store.product?.title ?? "Unknown")") - Spacer() - .frame(height: 20) - Text("\(store.product?.description ?? "Unknown")") - } - .padding() + public var body: some View { + WithPerceptionTracking { + VStack { + VStack { + Text("\(store.product?.title ?? "Unknown")") + Spacer() + .frame(height: 20) + Text("\(store.product?.description ?? "Unknown")") + } + .padding() - Form { - Button("Save") { - store.send(.view(.save)) - } + Form { + Button("Save") { + store.send(.view(.save)) + } - Button { - store.send(.view(.showSheet)) - } label: { - Text("Sheet") - } + Button { + store.send(.view(.showSheet)) + } label: { + Text("Sheet") + } - Button { - store.send(.view(.showFullScreenCover)) - } label: { - Text("Full Screen Cover") - } - } - } - .onAppear { - store.send(.view(.onAppear)) - } - .destinations(with: store) + Button { + store.send(.view(.showFullScreenCover)) + } label: { + Text("Full Screen Cover") + } } + } + .onAppear { + store.send(.view(.onAppear)) + } + .destinations(with: store) } + } } extension StoreOf { - fileprivate var bindableDestination: ComposableArchitecture.Bindable> { - return ComposableArchitecture.Bindable(self) - } + fileprivate var bindableDestination: + ComposableArchitecture.Bindable> + { + return ComposableArchitecture.Bindable(self) + } } @MainActor extension View { - fileprivate func destinations(with store: StoreOf) -> some View { - let bindableDestination = store.bindableDestination - return showSheet(with: bindableDestination) - .showFulllScreenCover(with: bindableDestination) - } + fileprivate func destinations(with store: StoreOf) -> some View { + let bindableDestination = store.bindableDestination + return showSheet(with: bindableDestination) + .showFulllScreenCover(with: bindableDestination) + } - private func showSheet( - with destinationStore: ComposableArchitecture.Bindable> - ) -> some View { - let destinationStore = destinationStore.scope( - state: \.destination?.sheet, - action: \.destination.sheet) + private func showSheet( + with destinationStore: ComposableArchitecture.Bindable> + ) -> some View { + let destinationStore = destinationStore.scope( + state: \.destination?.sheet, + action: \.destination.sheet) - return sheet(item: destinationStore) { store in - CounterView(store: store) - } + return sheet(item: destinationStore) { store in + CounterView(store: store) } + } - private func showFulllScreenCover( - with destinationStore: ComposableArchitecture.Bindable> - ) -> some View { - let destinationStore = destinationStore.scope( - state: \.destination?.fullScreenCover, - action: \.destination.fullScreenCover) + private func showFulllScreenCover( + with destinationStore: ComposableArchitecture.Bindable> + ) -> some View { + let destinationStore = destinationStore.scope( + state: \.destination?.fullScreenCover, + action: \.destination.fullScreenCover) - return fullScreenCover(item: destinationStore) { store in - CounterView(store: store) - } + return fullScreenCover(item: destinationStore) { store in + CounterView(store: store) } + } } #Preview { - AppView( - store: - .init( - initialState: AppFeature.State(), - reducer: { AppFeature() } - ) - ) + AppView( + store: + .init( + initialState: AppFeature.State(), + reducer: { AppFeature() } + ) + ) } diff --git a/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterFeature.swift b/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterFeature.swift index f5d1631..1ad7113 100644 --- a/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterFeature.swift +++ b/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterFeature.swift @@ -12,52 +12,52 @@ import Foundation public struct Counter: FeatureReducer { - public init() {} - - @ObservableState - public struct State: Equatable, Hashable { - public init() {} - - var count = 0 - } - - public enum ViewAction { - case decrementButtonTapped - case incrementButtonTapped - case closeButtonTapped - } + public init() {} - public enum InternalAction { - case close - } - - public enum DelegateAction { - case close - } + @ObservableState + public struct State: Equatable, Hashable { + public init() {} - public func reduce(into state: inout State, viewAction: ViewAction) -> Effect< - Action - > { - switch viewAction { - case .decrementButtonTapped: - state.count -= 1 - return .none - - case .incrementButtonTapped: - state.count += 1 - return .none - - case .closeButtonTapped: - return .send(.internal(.close)) - } + var count = 0 + } + + public enum ViewAction { + case decrementButtonTapped + case incrementButtonTapped + case closeButtonTapped + } + + public enum InternalAction { + case close + } + + public enum DelegateAction { + case close + } + + public func reduce(into state: inout State, viewAction: ViewAction) -> Effect< + Action + > { + switch viewAction { + case .decrementButtonTapped: + state.count -= 1 + return .none + + case .incrementButtonTapped: + state.count += 1 + return .none + + case .closeButtonTapped: + return .send(.internal(.close)) } - - public func reduce(into state: inout State, internalAction: InternalAction) - -> Effect - { - switch internalAction { - case .close: - return .send(.delegate(.close)) - } + } + + public func reduce(into state: inout State, internalAction: InternalAction) + -> Effect + { + switch internalAction { + case .close: + return .send(.delegate(.close)) } + } } diff --git a/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterView.swift b/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterView.swift index 9fcf5a5..0b54e93 100644 --- a/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterView.swift +++ b/{{cookiecutter.app_name}}/Features/Sources/Counter/CounterView.swift @@ -12,51 +12,51 @@ import SwiftUI @MainActor public struct CounterView: View { - let store: StoreOf - - public init(store: StoreOf) { - self.store = store - } + let store: StoreOf + + public init(store: StoreOf) { + self.store = store + } + + public var body: some View { + WithPerceptionTracking { + VStack(spacing: 16) { + HStack { + Button { + store.send(.view(.decrementButtonTapped)) + } label: { + Image(systemName: "minus") + } + + Text("\(store.count)") + .monospacedDigit() + + Button { + store.send(.view(.incrementButtonTapped)) + } label: { + Image(systemName: "plus") + } + } - public var body: some View { - WithPerceptionTracking { - VStack(spacing: 16) { - HStack { - Button { - store.send(.view(.decrementButtonTapped)) - } label: { - Image(systemName: "minus") - } - - Text("\(store.count)") - .monospacedDigit() - - Button { - store.send(.view(.incrementButtonTapped)) - } label: { - Image(systemName: "plus") - } - } - - Button { - store.send(.view(.closeButtonTapped)) - } label: { - Text("Dismiss") - .foregroundStyle(.white) - .frame(width: 120, height: 40) - .background(.blue) - } - } + Button { + store.send(.view(.closeButtonTapped)) + } label: { + Text("Dismiss") + .foregroundStyle(.white) + .frame(width: 120, height: 40) + .background(.blue) } + } } + } } #Preview { - CounterView( - store: - .init( - initialState: Counter.State(), - reducer: { Counter() } - ) - ) + CounterView( + store: + .init( + initialState: Counter.State(), + reducer: { Counter() } + ) + ) } diff --git a/{{cookiecutter.app_name}}/NetworkPlatform/Package.swift b/{{cookiecutter.app_name}}/NetworkPlatform/Package.swift index 2ced42d..085fc49 100644 --- a/{{cookiecutter.app_name}}/NetworkPlatform/Package.swift +++ b/{{cookiecutter.app_name}}/NetworkPlatform/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "NetworkPlatform", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ .library( name: "NetworkPlatform", diff --git a/{{cookiecutter.app_name}}/PersistentPlatform/Package.swift b/{{cookiecutter.app_name}}/PersistentPlatform/Package.swift index c8aecd2..1219842 100644 --- a/{{cookiecutter.app_name}}/PersistentPlatform/Package.swift +++ b/{{cookiecutter.app_name}}/PersistentPlatform/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "PersistentPlatform", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .library( diff --git a/{{cookiecutter.app_name}}/PersistentPlatform/Sources/PersistentPlatform/Repository/PreparePersistentRepository.swift b/{{cookiecutter.app_name}}/PersistentPlatform/Sources/PersistentPlatform/Repository/PreparePersistentRepository.swift index 0366619..fbabf4a 100644 --- a/{{cookiecutter.app_name}}/PersistentPlatform/Sources/PersistentPlatform/Repository/PreparePersistentRepository.swift +++ b/{{cookiecutter.app_name}}/PersistentPlatform/Sources/PersistentPlatform/Repository/PreparePersistentRepository.swift @@ -30,4 +30,3 @@ extension PreparePersistentRepository { public static var live = PreparePersistentRepository( persistenceController: PersistenceController.shared) } - diff --git a/{{cookiecutter.app_name}}/Utilities/Package.swift b/{{cookiecutter.app_name}}/Utilities/Package.swift index c642d3a..c549631 100644 --- a/{{cookiecutter.app_name}}/Utilities/Package.swift +++ b/{{cookiecutter.app_name}}/Utilities/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "Utilities", - platforms: [.macOS(.v12), .iOS(.v15)], + platforms: [.macOS(.v12), .iOS(.v16)], products: [ .library( name: "Utilities", diff --git a/{{cookiecutter.app_name}}/{{cookiecutter.app_name}}.xcodeproj/project.pbxproj b/{{cookiecutter.app_name}}/{{cookiecutter.app_name}}.xcodeproj/project.pbxproj index 97f4ebd..e4de207 100644 --- a/{{cookiecutter.app_name}}/{{cookiecutter.app_name}}.xcodeproj/project.pbxproj +++ b/{{cookiecutter.app_name}}/{{cookiecutter.app_name}}.xcodeproj/project.pbxproj @@ -516,6 +516,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -657,6 +658,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -798,6 +800,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -933,6 +936,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1068,6 +1072,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1203,6 +1208,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks",