관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] 튜토리얼 - 20. iOS앱 프로젝트에 macOS 맥북 앱 UI 구현 방법, Toolbar, Picker 사용방법 (4) 본문

iOS 튜토리얼 (SwiftUI)

[iOS - SwiftUI] 튜토리얼 - 20. iOS앱 프로젝트에 macOS 맥북 앱 UI 구현 방법, Toolbar, Picker 사용방법 (4)

jake-kim 2022. 7. 23. 23:03

* 프로젝트 파일은 애플 튜토리얼 사이트나 이전 포스팅 글 참고

ToolBar, Picker로 맥북앱에 어울리는 UI 구현 방법

  • Toolbar 사용 방법
    • .toolbar로 바로 추가
    • LandmarkList.swift에 추가
수정 전 수정 후
var body: some View {
  NavigationView {
    List {
      Toggle(isOn: $showFavoritesOnly) {
        Text("Favorites only")
      }
      
      ForEach(filteredLandmarks) { landmark in
        NavigationLink {
          LandmarkDetail(landmark: landmark)
        } label: {
          LandmarkRow(landmark: landmark)
        }
      }
    }
    .navigationTitle("Landmarks")
    .frame(minWidth: 300)
    .toolbar {
      ToolbarItem {
        Menu {
          
        } label: {
          Label("Filter", systemImage: "slider.horizontal.3")
        }
      }
    }
  }
}
  • toolbar안 Munu 클로저에 Toggle을 넣으면 해당 버튼을 눌러서 옵션 확인이 가능
    • 또, 누를때마다 토글되어 데이터에도 바인딩이 되어야 하므로 @State 변수에 바인딩

var body: some View {
  NavigationView {
    List {
      Toggle(isOn: $showFavoritesOnly) {
        Text("Favorites only")
      }
      
      ForEach(filteredLandmarks) { landmark in
        NavigationLink {
          LandmarkDetail(landmark: landmark)
        } label: {
          LandmarkRow(landmark: landmark)
        }
      }
    }
    .navigationTitle("Landmarks")
    .frame(minWidth: 300)
    .toolbar {
      ToolbarItem {
        Menu {
          Toggle(isOn: $showFavoritesOnly) { // <-
            Label("Favorites only", systemImage: "star.fill")
          }
        } label: {
          Label("Filter", systemImage: "slider.horizontal.3")
        }
      }
    }
  }
}
  • Favorites only라는 메뉴 아이템 뿐만이 아닌 다른 아이템도 추가하기위해 enum으로 타입을 정의
    • 아래 영상은 밑에서 구현할 UI

// LandmarkList.swift

@State private var filter = FilterCategory.all

enum FilterCategory: String, CaseIterable, Identifiable {
  case all = "All"
  case lakes = "Lakes"
  case rivers = "Rivers"
  case mountains = "Mountains"
  
  var id: FilterCategory { self }
}
  • 리스트에 들어가는 아이템에서 위에서 추가한 데이터 filter를 추가
    • 툴바에 filter 관련 버튼을 넣을 것이고, 이 버튼을 누르는 것에따라서 데이터 필터가 되어야하므로 선언
var filteredLandmarks: [Landmark] {
  modelData.landmarks.filter { landmark in
    (!showFavoritesOnly || landmark.isFavorite)
    && (filter == .all || filter.rawValue == landmark.category.rawValue) // <-
  }
}
  • Picker를 사용하여 구현
    • Picker라는 것은 목록이 있고 그 중에서 하나를 선택하면 다른 하나는 취소되는 "라디오 버튼" 형태

.toolbar {
  ToolbarItem {
    Menu {
      Picker("Category", selection: $filter) { // <-
        ForEach(FilterCategory.allCases) { category in
          Text(category.rawValue).tag(category)
        }
      }
      .pickerStyle(.inline)
      
      Toggle(isOn: $showFavoritesOnly) {
        Label("Favorites only", systemImage: "star.fill")
      }
    } label: {
      Label("Filter", systemImage: "slider.horizontal.3")
    }
  }
}

 

cf) 만약 Pikcer를 사용하지 않고 Text만 구현할 경우, 라디오 버튼으로 나오지 않는 것

  • NavigationTitle도 동적으로 변경해주고 싶은 경우, title 프로퍼티를 선언하고 navigationTitle에도 적용
  var title: String { // <-
    let title = filter == .all ? "Landmarks" : filter.rawValue
    return showFavoritesOnly ? "Favorite \(title)" : title
  }
  
  var body: some View {
    NavigationView {
      List {
      ...
      }
      .navigationTitle(title) // <-
  • NavigationView 두 번째 뷰에 Text 추가
추가 전 추가 후
  • iOS에서 Toolbar와 Picker를 이용하여 구현하면 Mac 앱에도 자동으로 자연스럽게 구현되어있는 것을 확인이 가능

cf) 맥 앱은 NavigationLink로 화면전환 시, iOS의 navigation push와 다르게 오른쪽에 화면이 뜨는 형태

  • 맵 앱의 오른쪽 NavigationLink하면 나오는 화면이 비어있으므로 placeholder를 추가하려면, NavigationView의 subView로 Text를 추가하면 적용

var body: some View {
  NavigationView {
    List {
      ...
    }
    .navigationTitle(title)
    .frame(minWidth: 300)
    .toolbar {
      ...
    }
    
    Text("Select a Landmark") // <-
  }
}

 

* macOS 나머지 UI 구현 방법 이어서, 다음 포스팅 글 참고

* 참고

https://developer.apple.com/tutorials/swiftui/creating-a-macos-app

Comments