Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

difference between "MVVM" and "Flux" #6

Open
wants to merge 21 commits into
base: mvvm
Choose a base branch
from
Open
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
Binary file added Images/Flux/Views.key
Binary file not shown.
Binary file modified Images/favorite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/repository.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/structure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/user_repository.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# iOSDesignPatternSamples (MVVM)
# iOSDesignPatternSamples (Flux)

This is Github user search demo app that made with MVVM design pattern.
This is Github user search demo app that made with Flux design pattern.

## Application Structure

Expand All @@ -13,35 +13,40 @@ Search Github user and show user result list

![](./Images/search.png)

- [SearchViewModel](./iOSDesignPatternSamples/Sources/UI/Search/SearchViewModel.swift)
- [SearchViewDataSource](./iOSDesignPatternSamples/Sources/UI/Search/SearchViewDataSource.swift) <- Adapt UITableViewDataSource and UITableViewDelegate
- [SearchAction](./iOSDesignPatternSamples/Sources/UI/Search/Flux/SearchAction.swift)
- [SearchStore](./iOSDesignPatternSamples/Sources/UI/Search/Flux/SearchStore.swift)

### [FavoriteViewController](./iOSDesignPatternSamples/Sources/UI/Favorite/FavoriteViewController.swift)
Show local on memory favorite repositories

![](./Images/favorite.png)

- [FavoriteViewModel](./iOSDesignPatternSamples/Sources/UI/Favorite/FavoriteViewModel.swift)
- [FavoriteViewDataSource](./iOSDesignPatternSamples/Sources/UI/Favorite/FavoriteViewDataSource.swift) <- Adapt UITableViewDataSource and UITableViewDelegate
- [FavoriteAction](./iOSDesignPatternSamples/Sources/UI/Favorite/Flux/FavoriteAction.swift)
- [FavoriteStore](./iOSDesignPatternSamples/Sources/UI/Favorite/Flux/FavoriteStore.swift)

### [UserRepositoryViewController](./iOSDesignPatternSamples/Sources/UI/UserRepository/UserRepositoryViewController.swift)
Show Github user's repositories

![](./Images/user_repository.png)

- [UserRepositoryViewModel](./iOSDesignPatternSamples/Sources/UI/UserRepository/UserRepositoryViewModel.swift)
- [UserRepositoryViewDataSource](./iOSDesignPatternSamples/Sources/UI/UserRepository/UserRepositoryViewDataSource.swift) <- Adapt UITableViewDataSource and UITableViewDelegate
- [UserRepositoryAction](./iOSDesignPatternSamples/Sources/UI/UserRepository/Flux/UserRepositoryAction.swift)
- [UserRepositoryStore](./iOSDesignPatternSamples/Sources/UI/UserRepository/Flux/UserRepositoryStore.swift)

### [RepositoryViewController](./iOSDesignPatternSamples/Sources/UI/Repository/RepositoryViewController.swift)
Show a repository and add / remove local on memory favorites

![](./Images/repository.png)

- [RepositoryViewModel](./iOSDesignPatternSamples/Sources/UI/Repository/RepositoryViewModel.swift)
- [RepositoryAction](./iOSDesignPatternSamples/Sources/UI/Repository/Flux/RepositoryAction.swift)
- [RepositoryStore](./iOSDesignPatternSamples/Sources/UI/Repository/Flux/RepositoryStore.swift)


## How to add / remove favorites

You can add / remove favorite repositories in RepositoryViewController, but an Array of favorite repository is hold by FavoriteViewController.
You can add / remove favorite repositories in RepositoryViewController. Array of favorite repository is hold by FavoriteModel that injected to each actions, therefore you can use its reference everywhere!

## Run

Expand Down
96 changes: 80 additions & 16 deletions iOSDesignPatternSamples.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

69 changes: 53 additions & 16 deletions iOSDesignPatternSamples/Sources/Common/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,82 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

private let favoriteModel = FavoriteModel()
let favoriteModel = FavoriteModel()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

if let viewControllers = (window?.rootViewController as? UITabBarController)?.viewControllers {
for value in viewControllers.enumerated() {
switch value {
case let (0, nc as UINavigationController):
let repositoryDispatcher = RepositoryDispatcher()
let searchDispatcher = SearchDispatcher()
let userRepositoryDispatcher = UserRepositoryDispatcher()
let searchVC = SearchViewController(
viewModel: SearchViewModel(
action: SearchAction(
notificationCenter: .default,
dispatcher: searchDispatcher,
searchModel: SearchModel(
sendRequest: ApiSession.shared.send
),
notificationCenter: .default
)
),
store: SearchStore(
dispatcher: searchDispatcher
),
makeUserRepositoryViewModel: { [favoriteModel] in
UserRepositoryViewModel(
user: $0,
favoriteModel: favoriteModel,
makeUserRepositoryAction: { user in
UserRepositoryAction(
dispatcher: userRepositoryDispatcher,
repositoryModel: RepositoryModel(
user: $0,
user: user,
sendRequest: ApiSession.shared.send
)
)
},
makeRepositoryViewModel: { [favoriteModel] in
RepositoryViewModel(
repository: $0,
favoritesModel: favoriteModel
makeUserRepositoryStore: { user in
UserRepositoryStore(
user: user,
dispatcher: userRepositoryDispatcher
)
},
makeRepositoryAction: { [favoriteModel] repository in
RepositoryAction(
repository: repository,
dispatcher: repositoryDispatcher,
favoriteModel: favoriteModel
)
},
makeRepositoryStore: { repository in
RepositoryStore(
repository: repository,
dispatcher: repositoryDispatcher
)
}
)
nc.setViewControllers([searchVC], animated: false)

case let (1, nc as UINavigationController):
let favoriteDispatcher = FavoriteDispatcher()
let repositoryDispatcher = RepositoryDispatcher()
let favoriteVC = FavoriteViewController(
viewModel: FavoriteViewModel(favoriteModel: favoriteModel),
makeRepositoryViewModel: { [favoriteModel] in
RepositoryViewModel(repository: $0, favoritesModel: favoriteModel)
action: FavoriteAction(
dispatcher: favoriteDispatcher,
favoriteModel: favoriteModel
),
store: FavoriteStore(
dispatcher: favoriteDispatcher
),
makeRepositoryAction: { [favoriteModel] repository in
RepositoryAction(
repository: repository,
dispatcher: repositoryDispatcher,
favoriteModel: favoriteModel
)
},
makeRepositoryStore: { repository in
RepositoryStore(
repository: repository,
dispatcher: repositoryDispatcher
)
}
)
nc.setViewControllers([favoriteVC], animated: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,27 @@ import UIKit
final class FavoriteViewController: UIViewController {
@IBOutlet private(set) weak var tableView: UITableView!

let viewModel: FavoriteViewModelType
let action: FavoriteActionType
let store: FavoriteStoreType
let dataSource: FavoriteViewDataSource

private let makeRepositoryViewModel: (Repository) -> RepositoryViewModelType
private let makeRepositoryAction: (Repository) -> RepositoryActionType
private let makeRepositoryStore: (Repository) -> RepositoryStoreType
private var cancellables = Set<AnyCancellable>()

init(
viewModel: FavoriteViewModelType,
makeRepositoryViewModel: @escaping (Repository) -> RepositoryViewModelType
action: FavoriteActionType,
store: FavoriteStoreType,
makeRepositoryAction: @escaping (Repository) -> RepositoryActionType,
makeRepositoryStore: @escaping (Repository) -> RepositoryStoreType
) {
self.makeRepositoryViewModel = makeRepositoryViewModel
self.viewModel = viewModel
self.dataSource = FavoriteViewDataSource(viewModel: viewModel)
self.action = action
self.store = store
self.dataSource = FavoriteViewDataSource(
action: action,
store: store
)
self.makeRepositoryAction = makeRepositoryAction
self.makeRepositoryStore = makeRepositoryStore
super.init(nibName: FavoriteViewController.className, bundle: nil)
}

Expand All @@ -37,27 +45,31 @@ final class FavoriteViewController: UIViewController {
super.viewDidLoad()

title = "On Memory Favorite"

dataSource.configure(with: tableView)

viewModel.output.selectedRepository
store.selectedRepository
.receive(on: DispatchQueue.main)
.sink(receiveValue: showRepository)
.store(in: &cancellables)

viewModel.output.relaodData
store.reloadData
.receive(on: DispatchQueue.main)
.sink(receiveValue: reloadData)
.store(in: &cancellables)

action.load()
}

private var showRepository: (Repository) -> Void {
{ [weak self] repository in
guard let me = self else {
return
}
let vm = me.makeRepositoryViewModel(repository)
let vc = RepositoryViewController(viewModel: vm)

let vc = RepositoryViewController(
action: me.makeRepositoryAction(repository),
store: me.makeRepositoryStore(repository)
)
me.navigationController?.pushViewController(vc, animated: true)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,33 @@ import GithubKit
import UIKit

final class FavoriteViewDataSource: NSObject {
private let viewModel: FavoriteViewModelType

init(viewModel: FavoriteViewModelType) {
self.viewModel = viewModel
private let action: FavoriteActionType
private let store: FavoriteStoreType

init(
action: FavoriteActionType,
store: FavoriteStoreType
) {
self.action = action
self.store = store
}

func configure(with tableView: UITableView) {
tableView.dataSource = self
tableView.delegate = self

tableView.register(RepositoryViewCell.self)
}
}

extension FavoriteViewDataSource: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.output.favorites.count
return store.favorites.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeue(RepositoryViewCell.self, for: indexPath)
let repository = viewModel.output.favorites[indexPath.row]
let repository = store.favorites[indexPath.row]
cell.configure(with: repository)
return cell
}
Expand All @@ -41,11 +46,11 @@ extension FavoriteViewDataSource: UITableViewDataSource {
extension FavoriteViewDataSource: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
viewModel.input.selectedIndexPath(indexPath)
action.select(from: store.favorites, for: indexPath)
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let repository = viewModel.output.favorites[indexPath.row]
let repository = store.favorites[indexPath.row]
return RepositoryViewCell.calculateHeight(with: repository, and: tableView)
}
}

This file was deleted.

Loading