๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์ด๋ชจ์ €๋ชจ/SwiftUI

Present, FullScreen ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ธฐ

by ARpple 2023. 12. 12.

๐Ÿšจ SwiftUI๋Š” UIKit์—์„œ์˜ Present๋ฅผ ๋’ค์— ์‹œํŠธ๋ฅผ ์ผ๋ถ€ ๊ฐ€๋ฆฌ๋ฉฐ Swipe๋กœ ๋‚ด๋ฆด ์ˆ˜ ์žˆ๋Š” Present, ๋’ค ์‹œํŠธ๋ฅผ ์ „๋ถ€ ๊ฐ€๋ฆฌ๋ฉฐ Swipe๋กœ ๋‚ด๋ฆด ์ˆ˜ ์—†๋Š” Fullscreen ๋‘ ๊ฐ€์ง€ ๋ชจ๋””ํŒŒ์ด์–ด๋กœ ๋‚˜๋ˆ„์—ˆ๋‹ค. ์ด ๋‘˜์„ ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค.

๊ธฐ์กด ์ฝ”๋“œ์™€ ๋ฌธ์ œ์ 

  • ๊ธฐ์กด ์ฝ”๋“œ) Swift Enum ์—ฐ๊ด€๊ฐ’์„ ํ†ตํ•œ Present, FullScreen ๋ถ„๋ฆฌ ์ƒํƒœ ์ผ€์ด์Šค ์ƒ์„ฑ
extension ProfileView{
    enum SheetType:String, Identifiable{
        var id: String{ self.rawValue}
        case profile // ํ”„๋กœํŒŒ์ผ ๋ทฐ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ์ฒ˜๋ฆฌ
    }
    enum FullscreenType:String, Identifiable{
        var id: String{ self.rawValue}
        case settings // ์„ค์ • ๋ทฐ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ์ฒ˜๋ฆฌ
    }
    enum PresentType:Equatable{
        case sheet(SheetType)
        case fullscreen(FullscreenType)
    }
...
}
  • ๋ฌธ์ œ 1) ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ์˜ ๋ณต์žกํ•จ๊ณผ ๋ทฐ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— @State ์ฝ”๋“œ ์ฆ๊ฐ€
struct ProfileView: View{
...
    @State var presentType:PresentType? = nil
    @State var sheetType: SheetType? = nil
    @State var fullScreenType: FullscreenType? = nil
...
}
  • ๋ฌธ์ œ 2) ์—ฐ๊ด€ ๊ฐ’์„ ์ด์šฉํ•œ ๋ทฐ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ ๋กœ์ง ๊ตฌ์„ฑ
struct ProfileView: View{
...
.onChange(of: presentType, perform: { value in
                            switch value{
                            case .fullscreen(let fullScreen):
                                self.fullScreenType = fullScreen
                                self.sheetType = nil
                            case .sheet(let sheet):
                                self.sheetType = sheet
                                self.fullScreenType = nil
                            case .none: break
                            }
                            self.presentType = nil
                        })
...
}

⇒ ์‚ฌ์‹ค ์ด ๋กœ์ง์€ Extension์œผ๋กœ ๋นผ๋„ ๋จ

โœ… ๋ทฐ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ์˜ ์ˆ˜๋ฅผ ์ค„์—ฌ๋ณด์ž!!

ํ•ด๊ฒฐ ๋ฐ ํ•œ๊ณ„์ 

ํ•ด๊ฒฐ

  • ๋ชจ๋”” ํŒŒ์ด์–ด ์ƒ์„ฑ ๋ฐ ๋‚ด๋ถ€ ๋กœ์ง ์ฒ˜๋ฆฌ
extension ProfileView{
...
struct SheetModifier<A: View,B:View>: ViewModifier{
        @Binding var presentType:PresentType?
        @ViewBuilder var sheet:((SheetType) -> A)
        @ViewBuilder var fullScreen:((FullscreenType) -> B)
        @State private var fullScreenType: ProfileView.FullscreenType? = nil
        @State private var sheetType: SheetType? = nil
        func body(content: Content) -> some View {
            content
                .sheet(item: $sheetType, content:sheet)
                .fullScreenCover(item: $fullScreenType,content: fullScreen)
                .onChange(of: presentType, perform: { value in
                    switch value{
                    case .fullscreen(let fullScreen):
                        self.fullScreenType = fullScreen
                        self.sheetType = nil
                    case .sheet(let sheet):
                        self.sheetType = sheet
                        self.fullScreenType = nil
                    case .none: break
                    }
                    self.presentType = nil
                })
        }
    }
}
  • ๋ทฐ ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ ๋‚ด๋ถ€์— extension
struct ProfileView{
    ...
}
fileprivate extension View{
    func present<A:View,B:View>(presentType:Binding<ProfileView.PresentType?>,sheet:@escaping ((ProfileView.SheetType) -> A),fullScreen:@escaping ((ProfileView.FullscreenType) -> B))->some View{
        self.modifier(ProfileView.SheetModifier(presentType: presentType, sheet: sheet, fullScreen: fullScreen))
    }
}
  • ์‚ฌ์šฉ ์˜ˆ์‹œ
struct ProfileView{
    ...
    @State var presentType:PresentType? = nil
    ...
            .present(presentType: $presentType) { item in
                        switch item{
                        case .profile: ProfileEditView()
                        }
                    } fullScreen: { item in
                        switch item{
                        case .settings: SettingView()
                        }
                    }
}

ํ•œ๊ณ„์ 

  1. Detent (Sheet ๋†’์ด๋ฅผ ์ปค์Šคํ…€ ํ•˜๋Š” ๊ธฐ๋Šฅ) ์ฒ˜๋ฆฌ๋Š” ํ•  ์ˆ˜ ์—†๋‹ค.
  2. ๊ฐ๊ฐ์˜ ๋ทฐ ๋งˆ๋‹ค ์•Œ๋งž๋Š” PresentType, FullscreenType, ๋ชจ๋””ํŒŒ์ด์–ด๋ฅผ ์ง์ ‘ ์ž…๋ ฅ ํ•ด์•ผํ•œ๋‹ค.
  3. PresentType, FullScreenType์ด ๋ทฐ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•œ Enum ํƒ€์ž…์œผ๋กœ ๊ธฐ์กด .sheet์—์„œ ์›ํ•˜๋Š” ์ˆœ์ˆ˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ๊ณผ ๋‹ฌ๋ฆฌ ์ถ”๊ฐ€์ ์ธ ๋กœ์ง ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Œ“๊ธ€