Picker with SegmentPickerStyle() doesn’t show picker title in SwiftUI - swiftui

I created a segment picker for select gender in that segment picker I have to option one for Male and another for Female. Picker is working fine But set title on with picker it’s not showing. I set title Select Gender which is not showing as a title on the Picker.
struct ManagerChildrenView: View {
//MARK: Properties
#State var selectedGender = 0
let genders = ["Male", "Female"]
var body: some View {
Form{
Section{
Picker("Select Gender", selection: $selectedGender) {
ForEach(0..<genders.count) { index in
Text(self.genders[index]).tag(index).font(.title)
}
}.pickerStyle(SegmentedPickerStyle())
}
}
}
}
Screenshot:

Label is not used for SegmentedPickerStyle. Instead you can use the following approach
HStack {
Text("Select Gender")
Picker("", selection: $selectedGender) {
ForEach(0..<genders.count) { index in
Text(self.genders[index]).tag(index).font(.title)
}
}.pickerStyle(SegmentedPickerStyle())
}

Related

How to customize picker page selection

I have a standard picker in a list, customized in dark colors.
When I tap on the picker, it opens the page with the choices, but the background is white, and I would like it to be black.
Didn't succeed to find the appropriate settings :(
Thanks for your help
My code :
import SwiftUI
let choices = ["red", "blue", "yellow"]
struct test4: View {
#State private var myColor: String = choices[0]
var body: some View {
VStack {
List {
Picker(selection: $myColor, label: Text("Type")) {
ForEach(choices, id: \.self) { col in
Text(col).foregroundColor(Color.gray)
}
}
.listRowBackground(Color.row)
}
}
.background(Color.black)
}
}
Page with the picker
Picker selection
Use instead preferred color scheme, like
VStack {
// List here ...
}
//.background(Color.black)
.preferredColorScheme(.dark) // << use this !!

SwiftUI: Switch .sheet on enum, does not work

I have two Modal/Popover .sheet's I would like to show based on which button is pressed by a user. I have setup an enum with the different choices and set a default choice.
Expected behaviour:
When the user selects any choice, the right sheet is displayed. When the user THEN selects the other choice, it also shows the correct sheet.
Observed behaviour:
In the example below, when the user first picks the second choice, the first sheet is shown and will continue to show until the user selects the first sheet, then it will start to switch.
Debug printing shows that the #State variable is changing, however, the sheet presentation does not observe this change and shows the sheets as described above. Any thoughts?
import SwiftUI
//MARK: main view:
struct ContentView: View {
//construct enum to decide which sheet to present:
enum ActiveSheet {
case sheetA, sheetB
}
//setup needed vars and set default sheet to show:
#State var activeSheet = ActiveSheet.sheetA //sets default sheet to Sheet A
#State var showSheet = false
var body: some View {
VStack{
Button(action: {
self.activeSheet = .sheetA //set choice to Sheet A on button press
print(self.activeSheet) //debug print current activeSheet value
self.showSheet.toggle() //trigger sheet
}) {
Text("Show Sheet A")
}
Button(action: {
self.activeSheet = .sheetB //set choice to Sheet B on button press
print(self.activeSheet) //debug print current activeSheet value
self.showSheet.toggle() //trigger sheet
}) {
Text("Show Sheet B")
}
}
//sheet choosing view to display based on selected enum value:
.sheet(isPresented: $showSheet) {
switch self.activeSheet {
case .sheetA:
SheetA() //present sheet A
case .sheetB:
SheetB() //present sheet B
}
}
}
}
//MARK: ancillary sheets:
struct SheetA: View {
var body: some View {
Text("I am sheet A")
.padding()
}
}
struct SheetB: View {
var body: some View {
Text("I am sheet B")
.padding()
}
}
With some very small alterations to your code, you can use sheet(item:) for this, which prevents this problem:
//MARK: main view:
struct ContentView: View {
//construct enum to decide which sheet to present:
enum ActiveSheet : String, Identifiable { // <--- note that it's now Identifiable
case sheetA, sheetB
var id: String {
return self.rawValue
}
}
#State var activeSheet : ActiveSheet? = nil // <--- now an optional property
var body: some View {
VStack{
Button(action: {
self.activeSheet = .sheetA
}) {
Text("Show Sheet A")
}
Button(action: {
self.activeSheet = .sheetB
}) {
Text("Show Sheet B")
}
}
//sheet choosing view to display based on selected enum value:
.sheet(item: $activeSheet) { sheet in // <--- sheet is of type ActiveSheet and lets you present the appropriate sheet based on which is active
switch sheet {
case .sheetA:
SheetA()
case .sheetB:
SheetB()
}
}
}
}
The problem is that without using item:, current versions of SwiftUI render the initial sheet with the first state value (ie sheet A in this case) and don't update properly on the first presentation. Using this item: approach solves the issue.

SwiftUI picker didn't update

I tried to build a form that contained multiple picker. The first picker will show the existing data. The second picker will get the data from API according to the selection from first picker. However, when I open the form, the first picker work but the second picker display nothing. Even I select other selection from first picker, I can get the data but the second picker didn't update as my expectation. So the main question is how to make the second picker get data since there is a default selection in first picker. And what is the problem that cause the second picker no update after I make a selection in first picker
struct addBooking : View {
#State var shops = ShopJSON.shared.shops //existing data
#State var selectedShopIndex = 0
#State var selectedOutletIndex = 0
#ObservedObject var bookingOutletJSON = BookingOutletJSON()
var body: some View {
NavigationView{
Form {
Picker(selection: $selectedShopIndex, label: Text("Select Shop")) {
ForEach(0 ..< shops.count) {
Text(self.shops[$0].name!)
}
}
.onChange(of: selectedShopIndex, perform: { (value) in
print("Shop changed")
bookingOutletJSON.getOutlet(selectedShopId: shops[value].shopID!)
})
Picker(selection: $selectedOutletIndex, label: Text("Select Outlet")){
ForEach(0 ..< bookingOutletJSON.outlets.count) {
Text(self.bookingOutletJSON.outlets[$0].location!)
}
}
if bookingOutletJSON.outlets.count != 0 {
Text("\(bookingOutletJSON.outlets[0].location!)")
}
class BookingOutletJSON : ObservableObject{
#Published var outlets = [BookingOutlets]()
init() {
}
func getOutlet(selectedShopId : Int){
//API get data
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
if let decodedOutlet = try? JSONDecoder().decode(OutletModal.self, from: data) {
DispatchQueue.main.async {
self.outlets = decodedOutlet.outlets!
print(self.outlets)
print("Outlet updated")
}
} else {
print("Invalid response from server")
}
}
task.resume()
}
}
Try with another ForEach constructor
Picker(selection: $selectedOutletIndex, label: Text("Select Outlet")){
ForEach(bookingOutletJSON.outlets.indices, id: \.self) {
Text(self.bookingOutletJSON.outlets[$0].location!)
}
}

SwiftUI: Picker content does not display when selected in a list

I am trying to make a list of selectionable rows in Swift UI, the rows including a Picker. Everything works fine, except that the content of the Picker disappears when selected, see attached screenshot (but is actually visible when the window of the app is not active (i.e. when I click on another window))
I tried everything I could think of, I could not solve this issue. Below a minimal code to reproduce the problem. Anyone has any idea, how to get around this problem
SelectionList.swift
struct SelectionList: View {
#State var dudes: [String] = ["Tim", "Craig", "Phil"]
#State var selectedRow = Set<String>()
var body: some View {
return List(selection: $selectedRow) {
ForEach(self.dudes, id: \.self) { item in
SelectionRow()
}
}
}
}
SelectionRow.swift
struct SelectionRow: View {
#State var selectedFruit = 0
let fruits = ["Apples", "Oranges", "Bananas", "Pears"]
var body: some View {
Picker(selection: self.$selectedFruit, label: EmptyView()) {
ForEach(0 ..< fruits.count, id: \.self) {
Text(self.fruits[$0])
}
}
}
}

SwiftUI NavigationBar Title not present as it is when ActionSheet is present

I have a problem regarding NagivationBarTitle.
I have a view (first view) from which I call another one (second view).
In the second view I have some photos which I can select. If no Images are selected the NavigationBar title is "Images". If I have images selected I have the title like "x Images selected".
If I have images selected I can press a button which will display an ActionSheet.
The problem is that when the action sheet is shown the title is going back to "Images".
How can I preserve the title in ActionSheet as it was before tapping ("x Images selected")?
Some example of code when action sheet is shown:
First View:
struct FirstView: View {
var body: some View {
VStack (alignment: .leading) {
List {
AnotherView(param: param)
.navigationBarItems(trailing:
NavigationLink(destination: SecondView()) {
Image(name: "search")
}
)
}
}
}
}
Second View:
struct SecondView: View {
#State private var imagesSelected: Int = 0
var body: some View {
VStack {
List {
// here is a grid of items. every time an item is clicked a
// counter in encreasing
when item clicked: imagesSelected++
}
.navigationBarTitle("\(self.imagesSelected) Files selected")
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(title: Text("Delete Images"), buttons: [
.destructive(Text("Delete")){
// Some action
},
.cancel()
])
}
}
}
}