Skip to content

yim2627/ios-bank-manager

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

65 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿฆ ์€ํ–‰ ์ฐฝ๊ตฌ ๋งค๋‹ˆ์ €

์—ฌ๊ธฐ ์ด์ž์œจ์ด ์™œ ์ด๋ž˜์š”..


Index


Preview

Not Open Open
Open

๐Ÿค Ground Rule

์‹œ๊ฐ„

  • ์˜ค์ „ 10์‹œ ~
  • ์ ์‹ฌ 12-2์‹œ
  • ์ €๋… 6-7์‹œ
  • ์ฃผ๋ง์€ ํœด์‹
  • ์‰ฌ๊ณ  ์‹ถ์œผ๋ฉด ์–ธ์ œ๋“ ์ง€ ๋งํ•˜๊ธฐ

์ง„ํ–‰ ๊ณ„ํš

  • STEP 1 โ†’ 12.21 18:00
  • STEP 2 โ†’ 12.24 18:00
  • STEP 3 โ†’ 12.28 18:00

์ปค๋ฐ‹ ๊ด€๋ จ

๊ธฐํƒ€

  • ๊ตฌํ˜„ ์ „ Issue๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•ด ํ•œ๋ฒˆ ๋” ์ƒ๊ฐํ•ด๋ณธ๋‹ค.

1๏ธโƒฃ Step 1

๐ŸŽฏย Step1 ๊ตฌํ˜„ ๋‚ด์šฉ

LinkedList

  1. ์šฐ๋ฆฌ๊ฐ€ ๋„ฃ์–ด์ค„ ์ธ๋ฑ์Šค์— ์›๋ž˜ ์œ„์น˜ํ–ˆ๋˜ ๋…ธ๋“œ๋ฅผ ์ž„์‹œ ๋ณ€์ˆ˜์— ์ €์žฅ(๋ณต์‚ฌ)ํ•˜๊ณ , ์›๋ž˜ ์œ„์น˜ํ–ˆ๋˜ ๋…ธ๋“œ์— ์šฐ๋ฆฌ๊ฐ€ ๋„ฃ์–ด์ค„ ๋…ธ๋“œ๋ฅผ ๋„ฃ์Œ
  2. ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’์„ ๋„ฃ์€ ๋…ธ๋“œ๋ฅผ ๋„ฃ๊ณ ์‹ถ์€ ์ธ๋ฑ์Šค์˜ ๋‹ค์Œ ๋…ธ๋“œ๋กœ ์ž„์‹œ ๋ณ€์ˆ˜์— ์ €์žฅํ–ˆ๋˜ ๋…ธ๋“œ๋ฅผ ์„ค์ • (์›๋ž˜ ํ•ด๋‹น ์ธ๋ฑ์Šค์— ์œ„์น˜ํ–ˆ๋˜ ๋…ธ๋“œ)
  3. ์ƒˆ๋กœ์šด ๋…ธ๋“œ๊ฐ€ ๋“ค์–ด๊ฐ”์œผ๋ฏ€๋กœ, prev์™€ next๋ฅผ ์–‘ ๋…ธ๋“œ์— ์—ฐ๊ฒฐ

LinkedList removeFirst() ๋ฉ”์†Œ๋“œ ๋ณ€๊ฒฝ

๋ณดํ†ต์˜ removeLast() ๊ธฐ๋Šฅ์„ Queue์˜ FIFO ํŠน์„ฑ์— ๋”ฐ๋ผ removeFirst()๋กœ ์ˆ˜์ •ํ•ด์ฃผ์—ˆ์Œ

์ด ๊ณผ์ •์—์„œ ๋”ฐ๋กœ ์กฐ๊ฑด์„ ๋งŒ๋“ค์–ด ์ฃผ์ง€ ์•Š์€ head = nil ์„ ํƒ€๊ฒŒ ๋˜๋ฉฐ head๋ถ€ํ„ฐ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ํ˜•์‹์˜ LinkedList๊ฐ€ ์ „๋ถ€ ๋Š๊ฒจ๋ฒ„๋ฆฌ๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ

head.next์— head๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ head๋Š” ์ด์ œ head.next ์ธ ๋ฐฉ์‹์„ ์‚ฌ์šฉ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ

// before
func removeFirst() -> T? {
        guard head != nil else {
            return nil
        }

        let data = head?.data
				if head?.next != nil {
						head?.next = head
				}
				head = nil
				
        return data
    }

// after
func removeFirst() -> T? {
        guard head != nil else {
            return nil
        }
        
        let data = head?.data
        
        if head?.next != nil {
            head = head?.next
        } else {
            head = nil
        }
        
        return data
    }

@discardableResult

removeFirst() ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๋ฐ˜ํ™˜ ๊ฐ’์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด@discardableResult ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ž„

ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Queue์˜ Dequeue()์—๋„ ๋งฅ๋ฝ์„ ์œ„ํ•ด @discardableResult ์„ ๋ถ™์ž„

๐Ÿค”ย Step1 ๊ณ ๋ฏผํ–ˆ๋˜ ์ 

LinkedList ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝ

๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ฆฌ์ŠคํŠธ์˜ ๋งจ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ ๋‹ค์Œ์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” append()๋ฅผ ํ•˜๋ ค๋ฉด ๋ฆฌ์ŠคํŠธ์˜ ๋๊นŒ์ง€ ์ˆœํšŒํ•ด์•ผํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์Œ

์ด๋ฅผ ๊ฐœ์„ ํ•˜๊ณ ์ž ์–‘๋ฐฉํ–ฅ ์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ๋กœ ์ˆ˜์ •

์–‘๋ฐฉํ–ฅ์œผ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ append()๋ฅผ ํ•  ๋•Œ, ๋ชจ๋“  node๋ฅผ ์ˆœํšŒํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ tail์„ ์ฐพ๊ธฐ๋•Œ๋ฌธ์— ๋‹จ๋ฐฉํ–ฅ์˜ ๋‹จ์ (๋งŽ์€ ๋น„์šฉ(์ˆœํšŒ))์„ ๋ณด์™„


Node, LinkedList struct vs class

  1. ๋…ธ๋“œ๋Š” ํƒ€์ž… ๋‚ด๋ถ€์—์„œ ๊ฐ™์€ ํƒ€์ž…์ธ ์ž์‹ ์„ ์ฐธ์กฐํ•˜๊ธฐ๋•Œ๋ฌธ์— ๊ตฌ์กฐ์ฒด๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†์Œ
  2. ๋…ธ๋“œ๋ฅผ ํด๋ž˜์Šค๋กœ ์ƒ์„ฑํ•˜์—ฌ ํ•œ ๋…ธ๋“œ์— ๋Œ€ํ•ด ์ฐธ์กฐ ํ•ด์ œ๋ฅผ ํ•ด์ค„ ๊ฒฝ์šฐ, ARC๋กœ ์ธํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋‚ด๋ ค๊ฐ€๊ฒŒ๋” ๋งŒ๋“ค์–ด์ค„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํด๋ž˜์Šค๋กœ ์ƒ์„ฑ
  3. LinkedList๋Š” queueํƒ€์ž…์—์„œ ์›๋ณธ๊ฐ’(๋…ธ๋“œ)์ด ๊ณ„์† ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์›๋ณธ์„ ์ฐธ์กฐํ•˜์—ฌ ์›๋ณธ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ํด๋ž˜์Šค๋กœ ์ƒ์„ฑ

๐Ÿ™‡โ€โ™‚๏ธย Step1 ๋ฐฐ์šด ์ 

Mock ํƒ€์ž… ์ƒ์„ฑ

  • ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผ์ œ์–ด๋ฅผ ์ฃผ์—ˆ๋Š”๋ฐ, ์ด๋Š” ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์„ค์ •ํ•˜์˜€์Œ
  • Unit Test ์ง„ํ–‰์‹œ ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด์•ผํ•˜๋Š”๋ฐ, ์ ‘๊ทผ์ œ์–ด๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ…Œ์ŠคํŠธ ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ
  • ๊ทธ๋Ÿด ๋• Mock ํƒ€์ž… ์ƒ์„ฑ ํ›„ ํ•ด๋‹น ํƒ€์ž…์„ ํ…Œ์ŠคํŠธ๋งŒ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋ฉด ๋จ ์ด๋กœ์จ Mock์˜ ์›๋ณธ ํƒ€์ž…์€ ๋ณธ๋ž˜ ์ƒํƒœ ์œ ์ง€

2๏ธโƒฃย Step 2

๐Ÿ“Šย Step2 UML

Untitled

๐ŸŽฏย Step2 ๊ตฌํ˜„ ๋‚ด์šฉ

  • Step1์—์„œ ๊ตฌํ˜„ํ•œ Queue๋ฅผ ์ด์šฉํ•ด ๊ณ ๊ฐ ๊ด€๋ฆฌ
  • ์ง์›์˜ ๊ณ ๊ฐ ์—…๋ฌด์ฒ˜๋ฆฌ, ์—…๋ฌด์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ๊ตฌํ˜„
  • ํƒ€์ž… ์ถ”์ƒํ™” ๋ฐ ์ผ๋ฐ˜ํ™”
  • ์—ญํ•  ๋ถ„๋ฆฌ
  • ์ƒํ•˜๊ด€๊ณ„๋กœ ์„ค๊ณ„ํ•˜์—ฌ ๋‹จ๋ฐฉํ–ฅ ์˜์กด์„ ํ•จ์œผ๋กœ์จ ์ˆœํ™˜ ์ฐธ์กฐ ๋“ฑ์˜ ์ƒํ™ฉ ๋ฐฉ์ง€

๐Ÿค”ย Step2 ๊ณ ๋ฏผํ–ˆ๋˜ ์ 

inout Parameter

// Bank
mutating func letClerkWork() {
    while waitingLine.isEmpty == false {
        bankClerk.work(&waitingLine)
    }
}

// Clerk
func work(_ waitingLine: inout Queue<Customer>) {
    guard let customer = waitingLine.dequeue() else {
        return
    }

    print("\(customer.waitingNumber)๋ฒˆ ๊ณ ๊ฐ ์—…๋ฌด ์‹œ์ž‘")
    Thread.sleep(forTimeInterval: 0.7)
    print("\(customer.waitingNumber)๋ฒˆ ๊ณ ๊ฐ ์—…๋ฌด ์ข…๋ฃŒ")
}
  • ํ•จ์ˆ˜ ์™ธ๋ถ€์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉฐ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด์„  inout Parameter๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
  • ํ•„์ž๋“ค์€ ์ด๋กœ์ธํ•ด ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ ธ ๋ณด์ธ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ , ๊ฐ ํƒ€์ž…์˜ ์—ญํ• ์„ ๋” ๋ถ„๋ช…ํžˆ ํ•œ๋‹ค๋ฉด ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•˜์˜€๊ณ  ์ฝ”๋“œ ๊ฒ€ํ†  ๊ฒฐ๊ณผ, ๊ธฐ์กด์— ์€ํ–‰์˜ ์ผ๋กœ ์„ค๊ณ„ํ•œ ์ผ์„ ์ง์›์ด ํ•˜๊ณ ์žˆ์—ˆ๊ณ  ์ด๋ฅผ ์€ํ–‰์ด ์ผ์„ ํ•œ ๋’ค, ์ผ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ง์›์ด ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์œผ๋กœ ๋ณ€๊ฒฝํ•˜์˜€์Œ

์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ? ์ง€์—ญ๋ณ€์ˆ˜?

Bank์˜ ์—…๋ฌด ๋งˆ๊ฐ์„ ์•Œ๋ฆฌ๋Š” ์ถœ๋ ฅ๋ฌธ์„ ๊ตฌํ˜„ํ•  ๋•Œ, ๋ช‡ ๋ช…์˜ ๊ณ ๊ฐ์„ ๋ฐ›์•˜๋Š”์ง€ ์•Œ์•„์•ผ ํ–ˆ์Œ

์ƒ๊ฐํ•œ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ์ฒ˜์Œ์— BankManager๊ฐ€ ์ƒ์„ฑํ•˜์—ฌ์ฃผ๋Š” ๋žœ๋คํ•œ ๊ณ ๊ฐ์˜ ์ˆ˜๋ฅผ ๊ฐ€์ ธ์™€ Bank ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•ด ์ค€ ๋’ค ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ

    struct Bank {
    	var totalNumber = 0
    
    	mutating func setWaitingLine(with numberOfCustomer: () -> Int) {
          totalNumber = numberOfCustomer()
          for number in 1...totalNumber {
              waitingLine.enqueue(Customer(waitingNumber: number))
          }
       }
    }
  2. Bank์˜ย letClerkWork()ย ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—์„œ ์ดˆ๊ธฐ๊ฐ’ 0์„ ๊ฐ€์ง„ ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜์—ฌ loop๊ฐ€ ํ•œ๋ฒˆ ๋Œ ๋•Œ(dequeue ํ•œ๋ฒˆ)๋งˆ๋‹ค ํ•ด๋‹น ์ง€์—ญ ๋ณ€์ˆ˜์— ์นด์šดํŠธ ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ’์„ ํ• ๋‹นํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ

    struct Bank {
    	mutating func letClerkWork() {
          let taskTime = 0.7
          var numberOfCustomer = 0
            
          while waitingLine.isEmpty == false {
              let customer = dequeueWaitingLine()
              bankClerk.handleTask(of: customer, until: taskTime)
              numberOfCustomer += 1
          }
          noticeCloseDown(totalCustomer: numberOfCustomer, taskTime: taskTime)
      }
    }

์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ: ์ €ํฌ๊ฐ€ ์„ค๊ณ„ํ•œ ํ”„๋กœ๊ทธ๋žจ ๋‚ด์—์„œ Bank๋ผ๋Š” ์ธ์Šคํ„ด์Šค๋Š” ์€ํ–‰์ด ์—ด๋ฆฌ๋Š” ์‹œ์ ๋ถ€ํ„ฐ ์—…๋ฌด๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ์‹œ์ ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ๊ฐ€ ์žˆ์–ด ํ”„๋กœํผํ‹ฐ๊ฐ€ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ ๋•Œ์—๋„ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๋‹ค.

ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ง€์—ญ๋ณ€์ˆ˜: ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ๋๋‚˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€๋งŒ, ๋ฐ˜๋ณต์ ์ธ ์—ฐ์‚ฐ์ด ์ผ์–ด๋‚˜ ์ฒ˜๋ฆฌ๋น„์šฉ์ด ์†Œ๋ชจ๋œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

๊ณ ๋ฏผ ๊ฒฐ๊ณผ

์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฑ„ํƒํ•˜์˜€๋‹ค.

  • ์ด์œ : ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‹จ ํ•œ๊ฐœ๋ผ๋ฉด ์ง€์—ญ ๋ณ€์ˆ˜๊ฐ€ ๋งž๊ฒ ์ง€๋งŒ, ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋ฅผ ๋‘ ๊ณณ์—์„œ ์‚ฌ์šฉํ•ด์ค˜์•ผ ํ–ˆ์œผ๋ฏ€๋กœ, ๋‘ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ์ง€์—ญ๋ณ€์ˆ˜๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ๊ณ  ๋‚ด๋ฆฌ๊ณ ์˜ ๋น„์šฉ๋ณด๋‹ค ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•œ๋ฒˆ๋งŒ ์˜ฌ๋ ค์ฃผ๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๊ฒ ๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€๋‹ค.

๐Ÿ™‡โ€โ™‚๏ธย Step2 ๋ฐฐ์šด ์ 

์—ญํ•  ๋ถ„๋ฆฌ

  • ์ฝ”๋“œ ์ž‘์„ฑ ์ „, UML๊ณผ ํƒ€์ž…์˜ ์ถ”์ƒํ™”, ์ผ๋ฐ˜ํ™”๋ฅผ ํ†ตํ•ด ๊ฐ ํƒ€์ž…์˜ ์ฑ…์ž„์„ ๋ถ„๋ช…ํžˆ ํ•˜์˜€์Œ

์€ํ–‰์›์ด ๊ณ ๊ฐ์„ ์ง์ ‘ ๋ถˆ๋Ÿฌ์˜ฌ์ง€, ์€ํ–‰์ด ์€ํ–‰์›์—๊ฒŒ ๊ณ ๊ฐ์„ ๋„˜๊ฒจ์ค„์ง€ ๋“ฑ์˜ ๊ฐ๊ฐ ์ž์‹ ์˜ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ฒŒ ํ•˜์—ฌ ๊ด€๊ณ„๋ฅผ ๋ถ„๋ช…ํžˆ ํ•œ๋‹ค๋ฉด ์ดํ›„ ๋‹จ์ผ ์ฑ…์ž„๊ณผ ์˜์กด์„ฑ ๊ด€๋ฆฌ์— ์šฉ์ดํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ถˆ๋Ÿฌ์˜ด์„ ์•Œ๊ฒŒ๋˜์—ˆ์Œ

inout Parameter

  • in-outย ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๊ธฐ์กด ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๊ธฐ์กด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ์ˆ˜์ •ํ•˜๊ณ , ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋  ๋•Œ ๊ธฐ์กด ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๋ณต์‚ฌ๋œ(์ˆ˜์ •๋œ) ๊ฐ’์œผ๋กœ ํ• ๋‹น

Naming ์ค‘์š”์„ฑ

https://www.swift.org/documentation/api-design-guidelines/#naming

3๏ธโƒฃย Step 3

๐ŸŽฏย Step3 ๊ตฌํ˜„ ๋‚ด์šฉ

๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • ์—ฌ๋Ÿฌ ์€ํ–‰์›๋“ค์ด ๋™์‹œ์— ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง ๊ตฌํ˜„
  • CustomQueue๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ํŠน์ • ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ง์›์ด ํ•œ๋ช…์ธ ์ƒํ™ฉ์—” Serial Queue๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์—ฌ๋Ÿฌ๋ช…์ธ ์ƒํ™ฉ์—” Concurrent Queue๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๊ตฌํ˜„

๊ณ ๊ฐ ๋Œ€๊ธฐ์—ด ์˜ค๋ฆ„์ฐจ์ˆœ ์ฒ˜๋ฆฌ

  • Concurrent Queue์—์„œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์ „ ์ž‘์—…์˜ ์ˆœ์„œ๋ฅผ ์ •ํ•˜๊ธฐ ์œ„ํ•ด Serial Queue์—์„œ ์ˆœ์„œ๋Œ€๋กœ ์ผ์„ Concurrent Queue๋กœ ๋ณด๋‚ด๋Š” ๋กœ์ง ๊ตฌํ˜„

๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œ ์ œํ•œ

  • Race Codition ๋ฐฉ์ง€
  • 2๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์ ‘๊ทผํ•ด๋„ Race Condition์€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ˆœ์„œ๋Œ€๋กœ ์ž‘์—…์ด ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„

enum ๊ตฌํ˜„

  • ์ผ์˜ ์ข…๋ฅ˜, ์ผ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ฅธ ์ฒ˜๋ฆฌ์‹œ๊ฐ„์„ enum์œผ๋กœ ๋”ฐ๋กœ ๋นผ์ฃผ์–ด ํ•˜๋“œ์ฝ”๋”ฉ ๋ฐฉ์ง€ ๋ฐ ์ฝ”๋“œ ์ •๋ฆฌ

Delegate ๊ตฌํ˜„

๐Ÿค”ย Step3 ๊ณ ๋ฏผํ–ˆ๋˜ ์ 

semaphore.wait()์˜ ์œ„์น˜

์˜ˆ๊ธˆ ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์€ํ–‰์›์€ 2๋ช…์ด๋ผ๋Š” ์กฐ๊ฑด์ด ์žˆ์–ด, ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œ์˜ ์ˆ˜๋ฅผ 2๊ฐœ๋กœ ์ œ์–ดํ•ด์ฃผ๊ธฐ ์œ„ํ•ดย semaphore๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.ย 

DispatchSemaphore๋Š”ย semaphore๋ฅผ ์นด์šดํŠธํ•˜๋Š” ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š”๋ฐ,ย semaphore.wait()์˜ ์œ„์น˜๋ฅผ ์–ด๋Š๊ณณ์— ์ž‘์„ฑํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”์ง€ ๊ณ ๋ฏผ์ด ๋˜์—ˆ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ, ์ฒซ๋ฒˆ์งธ๋Š” ๋น„๋™๊ธฐ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ count -1์„ ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๊ณ  ๋‘๋ฒˆ์งธ๋Š” ๋น„๋™๊ธฐ ์‹œ์ž‘ ์ „์— count๋ฅผ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.ย 

wait()๋Š” ๊ฐ’์— ์ ‘๊ทผํ–ˆ๋‹ค๊ณ  ์•Œ๋ฆฌ๋Š” ๋ฉ”์„œ๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ ๋น„๋™๊ธฐ๊ฐ€ ์‹œ์ž‘๋˜๋Š” ๋‚ด๋ถ€์— ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋‹ค.

// 1. ๋น„๋™๊ธฐ ๋‚ด๋ถ€์— ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•
case .deposit:
    depositQueue.async(group: workGroup) {
       semaphore.wait()
       taskTime = BankTask.deposit.processingTime
       self.bankClerk.handleTask(of: customer, until: taskTime)
       numberOfCustomer += 1
       semaphore.signal()
    }

// 2. ๋น„๋™๊ธฐ ์‹œ์ž‘ ์ „์— ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•
case .deposit:
    semaphore.wait()
    depositQueue.async(group: workGroup) {
       taskTime = BankTask.deposit.processingTime
       self.bankClerk.handleTask(of: customer, until: taskTime)
       numberOfCustomer += 1
       semaphore.signal()
    }

๊ณ ๊ฐ ๋Œ€๊ธฐ์—ด ์˜ค๋ฆ„์ฐจ์ˆœ ์ฒ˜๋ฆฌ

// before: ๊ณ ๊ฐ์˜ ๋ฒˆํ˜ธํ‘œ ์ˆœ์„œ๋Œ€๋กœ ์ผ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์ง€ ์•Š์Œ.
switch customer.task {
        case .deposit:
            depositQueue.async(group: workGroup) {
                semaphore.wait()
                self.bankClerk.handleTask(of: customer, until: BankTask.deposit.processingTime)
                numberOfCustomer += 1
                semaphore.signal()
            }

// after: ๊ณ ๊ฐ์˜ ๋ฒˆํ˜ธํ‘œ ์ˆœ์„œ๋Œ€๋กœ ์ผ์ฒ˜๋ฆฌ
switch customer.task {
         case .deposit:
             sequenceQueue.async {
                  depositQueue.async(group: workGroup) {
                      semaphore.wait()
                      self.bankClerk.handleTask(of: customer, until: BankTask.deposit.processingTime)
                      numberOfCustomer += 1
                      semaphore.signal()
                  }
              }

/*
sequenceQueue - Serial Queue
depositQueue - Concurrent Queue
*/

๋Œ€์ถœ(Loan)์„ ๋‹ด๋‹นํ•˜๋Š” ์ง์›์€ ํ•œ๋ช…์ด๋ผ Serial Queue๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋กœ ์ผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€๊ณ , ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” Serial Queue์˜ ํŠน์„ฑ์œผ๋กœ ์ธํ•ด ๋Œ€์ถœํ•˜๋Ÿฌ์˜จ ๊ณ ๊ฐ์˜ ์ˆœ์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ ์ถœ๋ ฅ

๊ทธ๋ฆฌ๊ณ  ์˜ˆ๊ธˆ(Deposit)์„ ๋‹ด๋‹นํ•˜๋Š” ์ง์›์€ ๋‘๋ช…์ด๋ผ Concurrent Queue๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ๋กœ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜์˜€์Œ

ํ•˜์ง€๋งŒ, ํ•ด๋‹น ๊ณผ์ •์—์„œ ๊ณ ๊ฐ์˜ ์ˆœ๋ฒˆ๋Œ€๋กœ ์ผ์ด ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ

ํŒŒ์•…ํ•œ ์›์ธ์œผ๋ก  Concurrent Queue์˜ ํŠน์„ฑ์ƒ ์ˆœ์„œ๋ฅผ ์ค‘์š”ํžˆ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์—์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ๋กœ ํŒŒ์•…ํ•˜์—ฌ ํ•ด๋‹น Task๋ฅผ Serial Queue๋กœ ๊ฐ์‹ธ์ฃผ์–ด ์ˆœ์„œ๋Œ€๋กœ Task๋ฅผ Concurrent Queue์— ๋„ฃ์–ด์ฃผ์–ด ์ฒ˜๋ฆฌํ•˜๊ฒŒ ํ•˜์—ฌ ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๊ตฌํ˜„

Untitled

ํ•˜์ง€๋งŒ ๊ฒฐ๊ณผ์ ์œผ๋กœ Task๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฑด Concurrent Queue์—์„œ ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น๋˜์–ด ์ฒ˜๋ฆฌ๋˜๋Š”๋ฐ ์œ„ ๊ณต์‹๋ฌธ์„œ์— ๋ช…์‹œ๋œ Concurrent Queue์˜ ํŠน์„ฑ์ƒ ์ˆœ์„œ๋ฅผ ์ค‘์š”ํžˆ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์ด ์ด์ƒํ•˜๋‹จ ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ , ์•ž์—์„œ Serial Queue๋ฅผ ๊ฑฐ์ณ ์ˆœ์„œ๋ฅผ ์ •ํ•ด์ค˜๋„ ๊ฒฐ๊ณผ๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ๊ณผ ์ƒ๊ด€์ด ์—†์„ ๊ฒƒ ๊ฐ™์€๋ฐ ์™œ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€?, ์ด์ „ ์ฝ”๋“œ๋ž‘ ๋˜‘๊ฐ™์€๊ฑฐ ์•„๋‹Œ๊ฐ€? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ ์ด๋Š” GCD์˜ ์˜์—ญ์ด๋ฉฐ, ์šฐ๋ฆฌ๋Š” sequenceQueue.async { }ย Serialํ•˜๊ฒŒย depositQueue.async(group: workGroup)์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œ์ผœ์„œ ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ž„์„ ์•Œ์•˜์Œ


Delegate

private func finishWork(workingTime: Double) {
    delegate?.didFinishWork(totalCustomer: totalCustomer, workingTime: workingTime)
    totalCustomer = 0
}

์€ํ–‰์˜ ์ผ์ด ๋๋‚˜๋ฉด ์€ํ–‰ ๋งˆ๊ฐ๋˜์—ˆ๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์€ย BankManager์˜ ์—ญํ• ์ด ์•„๋‹๊นŒ ํ•˜๋Š” ๊ณ ๋ฏผ์„ ํ•˜์˜€๊ณ , ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ์œ„ํ•ด delegation pattern์„ ํ™œ์šฉํ•˜์—ฌ ์€ํ–‰์˜ ์—…๋ฌด๊ฐ€ ๋๋‚ ์‹œ ๋งค๋‹ˆ์ €์—๊ฒŒ ์€ํ–‰ ์—…๋ฌด๊ฐ€ ๋๋‚ฌ๋‹ค๊ณ  ์•Œ๋ฆฌ๊ณ , ๋งค๋‹ˆ์ €๊ฐ€ ๋งˆ๊ฐ ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ๋ฐฉ์‹์„ ์ฑ„ํƒํ•˜์˜€์Œ


๊ตฌ์กฐ์ฒด ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ์˜ ํด๋กœ์ €๋Š” ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ

Bank ํƒ€์ž…์ด ๊ตฌ์กฐ์ฒด์ธ ๊ฒฝ์šฐ ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ ์•ˆ์˜ ํƒˆ์ถœ ํด๋กœ์ €๋Š” ๊ฐ’์„ ์บก์ฒ˜ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

Untitled

์ด์œ ๋Š” ํด๋กœ์ €๊ฐ€ ๊ฐ’์„ ์บก์ฒ˜ํ•  ๋•Œ ์›๋ณธ์˜ ๊ฐ’์„ ์บก์ฒ˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๊ตฌ์กฐ์ฒด ๋ณต์‚ฌ๋ณธ์„ ์บก์ฒ˜ํ•˜๊ธฐ๋•Œ๋ฌธ์— ์•„๋ฌด๊ฒƒ๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ Bank๋ฅผ ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.

์ฐธ๊ณ ๋งํฌ

๐Ÿ™‡โ€โ™‚๏ธย Step3 ๋ฐฐ์šด ์ 

  • ๋™๊ธฐ(Synchronous)์™€ ๋น„๋™๊ธฐ(Asynchronous)์˜ ์ดํ•ด
  • GCD
  • ์Šค๋ ˆ๋“œ
  • ํด๋กœ์ € ์บก์ณ

4๏ธโƒฃย Step4

๐Ÿ“ทย Step 4 UI

Untitled

  • ButtonStackView - Button x2
  • TimerStackView - Label x2
  • CustomerStatusStackView - StatusLabel + ScrollView + CustomerListStackView
  • CustomerListStackView - CustomerLabel

๐ŸŽฏย Step4 ๊ตฌํ˜„ ๋‚ด์šฉ

์ฝ”๋“œ๋กœ ๋ ˆ์ด์•„์›ƒ ๊ตฌํ˜„

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor? = nil,
                left: NSLayoutXAxisAnchor? = nil,
                bottom: NSLayoutYAxisAnchor? = nil,
                right: NSLayoutXAxisAnchor? = nil,
                paddingTop: CGFloat = 0,
                paddingLeft: CGFloat = 0,
                paddingBottom: CGFloat = 0,
                paddingRight: CGFloat = 0,
                width: CGFloat? = nil,
                height: CGFloat? = nil) {
        
        translatesAutoresizingMaskIntoConstraints = false
        
        if let top = top {
            topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
        }
        
        if let left = left {
            leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
        }
        
        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
        }
        
        if let right = right {
            rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
        }
        
        if let width = width {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }
        
        if let height = height {
            heightAnchor.constraint(equalToConstant: height).isActive = true
        }
    }
}

UIView์˜ Extension์„ ๊ตฌํ˜„ํ•˜์—ฌ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์„ฑ

์ด๋ฅผ ํ†ตํ•ด ๋ ˆ์ด์•„์›ƒ ์„ค์ • ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง€๊ณ  ๊น”๋”ํ•ด๋ณด์ด๋Š” ํšจ๊ณผ๊ฐ€ ์žˆ์—ˆ๋‹ค.

์Šคํฌ๋กค์„ ์œ„ํ•ด ์Šคํฌ๋กค ๋ทฐ ์œ„์— ์–น์–ด์ง€๋Š” ์Šคํƒ๋ทฐ์˜ ํฌ๊ธฐ๋ฅผ ์Šคํฌ๋กค๋ทฐ์— ๋งž์ถค

class CustomerStatusStackView: UIStackView {
		private func configLayout() {
        customerListScrollView.anchor(left: leftAnchor, right: rightAnchor)
        customerListStackView.anchor(top: customerListScrollView.topAnchor, left: customerListScrollView.leftAnchor, bottom: customerListScrollView.bottomAnchor, right: customerListScrollView.rightAnchor)
    }
}

์ปค์Šคํ…€ ๋ทฐ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ํ•ด๋‹น ๋ทฐ ์žฌ์‚ฌ์šฉ

class CustomerLabel: UILabel {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init(task: String, waitingNumber: Int) {
        self.init()
        configUI()
        setText(waitingNumber, task)
    }
}

class CustomerStatusStackView: UIStackView {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) hastitlenot been implemented")
    }
    
    convenience init(title: String, bgColor: UIColor) {
        self.init()
        configUI()
        configLayout()
        statusLabel.text = title
        statusLabel.backgroundColor = bgColor
    }
}

convenience init ์„ ๊ตฌํ˜„ํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํƒ€์ดํ‹€๊ณผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒ‰ ๋“ฑ์„ ๋ฐ›์•„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„

Timer ๊ตฌํ˜„

๊ณ ๊ฐ ์ถ”๊ฐ€ ๋ฒ„ํŠผ์˜ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•˜์„ ๋•Œ ํƒ€์ด๋จธ๊ฐ€ ์‹œ์ž‘๋˜๊ณ , ๊ณ ๊ฐ์˜ ์ผ์ฒ˜๋ฆฌ๊ฐ€ ๋ชจ๋‘ ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํƒ€์ด๋จธ๊ฐ€ ๋ฉˆ์ถ”๋„๋ก ๊ตฌํ˜„

๐Ÿค”ย Step4 ๊ณ ๋ฏผํ–ˆ๋˜ ์ 

์ง์›์ด ๊ณ ๊ฐ์˜ ์ผ์„ ์ฒ˜๋ฆฌ ์‹œ์ž‘ํ•˜๊ณ  ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ์˜ ๋™์ž‘ ๊ตฌํ˜„

๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ BankClerk ์˜ delegate์ด๋‹ค.

  • Delegate pattern์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง์›์ด ์ผ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์‹œ์ž‘ํ•˜์˜€์„ ๋•Œ ๋ทฐ์— CustomerLabel์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋„๋ก ๊ตฌํ˜„
  • Delegate pattern์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง์›์ด ์ผ์ฒ˜๋ฆฌ๋ฅผ ์ข…๋ฃŒํ•˜์˜€์„ ๋•Œ ๋ทฐ์˜ CustomerLabel์„ ์‚ญ์ œํ•ด์ฃผ๋„๋ก ๊ตฌํ˜„
extension ViewController: BankClerkDelegate {
    func bankClerkStartWork(waitingNumber: Int, task: String) {
        DispatchQueue.main.async { [self] in
        let customer = waitingLineStackView.removeLabel()
        customer.removeFromSuperview()

        workingLineStackView.addLabel(customer)
        }
    }
    
    func bankClerkFinishWork(waitingNumber: Int, task: String) {
        DispatchQueue.main.async { [self] in
            let customer = workingLineStackView.removeLabel()
            customer.removeFromSuperview()
        }
    }
}

class BankClerk {
		delegate?.bankClerkStartWork(waitingNumber: customer.waitingNumber, task: task)
    Thread.sleep(forTimeInterval: taskTime)
    delegate?.bankClerkFinishWork(waitingNumber: customer.waitingNumber, task: task)
}

๊ณ ๊ฐ์˜ ์ผ์ฒ˜๋ฆฌ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ ํ•  ๋™์ž‘ ๊ตฌํ˜„

Bank ์—์„œ์˜ ์ผ์ฒ˜๋ฆฌ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ ViewController์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ํƒ€์ด๋จธ๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๊ณ , View๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผํ–ˆ๋‹ค.

class ViewController: UIViewController {
		override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(stopTimer), name: .finishWork, object: nil
    }

		@objc func stopTimer() {
        timer.invalidate()
    }
}

class Bank {
		workGroup.notify(queue: .main) {
        NotificationCenter.default.post(name: .finishWork, object: nil)
    }
}

๊ณ ๊ฐ์˜ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ง์›๋“ค์€ ๋น„๋™๊ธฐ๋กœ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ด๋“ค์„ Group์œผ๋กœ ๋ฌถ์–ด ํ•ด๋‹น ๋น„๋™๊ธฐ ๋™์ž‘์ด ์ข…๋ฃŒ๋˜์—ˆ์„๋•Œ ๋™์ž‘์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” DispatchGroup.notify() ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ViewController์˜ NotificationCenter์— Notification์„ Postํ•˜๊ฒŒ๋” ๊ตฌํ˜„

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 100.0%