mngon
article thumbnail
์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ ์ด์Šˆ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ , ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์—ฌ ์ปจํŠธ๋ฆฌ๋ทฐํ„ฐ๊นŒ์ง€ ๋˜๋Š” ์ข‹์€ ๊ฒฝํ—˜์„ ํ•˜์—ฌ ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

์•ฑ ๊ฐœ๋ฐœ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๊ณผ๋„ํ•˜๊ฒŒ ๋งŽ๋‹ค๋Š” ๊ฒƒ์„ ๋А๋ผ๊ณ  ๋ฉ”๋ชจ๋ฆฌ ๊ทธ๋ž˜ํ”„๋ฅผ ๋ถ„์„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ถ„์„ ๊ฒฐ๊ณผ, ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž˜ ์“ฐ๊ณ  ์žˆ๊ณ  ๋Œ€์ฒดํ•˜๊ธฐ ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์Šˆ๋ฅผ ์ง์ ‘ ํ•ด๊ฒฐํ•ด๋ณด๊ณ ์ž ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์˜ ๋ฐœ๊ฒฌ

๋ฉ”๋ชจ๋ฆฌ ๋ถ„์„์„ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์—์„œ ๋ฐœ์ƒํ•œ ๊ฒƒ์ผ ๊ฑฐ๋ผ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋А ๋ถ€๋ถ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด Intruments๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋ถ„์„ ๋ฐ ํ•ด๊ฒฐ๊ณผ์ •

์ฝ”๋“œ๋ฅผ ๋ถ„์„ ๊ฒฐ๊ณผ ํŒŒ์•…ํ•œ ์ •๋ณด์ž…๋‹ˆ๋‹ค.

  • DispatchWorkItem์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด DispathWorkHolder
  • DispatchQueue ํ˜น์ธ DispatchGroup์—์„œ ์ˆ˜ํ–‰ํ•  Task์˜ ์ •๋ณด๋ฅผ ์บก์Аํ™”ํ•˜๋Š” ๊ฐ์ฒด DispatchWorkItem
  • ์ง€์ •ํ•œ ์‹œ๊ฐ„ ์ดํ›„์— ๋ทฐ๊ฐ€ ์ž๋™์œผ๋กœ ์‚ฌ๋ผ์ง€๊ฒŒ ํ•˜๋Š” ํ•จ์ˆ˜ setupAutohide()
  • ๋ทฐ๊ฐ€ ์‚ฌ๋ผ์ง€๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด setupAutohide() ๋‚ด๋ถ€์—์„œ DispatchWorkHolder๋ฅผ ๋‹ค์‹œ ์ฐธ์กฐ

๋งˆ์ง€๋ง‰ ํ•จ์ˆ˜์—์„œ DispatchWorkHolder์˜ Reference count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋ฉด์„œ retain cycle์ด ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋งˆ์ง€๋ง‰ ๊ณผ์ •์—์„œ Reference count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์„ ๋ฐฉ๋ฒ•์„ ๊ณต๋ถ€ํ•˜๊ณ , ์ƒ๊ฐํ•ด ๋ณด๊ณ , ์ ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

class -> struct๋กœ ๋ณ€๊ฒฝ

DispatchWorkHolder๋Š” class์ด๋ฉฐ ์ฐธ์กฐ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— Referece count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ๋‹จ์ˆœํ•˜๊ฒŒ ๊ฐ’ ํƒ€์ž…์ธ struct๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ•˜์—ฌ DispatchWorkHolder๋ฅผ struct๋กœ ๋ฐ”๊ฟ”๋ณด์•˜์Šต๋‹ˆ๋‹ค. 

struct DispatchWorkHolder {
    var work: DispatchWorkItem?
}

public struct FullscreenPopup<Item: Equatable, PopupContent: View>: ViewModifier {

    .
    .
    .

    /// holder for autohiding dispatch work (to be able to cancel it when needed)
    private var dispatchWorkHolder = DispatchWorkHolder()
    
    .
    .
    .

    func setupAutohide() {
        // if needed, dispatch autohide and cancel previous one
        if let autohideIn = autohideIn {
            dispatchWorkHolder.work?.cancel()

            // Weak reference to avoid the work item capturing the struct,
            // which would create a retain cycle with the work holder itself.

            dispatchWorkHolder.work = DispatchWorkItem(block: { [weak isPresentedRef, weak itemRef] in
                isPresentedRef?.value.wrappedValue = false
                itemRef?.value.wrappedValue = nil
                dismissSource = .autohide
            })
            if sheetPresented, let work = dispatchWorkHolder.work {
                DispatchQueue.main.asyncAfter(deadline: .now() + autohideIn, execute: work)
            }
        }
    }

}

 

ํ•˜์ง€๋งŒ ์ œ๊ฐ€ ๊ฐ„๊ณผํ•œ ๊ฒƒ์ด ์žˆ์—ˆ๋Š”๋ฐ, ๊ตฌ์กฐ์ฒด๋Š” ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๋Š” FullscreenPopup์ด ๊ตฌ์กฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

 

weak self

์•ฝํ•œ ์ฐธ์กฐ๋ฅผ ํ•˜๋ฉด Reference count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. setupAutohide() ๋‚ด๋ถ€์˜ ํด๋กœ์ €์—์„œ DispatchWorkHolder๋ฅผ ์žฌ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— cycle์ด ์ƒ๊ธด๋‹ค๊ณ  ์ƒ๊ฐํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํด๋กœ์ € ๊ตฌ๋ฌธ์—์„œ weak self๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ˜„์žฌ FullscreenPopup์€ ๊ตฌ์กฐ์ฒด์ด๊ณ  ์ด๋Š” ๊ฐ’ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— reference๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— self์˜ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค.(๋˜ ๋งŒ์•ฝ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ–ˆ๋”๋ผ๋„ ์ž˜๋ชป ์ƒ๊ฐํ•œ ํƒ“์— ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์—ˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.๐Ÿ˜…) ์ด๋Š” ์ฒซ ๋ฒˆ์งธ ์‹œ๋„์™€์™€ ๋น„์Šทํ•œ ์ƒํ™ฉ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ง์ ‘ ํ• ๋‹น ํ•ด์ œ

Reference count๋ฅผ ์ค„์ด๋Š” ๋ฐฉ๋ฒ• ์ค‘์— ํ•˜๋‚˜๋กœ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ nil๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์ข…์ ์œผ๋กœ ์ƒ๊ฐํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ์‹œ์ ์— DispatchWorkIteam์„ nil๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

func setupAutohide() {
    // if needed, dispatch autohide and cancel previous one
    if let autohideIn = autohideIn {
        dispatchWorkHolder.work?.cancel()
        
        // Weak reference to avoid the work item capturing the struct,
        // which would create a retain cycle with the work holder itself.
        
        dispatchWorkHolder.work = DispatchWorkItem(block: { [weak isPresentedRef, weak itemRef] in
            isPresentedRef?.value.wrappedValue = false
            itemRef?.value.wrappedValue = nil
            dismissSource = .autohide
            dispatchWorkHolder.work = nil
        })
        if sheetPresented, let work = dispatchWorkHolder.work {
            DispatchQueue.main.asyncAfter(deadline: .now() + autohideIn, execute: work)
        }
    }
}

์ด ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๋ก  ๋ฐ ํ›„๊ธฐ

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

merge๊นŒ์ง€ ํ•ด์ฃผ์—ˆ๋‹ค. ์ธ์ •๋ฐ›์€ ๊ธฐ๋ถ„์ด๋‹ค ใ…Žใ…Žใ…Žใ…Žใ…Ž

https://github.com/exyte/PopupView

 

GitHub - exyte/PopupView: Toasts and popups library written with SwiftUI

Toasts and popups library written with SwiftUI. Contribute to exyte/PopupView development by creating an account on GitHub.

github.com

 

profile

mngon

@๋ง๊ณค

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!