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

[Team 6 iOS๐Ÿฅ’ ์ญ & ์žญ์Šจ] MVVM ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•œ MainPage ๊ตฌํ˜„ #38

Merged
merged 72 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
aa3f6c1
chore : initial commit
JacksonPk Apr 20, 2021
d41ef21
feat : add collectionView
JacksonPk Apr 20, 2021
156f287
chore : remove unused code
JacksonPk Apr 20, 2021
0203357
chore : create group to organize files in
JacksonPk Apr 20, 2021
762729f
feat : create delegate and data source for mainViewController
1song2 Apr 20, 2021
ca95da9
feat : create DishCell
1song2 Apr 20, 2021
31d8959
add custom collectionViewCell
JacksonPk Apr 20, 2021
e1bdd0a
feat : register cell to collectionView
1song2 Apr 20, 2021
55848a2
feat : set collectionViewCell size with ratio
JacksonPk Apr 20, 2021
060ee02
feat : set ratio when device is in landscape mode
JacksonPk Apr 21, 2021
ec2592b
feat : add custom header view (#1)
JacksonPk Apr 21, 2021
49b453b
fix : show custom headerView in collectionView (#1)
JacksonPk Apr 21, 2021
910990e
chore : add entity 'Dish'
1song2 Apr 21, 2021
921f2cc
feat : add cornerRadius to image and badge (#4,#6)
JacksonPk Apr 21, 2021
ad1af83
chore : modify leading and trailing constraints
1song2 Apr 22, 2021
aefe7b1
chore : modify constraints
1song2 Apr 22, 2021
8e88fd3
refactor : modify cell item size
1song2 Apr 22, 2021
f497cf0
refactor : replace method willTransition with viewWillLayoutSubviews
1song2 Apr 22, 2021
4230819
chore : remove prototype cell
1song2 Apr 22, 2021
b45787f
refactor : change estimate size option to none
1song2 Apr 22, 2021
7c8bb4d
chore : move .gitignore file into iOS folder
1song2 Apr 22, 2021
9d4ef05
chore : add mock data
1song2 Apr 22, 2021
3c30484
refactor : modify Dish entity and add DishList
1song2 Apr 22, 2021
1ac7f86
feat : add DishesResponseDTO
1song2 Apr 22, 2021
a18b1f4
chore : remove unnecessary code
1song2 Apr 22, 2021
241051a
refactor : replace 'JSONParser' with 'JSONManager'
1song2 Apr 22, 2021
f3c7ecb
chore : add missing description
1song2 Apr 22, 2021
fc680ab
refactor : rename file and add methods to map DTO to Domain
1song2 Apr 22, 2021
cc57906
refactor : convert category to enum
1song2 Apr 22, 2021
9c067c4
feat : add array of DishList to dataSource and update cell using it
1song2 Apr 22, 2021
7b922a2
chore : install Alamofire pod
1song2 Apr 22, 2021
224772d
feat : add NetworkManager to perform request
1song2 Apr 22, 2021
3268b1f
chore : remove unused file and code
1song2 Apr 22, 2021
ba252f2
feat : perform request to update dataSource
1song2 Apr 22, 2021
77f8e26
chore : allow arbitrary loads to load image from HTTP URL
1song2 Apr 22, 2021
f3b4722
feat : get image data from URL
1song2 Apr 22, 2021
9541b3f
refactor : modify trailing constraints
1song2 Apr 22, 2021
4749253
feature : extend String for strikethrough
1song2 Apr 22, 2021
61b3575
refactor : add monetary unit after prices
1song2 Apr 22, 2021
d36f63d
refactor : fix order of catagories
1song2 Apr 23, 2021
305a946
feat : add Toaster by CocoaPods(#17)
JacksonPk Apr 23, 2021
c78a8e6
feat : add toaster for section title
JacksonPk Apr 23, 2021
a22cadb
feat : show count of menus in section
JacksonPk Apr 23, 2021
50d24cc
Merge pull request #19 from rla36/iOS/feat/toast
1song2 Apr 23, 2021
dc57c13
style : format code
1song2 Apr 23, 2021
47fde0f
feat : add DishListItemViewModel
1song2 Apr 23, 2021
460f06e
refactor : rename ViewModel
1song2 Apr 23, 2021
bb2a597
feat : add DishesListViewModel
1song2 Apr 23, 2021
cd289fd
refactor : remove and comment unused code
1song2 Apr 23, 2021
71b7e95
feat : apply view models to code
1song2 Apr 23, 2021
4c0178d
refactor : rename Identifier to reuseIdentifier
1song2 Apr 23, 2021
c457185
perf : get images asynchronously
1song2 Apr 26, 2021
04610f6
feat : add UseCase
1song2 Apr 26, 2021
d3bc8a4
refactor : apply Open-Closed Principle to code(#18)
1song2 Apr 26, 2021
82dec71
chore : Create groups to organize files in
1song2 Apr 26, 2021
b9c2309
refactor : rename MainViewController to MainPageViewController
1song2 Apr 26, 2021
86a4f58
refactor : rename discountPriceLabel to lastPriceLabel
1song2 Apr 26, 2021
3481f90
chore : remove .DS_Store from everywhere
1song2 Apr 26, 2021
5a5ad22
Merge pull request #21 from rla36/iOS/feat/view-model
JacksonPk Apr 26, 2021
b6b87af
chore : choose Info.plist file
1song2 Apr 26, 2021
8e3dec1
Merge branch 'iOS/feat/view-model' into dev-iOS
1song2 Apr 26, 2021
9f0df66
refactor : use method load directly instead of showDishList(#23)
1song2 Apr 27, 2021
381315b
refactor : add method to count number of items
1song2 Apr 27, 2021
db36088
refactor : remove public keywords
1song2 Apr 27, 2021
ddbf449
refactor : remove static keyword(#23)
1song2 Apr 27, 2021
f821230
refactor : remove ViewModel from DishCell
1song2 Apr 27, 2021
7c81402
refactor : change value of Observer type to non-optional
1song2 Apr 27, 2021
2e981ce
refactor : make categorizable and viewModel into arrays(#23)
1song2 Apr 27, 2021
48f2619
refactor : rename DishList to DishSet
1song2 Apr 27, 2021
4b51f52
Merge branch 'iOS/feat/view-model' of https://github.com/rla36/sidediโ€ฆ
1song2 Apr 27, 2021
ef8fb9d
Merge branch 'iOS/feat/view-model' into dev-iOS
1song2 Apr 27, 2021
1319881
refactor : rename DishSet to Dishes
1song2 Apr 27, 2021
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 .DS_Store
Binary file not shown.
92 changes: 92 additions & 0 deletions iOS/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## User settings
xcuserdata/

## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout

## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3

## Obj-C/Swift specific
*.hmap

## App packaging
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm

.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build/

# Accio dependency management
Dependencies/
.accio/

# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/

**/.DS_Store
908 changes: 908 additions & 0 deletions iOS/BanchanCode/BanchanCode.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
10 changes: 10 additions & 0 deletions iOS/BanchanCode/BanchanCode.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
14 changes: 14 additions & 0 deletions iOS/BanchanCode/BanchanCode/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// AppDelegate.swift
// BanchanCode
//
// Created by jinseo park on 4/20/21.
//

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

}

13 changes: 13 additions & 0 deletions iOS/BanchanCode/BanchanCode/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// SceneDelegate.swift
// BanchanCode
//
// Created by jinseo park on 4/20/21.
//

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
}
51 changes: 51 additions & 0 deletions iOS/BanchanCode/BanchanCode/Data/DishesResponseDTO+Mapping.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// DishesResponseDTO+Mapping.swift
// BanchanCode
//
// Created by Song on 2021/04/22.
//

import Foundation

struct DishesResponseDTO: Decodable {
private enum CodingKeys: String, CodingKey {
case dishes
}
let dishes: [DishDTO]
}

extension DishesResponseDTO {
struct DishDTO: Decodable {
private enum CodingKeys: String, CodingKey {
case id
case name
case description
case topImage = "top_image"
case prices
case badges
}
let id: Int
let name: String
let description: String
let topImage: String
let prices: [Int]
let badges: [String]
}
}

extension DishesResponseDTO {
func toDomain() -> DishList {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List ๋ผ๋Š” ํ‘œํ˜„์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ํŠน์ˆ˜ํ•œ ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž๋ฃŒ๊ตฌ์กฐ ์ค‘ ํ•˜๋‚˜์ธ List ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์ง“๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ์š”?(์‹ค์ œ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ List์ธ ๊ฒฝ์šฐ๋ผ๋„ ์ปจํ…Œ์ด๋„ˆ ์œ ํ˜•์„ ์ด๋ฆ„์— ๋„ฃ์ง€ ์•Š๋Š” ํŽธ์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค)

ํด๋ฆฐ์ฝ”๋“œ 2์žฅ ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„ ์ค‘ ๊ทธ๋ฆ‡๋œ ์ •๋ณด๋ฅผ ํ”ผํ•˜๋ผ๋„ ๊ฐ™์€ ๋‚ด์šฉ์ด๋‹ˆ ์ฐธ๊ณ ํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์˜ค ์•„์ง List ํƒ€์ž…์„ ๋งŽ์ด ์‚ฌ์šฉํ•ด๋ณธ ์ ์ด ์—†์–ด์„œ ๊ทธ๋Ÿฐ ์˜๋ฏธ๊ฐ€ ์žˆ์—ˆ๋Š”์ง€ ๋ชฐ๋ž๋„ค์š”. ์•Œ๋ ค์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!
ํด๋ฆฐ์ฝ”๋“œ๋„ ์ฝ์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค :)

return .init(dishes: dishes.map { $0.toDomain() })
}
}

extension DishesResponseDTO.DishDTO {
func toDomain() -> Dish {
return .init(id: id,
name: name,
description: description,
imageURL: topImage,
prices: prices,
badges: badges)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// CollectionViewDataSource.swift
// BanchanCode
//
// Created by Song on 2021/04/20.
//

import UIKit

class MainPageCollectionViewDataSource: NSObject, UICollectionViewDataSource {
var viewModels: [DishesListViewModel]!

func numberOfSections(in collectionView: UICollectionView) -> Int {
return viewModels.count
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModels[section].items.value.count

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ ‘๊ทผ์ด ๋„ˆ๋ฌด ๊นŠ์Šต๋‹ˆ๋‹ค. ๋””๋ฏธํ„ฐ ๋ฒ•์น™์„ ์ง€ํ‚ค๋ฉด ๊ฒฐํ•ฉ๋„๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ์…จ์œผ๋‹ˆ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•ด๋ณด๋Š”๊ฑด ์–ด๋–จ๊นŒ์š”?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋„ต viewModelย ๋‚ด๋ถ€์—์„œ item count๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: DishCell.reuseIdentifier, for: indexPath) as! DishCell
cell.fill(with: viewModels[indexPath.section].items.value[indexPath.row])
return cell
}

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeaderView.reuseIdentifier, for: indexPath) as! SectionHeaderView
headerView.fill(with: viewModels[indexPath.section])
headerView.countOfMenus = viewModels[indexPath.section].items.value.count

return headerView
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// CollectionViewDelegate.swift
// BanchanCode
//
// Created by Song on 2021/04/20.
//

import UIKit

class MainPageCollectionViewDelegate: NSObject, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.size.width - 32.0, height: 130.0)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
let width: CGFloat = collectionView.frame.width
let height: CGFloat = 32.0
return CGSize(width: width, height: height)
}
}
21 changes: 21 additions & 0 deletions iOS/BanchanCode/BanchanCode/Domain/Entities/Dish.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Dish.swift
// BanchanCode
//
// Created by Song on 2021/04/21.
//

import Foundation

struct Dish {
let id: Int
let name: String
let description: String
let imageURL: String
let prices: [Int]
let badges: [String]
}

struct DishList {
var dishes: [Dish]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// FetchDishesUseCase.swift
// BanchanCode
//
// Created by Song on 2021/04/25.
//

import Foundation

protocol FetchDishesUseCase {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • DishesUseCase ๋ผ๊ณ ๋งŒ ํ•ด๋„ ์ถฉ๋ถ„ํ•  ๊ฒƒ ๊ฐ™์•„์š”(๋˜ Fetch๋Š” ๋™์‚ฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ ๋ณผ๋•Œ ๋Š๋‚Œ์ด ๋ฉ”์†Œ๋“œ๊ฐ™๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค).
  • protocol์„ ์ข€ ๋” ๋ฒ”์šฉ์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”? ํ”„๋กœํ† ์ฝœ์„ Dishes ๊ด€๋ จ๋˜์–ด์„œ ์ œํ•œ์ ์œผ๋กœ ์„ค๊ณ„ํ•˜์‹  ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค. ์ข€ ๋” ๋ฒ”์šฉ์ ์œผ๋กœ ๋งŒ๋“ค๋ฉด ์•„๋ž˜์˜ DefaultFetchDishesUseCase ์ด๋ฆ„๋„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๋€” ๊ฒƒ ๊ฐ™์•„์š”.
  • execute์˜ (requestValue: FetchDishesUseCaseRequestValue)๋„ ์ข€ ๋” ๋ฒ”์šฉ์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ œ์•ˆ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
  • execute์˜ requestValue ๊ฐ€ request ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋„ค์š”! ์ด๊ฒƒ๋„ ์ ์ ˆํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(1๋ฒˆ ํ”ผ๋“œ๋ฐฑ) ์˜ค UseCase๋Š” ๊ฐ๊ฐ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์—ญํ• ์ด๋ผ (์ดˆ๊ธฐ๊ฐ’ ์„ธํŒ…, ์•„์ดํ…œ ์ถ”๊ฐ€ ๋“ฑ...) ๋™์‚ฌ์  ํ‘œํ˜„์ด ์ด๋ฆ„์— ํฌํ•จ๋˜์ง€ ์•Š์•„์•ผ ํ• ๊นŒ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ ์˜คํžˆ๋ ค ๋ฉ”์†Œ๋“œ ๊ฐ™์€ ๋Š๋‚Œ์„ ์ฃผ๋Š”๊ตฐ์š”. MVVM์ด๋‚˜ ํด๋ฆฐ ์•„ํ‚คํ…์ฒ˜ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋งŽ์ด ๋ณด์ง„ ๋ชปํ–ˆ์ง€๋งŒ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋™์‚ฌ๋ฅผ ๋„ฃ์–ด ๋„ค์ด๋ฐ ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ณด๊ธด ํ–ˆ๋Š”๋ฐ, ๊ทธ๋ฆฌ ์ผ๋ฐ˜์ ์ธ ์ปจ๋ฒค์…˜์€ ์•„๋‹Œ๊ฑธ๊นŒ์š”?
(2๋ฒˆ, 3๋ฒˆ ํ”ผ๋“œ๋ฐฑ) ์ข€ ๋” ๋ฒ”์šฉ์ ์œผ๋กœ ์ˆ˜์ •ํ•ด ๋‹ค์Œ๋ฒˆ PR์— ๋ฐ˜์˜ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

(4๋ฒˆ ํ”ผ๋“œ๋ฐฑ) execute์˜ requestValue ๊ฐ€ request ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋Š” ํ”ผ๋“œ๋ฐฑ์ด ํ˜น์‹œ FetchDishesUseCaseRequestValue ๊ตฌ์กฐ์ฒด์˜ ์†์„ฑ์ธ categorizable์˜ ์ „์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ทธ ๋‚ด๋ถ€ ์†์„ฑ์ด categorizable .name๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ ์„ ์ง€์ ํ•˜์‹  ๊ฑธ๊นŒ์š”? ๋ง์”€ํ•˜์‹  ์˜๋ฏธ๋ฅผ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜์ง€ ๋ชปํ•ด ๋‹ค์‹œ ํ•œ๋ฒˆ ์—ฌ์ญ™๋‹ˆ๋‹ค๐Ÿ™

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(4๋ฒˆํ”ผ๋“œ๋ฐฑ) ๋„ค๋„ค ๋งž์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์ชฝ์œผ๋กœ requestํ•˜๋Š”๊ฑฐ๋ผ๋ฉด url์ด๋‚˜ Request๋งŒ ํ•„์š”ํ•˜์ง€, category ์ž์ฒด๊ฐ€ ํ•„์š”ํ• ๊ฒƒ ๊ฐ™์ง„ ์•Š์•„์„œ์š”!
๊ทธ๋ฆฌ๊ณ  category๋Š” ๋ชจ๋ธ ๊ฐ์ฒด์˜ ๋Š๋‚Œ์ด ๊ฐ•ํ•œ๋ฐ request ๋ฉ”์†Œ๋“œ์— ์–ด์šธ๋ฆฌ์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด์„œ์š”.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(4๋ฒˆ ํ”ผ๋“œ๋ฐฑ) ํ˜„์žฌ url ๊ตฌ์กฐ๊ฐ€ baseURL/{{category์˜ ์†์„ฑ์ธ name}}์ด๋Ÿฐ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด requestValue๋กœ categorizable์„ ๋‹ด์•„ ๋ณด๋‚ด๊ณ  ์žˆ์—ˆ์—ˆ์Šต๋‹ˆ๋‹ค. (e.g. baseURL/soup)
category ์ž์ฒด๋ฅผ requestํ•˜๋Š” ๊ตฌ์กฐ์—์„œ category์˜ name๋งŒ ์š”์ฒญํ•˜๋Š” ๊ตฌ์กฐ๋กœ ์ˆ˜์ •ํ•ด๋ณด๋ ค ํ•ฉ๋‹ˆ๋‹ค!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(1๋ฒˆ ํ”ผ๋“œ๋ฐฑ) ์•„ ๋„ต, ์ด๊ฑด ์ €๋„ ์ด ๋ ˆํฌ๋ฅผ ๋ณด๋‹ˆ ๊ทธ๋Œ€๋กœ ๋‘ฌ๋„ ๋  ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋„ค์—ฌ.
์ €๋Š” ๋ฉ”์†Œ๋“œ๋Š” ๋™์‚ฌ๋กœ ์‹œ์ž‘ํ•˜๊ณ  ํ”„๋กœํผํ‹ฐ๋Š” ๋ช…์‚ฌ๋กœ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค๋Š” ์ฐจ์›์—์„œ ๋ง์”€๋“œ๋ฆฐ ๊ฑด๋ฐ ์ด ์ •๋„๋Š” ๊ดœ์ฐฎ์„ ๊ฒƒ ๊ฐ™์•„์š”, ๋ช…์‚ฌ๋กœ ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„์ด ๋๋‚˜๊ธฐ๋„ ํ•˜๊ณ ์š”.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(2๋ฒˆ, 3๋ฒˆ ํ”ผ๋“œ๋ฐฑ) ๋„ค ์ตœ๋Œ€ํ•œ ๋ฒ”์šฉ์ ์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฑฐ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์•ผ ์™œ protocol์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์™€๋‹ฟ์œผ์‹ค ๊ฒƒ ๊ฐ™์•„์š”!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์˜ค ๋„ต! ๋งํฌ๋กœ ๋‹ฌ์•„์ฃผ์‹  ๋ ˆํฌ๋ฅผ ๋งŽ์ด ์ฐธ๊ณ ํ•˜์—ฌ MVVM์„ ๊ตฌํ˜„ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹คใ…Žใ…Ž
UseCase๋Š” ์ตœ๋Œ€ํ•œ ๋ฒ”์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์–ด๋–ค ์ ์ด ๋‹ฌ๋ผ์ง€๋Š”์ง€ ํ•™์Šตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

func execute(requestValue: FetchDishesUseCaseRequestValue,
completion: @escaping (Result<DishList, Error>) -> Void)
}

final class DefaultFetchDishesUseCase: FetchDishesUseCase {
func execute(requestValue: FetchDishesUseCaseRequestValue,
completion: @escaping (Result<DishList, Error>) -> Void) {
return fetchDishes(category: requestValue.category, completion: { result in
completion(result)
})
}

func fetchDishes(category: Categorizable,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toDomain()์„ ํ˜ธ์ถœํ•ด์„œ DishList, Dish ๊ฐ์ฒด๋กœ ๋ฐ”๊พธ์…จ์ง€๋งŒ, ๊ทธ๋ž˜๋„ ์ œ๊ฐ€ ๋ณด๊ธฐ์—” networkmanager์™€ usecase์˜ ์—ญํ• ์˜ ์ฐจ์ด๊ฐ€ ์—†์–ด ๋ณด์ž…๋‹ˆ๋‹ค! ๊ฐ ๊ฐ์ฒด์˜ ์—ญํ• ์„ ๋” ๊ตฌ๋ถ„์ง€์–ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋‹ค์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ˆ ํ™•์‹คํžˆ ํ˜„์žฌ FetchDishesUseCase์™€ NetworkManager๊ฐ€ ํฐ ์ฐจ์ด๊ฐ€ ์—†๋Š”๊ฑฐ ๊ฐ™๋„ค์š”.
DishCell์— ์žˆ๋˜ image๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์ž‘์—…์„ NetworkManager๋กœ ์˜ฎ๊ธฐ๊ณ , ์œ„ ๋งํฌ๋“ค๋„ ์ฐธ๊ณ ํ•˜์—ฌ ๊ฐ์ฒด๊ฐ„ ์—ญํ• ์„ ์ข€ ๋” ๊ตฌ๋ถ„ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

completion: @escaping (Result<DishList, Error>) -> Void) {
let url = "https://79129275-12cd-405a-80a6-677b968b1977.mock.pstmn.io/banchan-code/\(category.name)"
NetworkManager.performRequest(urlString: url) { (responseDTO) in
completion(.success(responseDTO.toDomain()))
}
}
}

struct FetchDishesUseCaseRequestValue {
let category: Categorizable
}
24 changes: 24 additions & 0 deletions iOS/BanchanCode/BanchanCode/Network/NetworkManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// NetworkManager.swift
// BanchanCode
//
// Created by Song on 2021/04/22.
//

import Foundation
import Alamofire

class NetworkManager {
static func performRequest(urlString: String, completionHandler: @escaping (DishesResponseDTO) -> ()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ์ด ๋ฉ”์„œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ๋‚˜์„๊นŒ์š”, ์ •์  ๋ฉ”์„œ๋“œ๊ฐ€ ๋‚˜์„๊นŒ์š”? ์Šค์œ„ํ”„ํŠธ ๋‚ด๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ •์  ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ค ์—ญํ• ์˜ ๋ฉ”์„œ๋“œ์ธ์ง€ ํ™•์ธํ•˜๋ฉด์„œ ๊ณ ๋ฏผํ•˜์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”!
  • ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“œ์‹œ๋ฉด ํ…Œ์ŠคํŠธํ•˜๊ธฐ์—๋„ ์ข‹์Šต๋‹ˆ๋‹ค. ์˜์กด์„ฑ ์ฃผ์ž…, ๊ฐ€์งœ ๊ฐ์ฒด ๋“ฑ ๊ณต๋ถ€ํ•˜์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š” ๐Ÿ’ช

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static์ด ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ต๋‹ค๋Š” ๊ฒƒ์€ ์˜ˆ์ „์— ๋“ค์—ˆ์—ˆ๋Š”๋ฐ ๊นœ๋นก ์ƒ๊ฐ์„ ๋ชปํ–ˆ๋„ค์š”!
๋ง์”€ํ•˜์‹  ํ‚ค์›Œ๋“œ๋“ค๋„ ๊ณต๋ถ€ํ•ด๋‘๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

AF.request(urlString, method: .get)
.validate(statusCode: 200..<300)
.responseDecodable(of: DishesResponseDTO.self) { (response) in
switch response.result {
Comment on lines +13 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • AF์™€์˜ ์˜์กด์„ฑ์ด ๋†’๋„ค์š”. ๋‹ค๋ฅธ ๊ณณ์—์„œ ํ•˜์…จ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ํ•˜๋Š” ๊ฒƒ ์–ด๋–จ๊นŒ์š”?
  • ๋˜ ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ•˜์‹ค๋•Œ ์˜์กด์„ฑ ์—ญ์ „ ์›์น™์„ ์ง€ํ‚ค๋„๋ก protocol ํƒ€์ž…์„ ๋งŒ๋“œ์‹œ๋Š” ๊ฒƒ๋„ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alamofire๋ฅผ ์‚ฌ์šฉํ•ด request ์š”์ฒญํ•˜๋Š” ๋ถ€๋ถ„์„ ๋”ฐ๋กœ protocol๋กœ ๊ตฌํ˜„ํ•ด NetworkManager๊ฐ€ ์ฑ„ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ผ๋Š” ๋ง์”€์ด์‹ค๊นŒ์š”?
์ €ํฌ๊ฐ€ ํ•™์Šต์„ ํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋‹ˆ ์–ด๋Š ๋ถ€๋ถ„์ด ๋ง์”€ํ•˜์‹  ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ตฌํ˜„ํ•œ ๋ถ€๋ถ„์ธ์ง€ ์ •ํ™•ํžˆ ํŒŒ์•…์ด ์•ˆ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค๐Ÿฅฒ ํ˜น์‹œ ์–ด๋–ค ๋ถ€๋ถ„์ธ์ง€ ์กฐ๊ธˆ ํžŒํŠธ๋ฅผ ์ฃผ์‹ค ์ˆ˜ ์žˆ์„๊นŒ์š”? ๐Ÿ˜ญ๐Ÿ˜ญ

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alamofire๋ฅผ ์‚ฌ์šฉํ•ด request ์š”์ฒญํ•˜๋Š” ๋ถ€๋ถ„์„ ๋”ฐ๋กœ protocol๋กœ ๊ตฌํ˜„ํ•ด NetworkManager๊ฐ€ ์ฑ„ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ผ๋Š” ๋ง์”€์ด์‹ค๊นŒ์š”?

=> ์•„ ์ง€๊ธˆ ๋ณด๋‹ˆ, AF๊ฐ€ Networkmanager ์ž์ฒด์˜ ์—ญํ• ์„ ํ•ด๋„ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ €ํฌ๊ฐ€ ํ•™์Šต์„ ํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋‹ˆ ์–ด๋Š ๋ถ€๋ถ„์ด ๋ง์”€ํ•˜์‹  ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ตฌํ˜„ํ•œ ๋ถ€๋ถ„์ธ์ง€ ์ •ํ™•ํžˆ ํŒŒ์•…์ด ์•ˆ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค๐Ÿฅฒ ํ˜น์‹œ ์–ด๋–ค ๋ถ€๋ถ„์ธ์ง€ ์กฐ๊ธˆ ํžŒํŠธ๋ฅผ ์ฃผ์‹ค ์ˆ˜ ์žˆ์„๊นŒ์š”?

=> ์œ„์—๋Œ€๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๊ฐ Usecase ๊ฐ€ networkmanager๋ฅผ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์˜์กด์„ฑ ์ฃผ์ž… ๋ฐ ์˜์กด์„ฑ ์—ญ์ „ ์›์น™์„ ํ•˜๋ฉด ๋˜๊ฒ ๋„ค์š”!
๊ตฌ๊ธ€๋งํ•ด์„œ ์ฐพ์•„๋ณด์…”์š” ใ…Žใ…Žใ…Ž

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด ๋ถ€๋ถ„์ด ์ค‘์š”ํ•˜๊ธฐ๋„ ํ•˜๊ณ  ์ €ํฌ๊ฐ€ ํ•™์Šต์ด ๋งŽ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์ธ ๊ฒƒ ๊ฐ™์•„์„œ ํŒ€์›๊ณผ ์ข€๋” ๊ผผ๊ผผํžˆ ๊ณต๋ถ€ํ•ด๋ณด๊ณ  ๊ทธ๋ž˜๋„ ์ดํ•ด๊ฐ€ ์–ด๋ ค์šฐ๋ฉด ์ถ”๊ฐ€์ ์œผ๋กœ ์งˆ๋ฌธ์„ ๋“œ๋ฆด ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”. ๋ง์”€ํ•˜์‹  ๊ฒƒ์ฒ˜๋Ÿผ ๊ตฌ๊ธ€๋ง์ด๋‚˜ ์ž๋ฃŒ ์ฐพ์•„๋ณด๋ฉด์„œ ๊ณต๋ถ€ํ•˜๊ณ  ์ข€๋” ๊ฐœ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

case .success(let dishes):
completionHandler(dishes)
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
Loading