watchOS multiple toolbar items - swiftui

my goal is to have 2 buttons as a toolbar item in my WatchOS app, but even if I group them in a toolbargroup or place multiple toolbarItems on their own, there is only one that is shown. Any idea what is wrong here ?
.toolbar {
ToolbarItem {
Button("1") {
}
}
ToolbarItem {
Button("2") {
}
}
}
or
.toolbar {
ToolbarGroup {
Button("1") {
}
Button("2") {
}
}
}

Ok, found it. Placing them in a Stack (V or H) works
.toolbar {
ToolbarGroup {
VStack {
Button("1") {
}
Button("2") {
}
}
}
}

Related

SwiftUI platform testing deuglification (composing view hierarchies)

I could use a way or two to make this not as ugly moving the filler for HStack/List into a common helper method or make a helper for wrapper of the ForEach to prebuild a portion of a view hierarchy somehow?
var body: some View {
NavigationView {
if horizontalScroll {
ScrollView (.horizontal, showsIndicators: false) {
HStack {
ForEach(videos) { video in
Button {
selectedVideo = video
} label: {
VideoRow(video: video)
}
}
}
}
} else {
List {
// makeEmbeddedVideoPlayer()
ForEach(videos) { video in
Button {
selectedVideo = video
} label: {
VideoRow(video: video)
}
}
}
.navigationTitle("Travel Vlogs")
}
}
.fullScreenCover(item: $selectedVideo) {
embeddedVideoRate = 1.0
} content: { item in
makeFullScreenVideoPlayer(for: item)
}
}
var horizontalScroll: Bool {
#if os(tvOS)
return true
#else
return false
#endif
}
A naive attempt to make a common helper yielded this
What's the return type for the guts of List/Hstack?

ForEach Loop in Swift for Buttons

I want to use a ForEach loop to simplify the following code:
.toolbar {
ToolbarItem() {
Button {
}
label: {
Image(systemName: "magnifyingglass")
}
}
ToolbarItem() {
Button {
}
label: {
Image(systemName: "plus")
}
}
}
But it's not working. My approach only creates the "magnifyingglass" button.
My approach:
let toolbar = ["magnifyingglass", "plus"]
.toolbar {
ToolbarItem() {
ForEach(toolbar.indices) { index in
Button {
}
label: {
Image(systemName: toolbar[index])
}
}
}
}
you could try this:
struct ContentView: View {
let toolbar = ["magnifyingglass", "plus"]
var body: some View {
NavigationView {
Text("testing")
.toolbar {
ToolbarItem() {
HStack { // <--- here
ForEach(toolbar.indices) { index in
Button { }
label: { Image(systemName: toolbar[index]) }
}
}
}
}
}
}
}
import SwiftUI
struct ContentView: View {
let toolbar = ["magnifyingglass", "plus"]
var body: some View {
NavigationView {
Text("Toolbar")
.navigationTitle("")
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
ForEach(toolbar, id: \.self) { index in
Button {
} label: {
Image(systemName: ("\(index)"))
}
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I suggest (not tested) to put the for loop outside of ToolbarItem() :
let toolbar = ["magnifyingglass", "plus"]
.toolbar {
ForEach(toolbar.indices) { index in
ToolbarItem() {
Button {
}
label: {
Image(systemName: toolbar[index])
}
}
}
}

SwiftUI navigation from collapse list

I have collapse list in main view, i wanna to go in another view when i tap in a child of section in list, i tried but it didint work. Nothing didnt change when i tapped. What im doing wrong ?
func sectionIndex(section : Theme) -> Int {
userData.data.firstIndex(where: {$0.name == section.name})!
}
var body: some View {
NavigationView {
List {
ForEach(userData.data) { section in
Section(header: HeaderView(section: section)
.onTapGesture {
self.userData.data[self.sectionIndex(section: section)].expanded.toggle()
}, footer: EmptyView()) {
if section.expanded {
ForEach(section.questions!) { question in
QuoteView(question: question)
.onTapGesture {
NavigationLink(destination: DetailView()) {
Text("Do Something")
}
print("dsdsw")
}
}
}
}
}
}
}
}
}
struct DetailView : View {
var body: some View {
Text("Hello World B")
}
}
I don't know what is QuoteView, but try to put link into background of that view, NavigationView should handle link in it automatically, ie.
ForEach(section.questions!) { question in
QuoteView(question: question)
.background (
NavigationLink(destination: DetailView()) {
EmptyView() // << content is not needed here
}
)
}

SwiftUI error: Generic parameter 'Label' could not be inferred Explicitly specify the generic arguments to fix this issue `

I can't find the issue for this error. I don't think the compiler is giving a meaningful error message.
Why self.book.map {} does not work here?
var body: some View {
List {
ForEach(cards) { card in
if (!self.showMarkedOnly || card.marked) {
ZStack() {
CardView(card: card).frame(maxWidth: 400)
.contextMenu() {
if self.editMode {
Button(action: {}) { HStack { Image(systemName: "square.and.pencil"); Text("Edit") } }
Button(action: {}) { HStack { Image(systemName: "trash"); Text("Delete") } }
// self.book.map { Button(action: { self.onRemoveCard(card, fromBook: $0) }) { HStack { Image(systemName: "folder.badge.minus"); Text("Remove from current Book") } } } // ERROR happens here
if self.book != nil {
Button(action: { self.onRemoveCard(card, fromBook: self.book!) }) { HStack { Image(systemName: "folder.badge.minus"); Text("Remove from current Book") } }
} // <------- this works!!! but I prefer to not use "self.book!"
} else {} }
}
}
}
}
}
This is a case of nesting closures interfering with $0. Try this:
self.book.map { book in Button(action: { self.onRemoveCard(card, fromBook: book) }) { ... }

List with two different entities based on segment selection

I don't know if it's possible. I would like that depending on what is selected in the segments the list changes Entity. Similar to what Apple does in its examples with Landmarks but instead of favorites ....
var body: some View {
VStack {
GeometryReader { geometry in
TabView {
NavigationView {
List {
VStack {
Picker(selection: self.$userData.tipoSeleccionado,
label: Text("....?")) {
ForEach(0..<self.Tipo.count) { index in
Text(self.Tipo[index]).tag(index)
}
} .pickerStyle(SegmentedPickerStyle())
}
if self.containedViewType == .tipo1 {
ForEach(self.listadoTipo1, id: \.self) { elemento in
NavigationLink(destination: Tipo1Detail(elementoSeleccionado: elemento)) {
Tipo1Row(tipo: elemento)
} .navigationBarTitle("Busqueda")
.navigationBarHidden(false)
} .onDelete(perform: self.removeTipo1)
}
if self.containedViewType == .tipo2 {
ForEach(self.listadoTipo2, id: \.self) { elemento in
NavigationLink(destination: Tipo2Detail(elementoSeleccionado: elemento)) {
Tipo2Row(tipo: elemento)
} .navigationBarTitle("Busqueda")
.navigationBarHidden(false)
} .onDelete(perform: self.removeTipo2)
}
} // List
}
}
}
}
}