apple/SwiftUI & Combine

[iOS] NavigationSplitView

lgvv 2023. 8. 5. 00:50

NavigationSplitView

 

https://developer.apple.com/documentation/swiftui/navigationsplitview

 

NavigationSplitView | Apple Developer Documentation

A view that presents views in two or three columns, where selections in leading columns control presentations in subsequent columns.

developer.apple.com

 

✅ 목차

NavigationSplitView Overview

UI 예시

init - NavigationSplitViewVisibility

init - NavigationSplitViewColumn

Customize - navigationSplitViewStyle

Sample Code

 

 

⚙️ 개발환경

XCode 15.0 beta 2

최소타겟

단, preferredCompactColunm을 사용하지 않는다면 16.0으로도 가능.

 

NavigationSplitView Overview

NavigationSplitView는 2개 혹은 3개의 칼럼으로 화면을 표시하여, 사용자 경험을 향상.

 

 

NavigationSplitView의 기본 구조

        NavigationSplitView(columnVisibility: $visibility, 
                            preferredCompactColumn: $columns) {
             // 사이드 바 영역
        } content: {
             // 컨텐트 영역
        } detail: {
             // 디테일 영역
        }

 

NavigationSplitView의 경우 반드시 init(sidebar:, detail:)이 존재해야함.

 

 

UI 예시 

아이패드 - 가로

아이패드 - 세로

아이폰 

맥북

VisionOS의 경우에는 동일. 

 

iPad - 가로
iPad - 세로

 

iPhone
MacOS

 

init - NavigationSplitViewVisibility

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)

 

들어가기 전, 용어정리.

leading과 trailing은 우리가 레이아웃 잡을 때 자주 보았을 것임.

우리나라 기준으로는 leading은 왼쪽, trailing은 오른쪽임.

 

그러나, 어떤 국가의 경우에는 오른쪽에서 왼쪽으로 읽으므로, leading이 오른쪽 trailing이 왼쪽이 된다.

 

 

 - detailOnly: 다 숨기고 오직 가장 trailiing에 위치한 것만 보여줌 (우리나라 기준 오른쪽)

    - 그러니까 결국 디테일 부분의 뷰만 보임

 - doubleColums: 가장 왼쪽 칼럼 숨김

   - 그러니까 결국 사이드바만 숨김

 - all: 다 보여줌

   - 다 보여줌

 - automatic: 현재 컨텍스트에 맞게 알아서 해줌

 

 

Note> 몇몇 플랫폼에서는 해당 옵션이 적용되지 않는데, macOS서는 컨텐트 영역 항상 보여줌.

 

 

init - NavigationSplitViewColumn

@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)

 

자 생각해보자.

아이폰이나 애플 워치의 경우에는  세개의 스택이 아니라 두개의 스택으로 표현된다.

 

그렇다면 NavigationSplitView에서 위에 있는 사이드바 > 컨텐트 > 디테일로 위치하기에 그 2개의 스택은 언제나

사이드바와 컨텐트였다.

 

그러나 사이드바와 디테일을 사용하고 싶은 경우에는?

해당 옵션을 주어서 사이드바 > 디테일 이렇게 조정이 가능하다.

 

 

Customize - navigationSplitViewStyle

 

.navigationSplitViewStyle(.balanced)

 

 

 

Sample Code

//
//  ContentView.swift
//  NavigationSplitView
//
//  Created by Hamlit Jason on 2023/08/05.
//

import SwiftUI

struct ContentView: View {
    var 카페리스트: [Cafe] = [
        Cafe.스타벅스,
        Cafe.엔바이콘,
        Cafe.공차,
        Cafe.이디야
    ]
    
    @State private var selection = Set<Cafe.ID>()
    @State private var visibility: NavigationSplitViewVisibility = .all
    @State private var columns: NavigationSplitViewColumn = .detail
    
    var body: some View {
        NavigationSplitView(columnVisibility: $visibility,
                            preferredCompactColumn: $columns) {
            List(카페리스트, selection: $selection) { cafe in
                Text(cafe.name)
            }
        } content: {
            if let selectedCafe = 카페리스트.first(where: { $0.id == selection.first }) {
                Text("컨텐트 영역 - \(selectedCafe.name)")
            } else {
                Text("컨텐트 영역 - 카페를 선택해주세요.")
            }
        } detail: {
            if let selectedCafe = 카페리스트.first(where: { $0.id == selection.first }) {
                Text("디테일 영역 - \(selectedCafe.name)")
            } else {
                Text("디테일 영역 - 카페를 선택해주세요.")
            }
        }
        .navigationSplitViewStyle(.automatic)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Cafe: Identifiable, Hashable {
    var id: String { self.name }
    
    var name: String
}

extension Cafe {
    static let 스타벅스 = Cafe.init(name: "스타벅스")
    static let 엔바이콘 = Cafe.init(name: "엔바이콘")
    static let 이디야 = Cafe.init(name: "이디야")
    static let 공차 = Cafe.init(name: "공차")
}