Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Example/Example/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}()

navigationController.viewControllers = [
FirstView(viewModel: FirstViewModel()).viewController,
FirstView(stateView: .init()).viewController,
NumberingView(viewModel: .init()).viewController,
NumberingView(viewModel: .init()).viewController
]
Expand Down
14 changes: 5 additions & 9 deletions Example/Example/View/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,32 @@ import ControllerableViewModel

import SwiftUI

final class FirstViewModel: NavigationableViewModel {

}

struct FirstView: ControllerableView {

@ObservedObject var viewModel: FirstViewModel
var stateView: StateView

var body: some View {
VStack(spacing: 30) {
Button(action: {
viewModel.push(view: NumberingView(viewModel: .init()))
self.push(view: NumberingView(viewModel: .init()))
}) {
Text("Push")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()))
self.present(view: NumberingView(viewModel: .init()))
}) {
Text("Default Present")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()), to: .fullScreen, by: .coverVertical)
self.present(view: NumberingView(viewModel: .init()), to: .fullScreen, by: .coverVertical)
}) {
Text("Full Screen")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()), to: .custom, by: .coverVertical, with: [.large(), .medium()])
self.present(view: NumberingView(viewModel: .init()), to: .custom, by: .coverVertical, with: [.large(), .medium()])
}) {
Text("Changable Modal")
}
Expand Down
32 changes: 10 additions & 22 deletions Example/Example/View/CustomAlertView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,16 @@ import ControllerableViewModel

import SwiftUI

final class CustomeAlertViewModel: NavigationableViewModel {

struct Item {
let title: String
let message: String
let completion: () -> Void
}

let item: Item

init(item: Item) {
self.item = item
}

var title: String { item.title }
var message: String { item.message }
var completion: () -> Void { return item.completion }
struct AlertItem {
let title: String
let message: String
let completion: () -> Void
}

struct CustomAlert: ControllerableView {

@ObservedObject var viewModel: CustomeAlertViewModel
var stateView: StateView
let item : AlertItem

var body: some View {
ZStack {
Expand All @@ -39,19 +27,19 @@ struct CustomAlert: ControllerableView {
.ignoresSafeArea(.all)
VStack(alignment: .center, spacing: 0) {
Spacer()
Text(viewModel.title)
Text(item.title)
Spacer()
.frame(height: 11)
Text(viewModel.message)
Text(item.message)
.foregroundColor(.gray)
Spacer()
Divider()
.padding(0)
Spacer()
Button(
action: {
viewModel.dismiss()
viewModel.completion()
self.dismiss()
item.completion()
}, label: {
HStack {
Spacer()
Expand Down
48 changes: 23 additions & 25 deletions Example/Example/View/NumberingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ import ControllerableViewModel

import SwiftUI

final class NumberingViewModel: NavigationableViewModel {
final class NumberingViewModel: ObservableObject {
static var number: Int = 0

let number: Int

override init() {
init() {
self.number = Self.number

super.init()


Self.number += 1

print("init \(number)")
Expand All @@ -32,6 +30,8 @@ final class NumberingViewModel: NavigationableViewModel {

struct NumberingView: ControllerableView {

var stateView: StateView = .init()

@ObservedObject var viewModel: NumberingViewModel

var body: some View {
Expand All @@ -40,67 +40,65 @@ struct NumberingView: ControllerableView {
Text("Number \(viewModel.number)")

Button(action: {
viewModel.push(view: NumberingView(viewModel: .init()))
self.push(view: NumberingView(viewModel: .init()))
}) {
Text("push")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()))
self.present(view: NumberingView(viewModel: .init()))
}) {
Text("Default Present")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()), to: .fullScreen, by: .coverVertical)
self.present(view: NumberingView(viewModel: .init()), to: .fullScreen, by: .coverVertical)
}) {
Text("Full Screen")
}

Button(action: {
viewModel.present(view: NumberingView(viewModel: .init()), to: .custom, by: .coverVertical, with: [.large(), .medium()])
self.present(view: NumberingView(viewModel: .init()), to: .custom, by: .coverVertical, with: [.large(), .medium()])
}) {
Text("Changable Modal")
}

Button(action: {
viewModel.dismiss()
self.dismiss()
}) {
Text("dismiss")
}

Button(action: {
viewModel.pop()
self.pop()
}) {
Text("pop")
}

Button(action: {
viewModel.popToRoot()
self.popToRoot()
}) {
Text("pop to root")
}

Button(action: {
viewModel.popToRoot()
viewModel.push(view: NumberingView(viewModel: .init()))
viewModel.push(view: NumberingView(viewModel: .init()))
self.popToRoot()
self.push(view: NumberingView(viewModel: .init()))
self.push(view: NumberingView(viewModel: .init()))
}) {
Text("reStacks")
}

Button(action: {
let viewModel = CustomeAlertViewModel(
item: .init(
title: "SwiftUI 로 구현된 Alert 예제",
message: "UIKit 으로도 구현가능\n여기는 View Number \(viewModel.number)",
completion: {
print("얼럿 Completion")
}
)
let alertItem = AlertItem(
title: "SwiftUI 로 구현된 Alert 예제",
message: "UIKit 으로도 구현가능\n여기는 View Number \(viewModel.number)",
completion: {
print("얼럿 Completion")
}
)
let view = CustomAlert(viewModel: viewModel)
viewModel.alert(view: view)
let view = CustomAlert(stateView: .init(), item: alertItem)
self.presentAlert(view: view)
}) {
Text("alert")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
//
// NavigationableViewModel.swift
// File.swift
//
//
//
// Created by 김용우 on 2023/10/17.
// Created by 김용우 on 2023/10/19.
//

import SwiftUI

open class NavigationableViewModel: ObservableObject {
public weak var viewController: UIViewController?
public extension ControllerableView {

public init() {}
}

// MARK: - Navigation
@MainActor
extension NavigationableViewModel {
var viewController: UIViewController {
let viewController = HostingController(rootView: self)
self.stateView.viewController = viewController
return viewController
}

// MARK: ViewController Life Cycle
func loadView() {}
func viewDidLoad() {}
func viewWillAppear() {}
func viewDidAppear() {}
func viewWillDisappear() {}
func viewDidDisappear() {}

public func push(view: some ControllerableView) {
viewController?.navigationController?.pushViewController(view.viewController, animated: true)
// MARK: Navigation
func push(view: some ControllerableView) {
stateView.viewController?.navigationController?.pushViewController(view.viewController, animated: true)
}

public func pop() {
guard let currentViewController = viewController,
let navigationController = currentViewController.navigationController else { return }
guard navigationController.topViewController == currentViewController else { return }

navigationController.popViewController(animated: true)
func pop() {
stateView.viewController?.navigationController?.popViewController(animated: true)
}

public func present(
func present(
view: some ControllerableView,
to presentationStyle: UIModalPresentationStyle? = nil,
by transitionStyle: UIModalTransitionStyle? = nil,
Expand All @@ -50,22 +53,17 @@ extension NavigationableViewModel {
let presentingViewController = UINavigationController(rootViewController: nextViewController)
presentingViewController.setNavigationBarHidden(true, animated: false)

viewController?.present(presentingViewController, animated: true)
stateView.viewController?.present(presentingViewController, animated: true)
}

public func dismiss() {
viewController?.dismiss(animated: true)
func dismiss() {
stateView.viewController?.dismiss(animated: true)
}

public func popToRoot() {
viewController?.navigationController?.popToRootViewController(animated: true)
func popToRoot() {
stateView.viewController?.navigationController?.popToRootViewController(animated: true)
}

}

@MainActor
extension NavigationableViewModel {

private var window: UIWindow? {
if #available(iOS 16.0, *) {
return UIApplication.shared.connectedScenes
Expand All @@ -77,7 +75,7 @@ extension NavigationableViewModel {
}
}

public func alert(
func presentAlert(
view: some ControllerableView,
to presentationStyle: UIModalPresentationStyle? = .overFullScreen,
by transitionStyle: UIModalTransitionStyle? = .crossDissolve
Expand All @@ -101,5 +99,4 @@ extension NavigationableViewModel {

rootViewController.present(nextViewController, animated: true)
}

}
Loading