Dear. UI-App User Customer
Bank
μ μ
무λ₯Ό λ³΄λ¬ μ€μ
¨λμ?
μ ν¬ μνμ 10λͺ
μ© λκΈ°μ€
μ μΆκ°λ₯Ό ν΄λλ¦¬κ³ μμ΅λλ€!
μμκ° λλ©΄ BankClerk
μ΄ μλ²μ λ°λΌ μ
무μ€
λΌμΈμμ νΈμΆν΄λ립λλ€.
μ μλ§ κΈ°λ€λ € μ£ΌμΈμ~
ν΅μ¬ κ°λ λ° κ²½ν
- MVC
Model
,View
,Controller
κ° νλμ μν λ§ ν μ μλλ‘ κ΅¬ν- Timer
Timer
λ₯Ό μ΄μ©νμ¬ μ 무μκ°μ μΈ‘μ ν μ μλWorkTimer
ꡬν- CustomView
CustomView
λ₯Ό λ§λ€μ΄View
μController
λ₯Ό λΆλ¦¬νκ³ μ½λλ‘λ§ UI ꡬνStackView
λ₯Ό νμ©νμ¬Label
μ μΆκ° μμ κΈ°λ₯μ ꡬν- Concurrency UI update
- λ©ν° μ€λ λ νκ²½μμ
Operation.main
μ μ΄μ©ν UI μ λ°μ΄νΈ μμ± μν- Swift Package Manager
- μ½μμ±μ
Customer
λ₯Ό λ‘컬 ν¨ν€μ§λ‘ λ§λ€μ΄ UIμ±μ νμ©
Serena π· | Erick 𦦠|
---|---|
![]() |
νλ‘μ νΈ κΈ°κ° : 2023.07.10 ~ 2023.07.21
λ μ§ | λ΄μ© |
---|---|
2023.07.10 | β«οΈ Linked List ꡬν β«οΈ Linked List λ₯Ό μ΄μ©ν Queue ꡬν |
2023.07.11 | β«οΈ μ½λ κ°μ μ μν 리νν λ§ |
2023.07.12 | β«οΈ κ³ κ°μ μν μ νλ Customer β«οΈ μνμμ μν μ νλ BankClerk ꡬν β«οΈ μνμ μ 무λ₯Ό νκΈ° μν Bank ꡬν β«οΈ Bank λ₯Ό κ΄λ¦¬νλ BankManager ꡬν |
2023.07.13 | β«οΈ μ½λ κ°μ μ μν 리νν λ§ |
2023.07.14 | β«οΈ μ
무μ μ’
λ₯λ₯Ό λλκΈ° μν΄ WorkType ꡬν β«οΈ μνμμ μΈμμ λ°λΌ λΉλκΈ°μ μΌλ‘ μ 무λ₯Ό μ²λ¦¬νλ λ‘μ§ κ΅¬ν β«οΈ μνμμ WorkType μ λ°λΌ μ
무λ₯Ό λλ μ£Όλ λ‘μ§ κ΅¬ν β«οΈ README μμ± |
2023.07.16 | β«οΈ μ½λ κ°μ μ μν 리νν λ§ β«οΈ WorkType μ μ
무 Name μΆκ° |
2023.07.17 | β«οΈ HTTP κ°μΈ κ³΅λΆ |
2023.07.18 | β«οΈ μ½λ κ°μ μ μν 리νν λ§ |
2023.07.19 | β«οΈ Queue λ₯Ό protocol Queueable λ‘ μΆμν β«οΈ μν창ꡬ 맀λμ μ±μ νλ©΄μ ꡬμ±νλ BankManagerView ꡬν β«οΈ DynamicType μ μ© |
2023.07.20 | β«οΈ MVC νμΌ λΆλ¦¬ λ° Timer κ°μΈ κ³΅λΆ |
2023.07.21 | β«οΈ SPM νμ©νμ¬ λ‘컬 λΌμ΄λΈλ¬λ¦¬ μΆκ° β«οΈ Console App μ ꡬνν Bank λ₯Ό UI App μ λ§κ² 리νν λ§ β«οΈ μ 무μκ°μ μΈ‘μ νλ WorkTimer ꡬν β«οΈ Controller μμ μ¬μ©μ μ
λ ₯μ λ§κ² View λ₯Ό μ
λ°μ΄νΈνκ³ Model μ νΈμΆνλ λ‘μ§ κ΅¬ν |
![](https://private-user-images.githubusercontent.com/109963294/255393419-2785d477-05a5-481b-8e88-c0a32e1ea1f8.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE5MTIwMzIsIm5iZiI6MTcyMTkxMTczMiwicGF0aCI6Ii8xMDk5NjMyOTQvMjU1MzkzNDE5LTI3ODVkNDc3LTA1YTUtNDgxYi04ZTg4LWMwYTMyZTFlYTFmOC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzI1JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcyNVQxMjQ4NTJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1hYjExNDY0ZDJhMWEyOTEyNDhhNzAyYzYyZTAzYjU2YmU4OTQ1MzNmM2NkMGQzOWJlY2E3YWJhMTEyMTM2MzYxJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.3el7r0afs1kByJ54oLBnFJLOKxaXJCATuDcvfWtpKVY)
BankManagerUIApp
βββ Application
βΒ Β βββ AppDelegate.swift
βΒ Β βββ SceneDelegate.swift
βββ ViewController
βΒ Β βββ BankManagerViewController.swift
βββ View
βΒ Β βββ BankManagerView.swift
βββ Model
βΒ Β βββ Bank
βΒ Β βΒ Β βββ Bank.swift
βΒ Β βΒ Β βββ BankClerk.swift
βΒ Β βββ WorkTimer.swift
βββ Extenstion
βββ Double+.swift
Β Β βββ Notification.Name+.swift
Model
,View
,Controller
μ μν μ λν΄ κ³ λ―Όνμ΅λλ€.- λν κ°μ²΄κ° μλ‘μ νλ‘νΌν°μ μ§μ μ κ·Όνλ κ²μ΄ μλ λ©μλλ₯Ό ν΅ν μμ¬μν΅μ ν΄μΌνλ€κ³ μκ°νμ΅λλ€.
- View:
View
λView
κ°μ²΄λ₯Ό νλ‘νΌν°λ‘ κ°μ§κ³Constraints
μ½λμView
κ°μ²΄μ λ°μ΄ν°λ₯Ό μΈν ν μ μλ λ©μλλ₯Ό κ°μ§κ³ μμ΅λλ€. - Model: λΉμ¦λμ€ λ‘μ§μ μ€νμν¬ μ μλ μ½λμ
Controller
μμ μ΄λ₯Ό μ€ν μν¬ μ μλ λ©μλλ₯Ό κ°μ§κ³ μμ΅λλ€. - Controller:
View
μModel
μ κ°μ²΄λ‘ κ°μ§κ³ μκ³ μ¬μ©μμ μ λ ₯μ΄λ νΉμ μ΄λ²€νΈκ° λ°μνμλ λ·°λ₯Ό μ λ°μ΄νΈ μν€κ±°λModel
μ λ‘μ§μ μ€νμν΅λλ€.
- νλ©΄ νμ μ ν΄λ
UI
κ° κΈ°κΈ°μ κ°μ₯μ리μ μλ¦¬μ§ μκ³ μΆλ ₯λ μ μλλ‘ κ΅¬ννκΈ° μν΄ κ³ λ―Όνμ΅λλ€. - κ·Έλ¦¬κ³ νλ©΄ μ€ν¬λ‘€μ
λκΈ°μ€/μ 무μ€
stackView
λ§ μ€ν¬λ‘€μ΄ λλλ‘ ν μ§ μ 체 νλ©΄μ λͺ¨λ μ€ν¬λ‘€μ ν μ§ κ³ λ―Όνμ΅λλ€.
- νλ©΄ νμ μ ν΄λ
UI
κ° κΈ°κΈ°μ κ°μ₯μ리μ μλ¦¬μ§ μκ³ μΆλ ₯λ μ μλλ‘scrollView
λ₯Ό λ·°μ μμ ꡬμ λ΄μ μμΉνκ² νμμ΅λλ€. μ΄λ₯Ό μν΄view.safeAreaLayoutGuide
μconstraint
λ₯Ό μ€μ ν΄μ£Όμμ΅λλ€.private func setUpScrollViewConstraints() { NSLayoutConstraint.activate([ scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor) ]) }
- μ±μ μ΄μ©ν λ νλ©΄ λ΄ λ·°κ°μ²΄κ° μ€ν¬λ‘€λλ κ²λ³΄λ¨ μ 체 νλ©΄μ μ€ν¬λ‘€ νλ μͺ½μ΄ μ κ·Όμ±μ΄ λ μ’λ€κ³ μκ°νμ¬ μ 체νλ©΄μ΄ μ€ν¬λ‘€ λλλ‘ μ€μ νμμ΅λλ€.
- νΉν μΌκ³° λ·λ·μ ν΅ν΄ λ°°μ΄ λ΄μ© λν νμ©νμμ΅λλ€. μ€ν¬λ‘€λ·° μ€μ μ
frame
κ³Όmultiply
μ 1λ‘ λ§μΆ νconstant
1κ°μ μ£Όλ©΄contentview
μ ν¬κΈ°κ° μμλ λλκ·Έ λ° μ€ν¬λ‘€μ ν¨κ³Όλ₯Ό λ΄μμ΅λλ€.
let contentViewHeightConstraints = contentView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor, constant: 1) contentViewHeightConstraints.priority = .init(1) contentViewHeightConstraints.isActive = true
- νΉν μΌκ³° λ·λ·μ ν΅ν΄ λ°°μ΄ λ΄μ© λν νμ©νμμ΅λλ€. μ€ν¬λ‘€λ·° μ€μ μ
- μ§μ μ€ν
κ³Ό λ¬λ¦¬
UI
μ λ§μΆμ΄ νλ‘μ νΈλ₯Ό ꡬμ±νλ€λ³΄λ μ΄λ ν λ°©μμΌλ‘ λΉλκΈ°λ₯Ό ꡬνν μ§ κ³ λ―Όνμμ΅λλ€.- 첫λ²μ§Έλ‘
DispatchQueue
λOperation
κ³Ό λ¬λ¦¬ μ€λ λμ μμ μ μ λ¬ μ λ³κ²½ λ° μ·¨μκ° λμ§ μμμ΅λλ€. μ΄μUI
λmain
μ€λ λμμλ§ μ§νκΈ° λλ¬Έμ μλ μ μΆ©λμ μ°λ €κ° μμμ΅λλ€. - λλ²μ§Έλ‘ μ½μμ±κ³Ό
UI
λ₯Ό ꡬνν λ 뷰컨νΈλ‘€μ΄λΌλ κ°μ₯ ν° μ°¨μ΄κ° μκ²Όμ΅λλ€. μ΄μ ꡬ쑰λ₯Ό μ΄μ κ³Ό λμΌνκ² μ§ννκΈ°μ μ΄μν λΆλΆμ΄ μκΈΈ μ μλ€κ³ μκ°νμ΅λλ€
- 첫λ²μ§Έλ‘
Operation
μΌλ‘ μμ μ νμ ν μμΌμ€ μ μκ³ ,Queue
λ₯Ό μ΄μ©ν μμ κ΄λ¦¬κ° λ μ¬μ μ½λκ° κ°κ²°νλ©° κ°λ μ±μ΄ μ’μμ ΈGCD
λ‘ κ΅¬νλμ΄ μλ λΉλκΈ° λ‘μ§μOperation
μΌλ‘ λ³κ²½νμμ΅λλ€.BankClerk
μ μ 무λ³λ‘ λλ μΈμ€ν΄μ€λ₯Ό μμ±νλ κ²μ΄ μλ μ 무λ³λ‘OperationQueue
λ₯Ό λλ μμ±νμ¬ μ€λ λ κ΄λ¦¬λ₯Ό νμμ΅λλ€.- 그리κ³
BankClerk.carryOutBankService
λ₯ΌBlockOperation
μΌλ‘ νμ ννμ¬ μ 무λ³Queue
μ λ£μ΄μ£Όλ κ²μΌλ‘ λΉλκΈ° μ²λ¦¬λ₯Ό νμμ΅λλ€. μ΄κΈ°ν
λ²νΌμ λλ μ λ μ΄λ―Έ νμ λ€μ΄κ° μμ μcancelAllOperations
λ₯Ό μ΄μ©νμ¬ μ·¨μνμμ΅λλ€.
class Bank { // ... private let loanOperationQueue: OperationQueue = { let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = WorkType.loan.numberOfBankClerk return operationQueue }() private let depositOperationQueue: OperationQueue = { let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = WorkType.deposit.numberOfBankClerk return operationQueue }() // ... private func startBankService() { while !waitingLine.isEmpty { guard let currentCustomer = waitingLine.dequeue() else { return } let operation = BlockOperation { BankClerk.carryOutBankService(for: currentCustomer) } switch currentCustomer.workType { case .deposit: depositOperationQueue.addOperation(operation) case .loan: loanOperationQueue.addOperation(operation) default: print("workTypeμ΄ nilμ λλ€.") } } } func stopBankService() { // ... depositOperationQueue.cancelAllOperations() loanOperationQueue.cancelAllOperations() } }
- νλ©΄μ μ€ν¬λ‘€ μ νμ΄λ¨Έκ° λ©μΆλ λ¬Έμ κ° μμμ΅λλ€. μ΄λ μ¬μ©μκ° μ€ν¬λ‘€μ νμ λ RunLoopκ° tracking λͺ¨λλ‘ λ°λμ΄ νμ΄λ¨Έκ° μ€νλμ§ μλ λ¬Έμ μμ΅λλ€.
- μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ νμ¬ λ°λ£¨νμ νμ΄λ¨Έλ₯Ό
.common
λͺ¨λλ‘ λ±λ‘νμμ΅λλ€.
.common: νλ μ΄μμ λ€λ₯Έ μ€ν λͺ¨λλ₯Ό ν¬ν¨ν λͺ¨λ
RunLoop.current.add(timer, forMode: .common)
- κΈ°μ‘΄μ ꡬνν μ½μμ± νλ‘μ νΈλ₯Ό νμ©νμ¬ μλ‘κ² UIνλ‘μ νΈλ₯Ό μ§νν¨μ μμ΄ μ΄λ»κ² νμΌμ ν©μΉ μ§ κ³ λ―Όμ νμ΅λλ€. μ½μμ± νλ‘μ νΈμ ꡬνν νμΌμ κ²½λ‘λ₯Ό μΆμ νμ¬ νμΌμ 곡μ νλ λ°©λ²λ κ°λ₯νμ§λ§ μ΄ λ°©λ²μ μ¬μ©ν κ²½μ° UIνλ‘μ νΈλ₯Ό μν΄ νμΌμ λ³κ²½ν κ²½μ° μ½μμ±μ νλ‘μ νΈλ ν¨κ» μμ λλ€λ λ¨μ μ΄ μ‘΄μ¬νμ΅λλ€.
- μ½μμ±κ³Ό UI νλ‘μ νΈ λͺ¨λ
Queue
,Linked-List
,Customer
λ± ν ꡬ쑰μCustomer
λ΄μ©μ λ‘컬framework
λ‘ λ§λ€μμ΅λλ€. νλ μμν¬λ₯Ό νμ©νλλ°CocoaPods
,Carthage
,SPM
λ± μ¬λ¬ λ°©λ²μ΄ μμ§λ§ λ‘μ»¬λ‘ λ°λ‘ μ°λμ΄ κ°λ₯νSPM
μ μ¬μ©νμ¬ μ½μμ± νλ‘μ νΈμ κ³΅ν΅ λ΄μ©μ UI νλ‘μ νΈμ μ μ©νμμ΅λλ€.
swift packmanager
λ₯Ό μ¬μ©νμ¬customer
λ‘컬 ν¨ν€μ§λ₯Ό μμ±νμ¬ νμ©νλ κ³Όμ μμ μ§μ λ§λ ν¨μ§λ₯Ό νμ©νλ€λ³΄λ μλ‘μ΄ λ¬Έμ μ μ§λ©΄νμ΅λλ€. κΈ°λ³Έμ μΌλ‘ μ€μ λμ΄μλinternal
μ λͺ¨λ μΈλΆμμλ μ¬μ©κ°λ₯νκ² μμ ν΄μΌνλ λ¬Έμ μμ΅λλ€. λͺ¨λ μΈλΆμμ μ¬μ© κ°λ₯νκ² νλ μ κ·Όμ μ΄μμλpublic
κ³Όopen
μ΄ μμ΅λλ€. μ΄ λμ μ°¨μ΄μ μ κ³ λ €νμ¬ μ μ©νκ³ μ νμμ΅λλ€.
open
κ³Όpublic
μ λͺ¨λ μΈλΆμ κ°λ°©μ΄ λμ΄ μμ΄ λͺ¨λ λ°μμ λͺ¨λ μ κ·Όμ΄ κ°λ₯νλ€λ 곡ν΅μ μ΄ μμ§λ§,open
μ κ²½μ° μ€λ²λΌμ΄λ, μλΈν΄λμ±μ΄ κ°λ₯νμ§λ§public
μ κ²½μ° μ€λ²λΌμ΄λ, μλΈν΄λμ±μ΄ λΆκ°λ₯ν©λλ€. μ΄λ¬ν μ°¨μ΄λ₯Ό κ³ λ €μνμ λ μ ννλ νμCustomer
κ°μ²΄λ₯Ό 곡μ νκ³ μ νλ μμν¬λ₯Ό μμ±ν μ ν¬μ μλμλpublic
μ΄ λ μ μ νλ€ μκ°νμ¬public
μ κ° λ©μλ, νλ‘νΌν°λ³λ‘ μΆκ°νμμ΅λλ€.public struct Customer { public let waitingNumber: Int public let workType: WorkType? = WorkType.allCases.randomElement() public init(waitingNumber: Int) { self.waitingNumber = waitingNumber } }
ν νκ³
- μ½λλ₯Ό ꡬνν¨μ μμ΄ μλ‘μ μ견μ λ°μνμ¬ μ½λλ₯Ό μμ±νμμ΅λλ€.
- νλ‘μ νΈ κ΅¬νμ ν¨μ μμ΄ νκ°μ§ λ°©λ²μ΄ μλ μ¬λ¬κ°μ§ λ°©λ²μ κ³ λ €ν μ μ΄ μ’μμ΅λλ€.
- μ½λλ₯Ό κΉμ΄μκ² κ³ λ―Όνκ³ κ³΅λΆν ν νλ‘μ νΈλ₯Ό μ§ννμμ΅λλ€.
- μκ° λ΄μ νλ‘μ νΈλ₯Ό μμ±λ μκ² λ§λ¬΄λ¦¬νμμ΅λλ€.
- νμ κ° μκ°μ΄ μ μ λ§μ λ λ§μ 곡λΆλ₯Ό ν¨κ»νμ§ λͺ» νλ κ²μ΄ μμ¬μ μ΅λλ€.
- κ°μΈ μ¬μ μΌλ‘ μκ° μ‘°μ μ μ΄λ €μμ΄ μμμ΅λλ€.