Swift Playgrounds on iPad Not Working with SwiftUI code as Expected - swiftui

The attached code works as expected on the Playgrounds simulator for the Mac but the States don't register a view update when the same code runs on an iPad. Does anyone know of a known issue/fix/workaround?
import SwiftUI
import PlaygroundSupport
struct MathGame: View
{
#State var showAnswer = false
#State var answer = ""
#State var x = Int.random(in: 0...100)
#State var y = Int.random(in: 0...100)
var body: some View
{
VStack
{
Text(x.description)
Text(y.description)
if showAnswer
{
let z = x + y
Text(z.description)
} else
{
Text(" ")
}
Button("Next Question")
{
showAnswer = false
x = Int.random(in: 0...100)
y = Int.random(in: 0...100)
}
Spacer()
Toggle(isOn: $showAnswer)
{
Text("Show Answer")
}
}.padding().font(.system(size: 64))
}
}
PlaygroundPage.current.setLiveView(MathGame())

I faced the same issue and I just found out that setting « Show results » to false was fixing it.
My iPad runs on iOS 14.6. I hope that the new Swift playgrounds with iOS 15 will fix this issue definitely.

Related

SwiftUI iOS 16, close multiple modals not working

I'm trying to present multiple modals on top of my home view, but when I try to dismiss all modals, there is only the first one that close...
(I know, there is a lot of subject about this, but I didn't found any solution that was working for me...)
Any ideas?
Here is my testing code:
struct ContentView: View {
#State var presentA = false
var body: some View {
Button("Present A") { presentA = true }
.sheet(isPresented: $presentA) { ContentViewA(presentAll: $presentA) }
}
}
struct ContentViewA: View {
#Binding var presentAll: Bool
#State var presentB = false
var body: some View {
Button("Present B") { presentB = true }
.sheet(isPresented: $presentB) { ContentViewB(presentAll: $presentAll) }
}
}
struct ContentViewB: View {
#Binding var presentAll: Bool
var body: some View {
Button("Close all") {
presentAll = false
}
}
}
So when I touch the "Close all" button, I go back to the ContentViewA instead of the ContentView...
In my memory this was working with the previous version of SwiftUI but it seems that's not working anymore...
What am I doing wrong?
I don't think it is a valid user flow and SwiftUI does not handle it. The possible workaround is the same as for UIKit
Tested with Xcode 14b3 / iOS 16
var body: some View {
Button("Close all") {
UIApplication.shared.keyWindow?
.rootViewController?
.dismiss(animated: false, completion: nil) // false is important !!
}
}

Issue in Setting Value to #State variable in SwiftUI [duplicate]

Hello I am running into a problem here and I do not have a consistent behavior between my .sheet() view when running on ios13 or ios14
I got a view like this :
#State private var label: String = ""
#State private var sheetDisplayed = false
///Some code
var body: some View {
VStack {
Button(action: {
self.label = "A label"
self.isDisplayed = true
}) {
Text("test")
}
}.sheet(isPresented: $sheetDisplayed, onDismiss: {
self.label = ""
}) {
Text(self.label)
}
}
On ios 13 this work as expected btn click -> set label -> call sheet -> display "A label" in a Text view.
On ios14 I got an empty string in self.label when in sheet closure, hence it does not display anything.
Did I missed something ? Is it an iOS 14 bug or did I had it wrong on ios13 and that got corrected.
PS: I have a couple of other variables that are passed in the closure I simplified it.
Your code have expectation of view update/creation order, but in general it is undefined (and probably changed in iOS 14).
There is explicit way to pass information inside sheet - use different sheet creator, ie. .sheet(item:...
Here is working reliable example. Tested with Xcode 12 / iOS 14
struct ContentView: View {
#State private var item: Item?
struct Item: Identifiable {
let id = UUID()
var label: String = ""
}
var body: some View {
VStack {
Button(action: {
self.item = Item(label: "A label")
}) {
Text("test")
}
}.sheet(item: $item, onDismiss: {
self.item = nil
}) {
Text($0.label)
}
}
}
This is some really strange behaviour in iOS 14, which doesn't appear to be documented.
Using the other answer here and the comment on this thread, I used #Binding to solve the issue as it seemed the cleanest and most SwiftUI-esq solution.
I have no idea why this behaviour has changed, and it seems less intuitive than before, so I'm assuming its a bug!
An example:
struct MainView: View {
#State private var message = ""
#State private var showSheet = false
var body: some View {
Button(action: {
self.message = "This will display the correct message"
self.showSheet = true
}, label: {
Text("Test Button")
})
.sheet(isPresented: self.$showSheet) {
SheetView(message: self.$message)
}
}
}
struct SheetView: View {
#Binding var message: Int
var body: some View {
Text(self.message)
}
}
The behaviour changed with SwiftUI 2.0, so it affects MacOS 11 as well, just adding a binding to the view fixes it even when that binding is never used, which makes me think this is an implementation bug.
Additionally just using the details state variable in a Text() within the body of the view also fixes it.
struct MyViewController : View {
#State var details: String?
#State var showDetails = false
// #Binding var havingAbindingFixesIt: String?
var body: some View {
VStack {
// Text(details ?? "")
Text("Tap here for details")
.onTapGesture {
self.details = "These are the details"
self.showDetails.toggle()
}
.sheet(isPresented: $showDetails) { Text(details ?? "") }
}
}
}

SwiftUI #State and .sheet() ios13 vs ios14

Hello I am running into a problem here and I do not have a consistent behavior between my .sheet() view when running on ios13 or ios14
I got a view like this :
#State private var label: String = ""
#State private var sheetDisplayed = false
///Some code
var body: some View {
VStack {
Button(action: {
self.label = "A label"
self.isDisplayed = true
}) {
Text("test")
}
}.sheet(isPresented: $sheetDisplayed, onDismiss: {
self.label = ""
}) {
Text(self.label)
}
}
On ios 13 this work as expected btn click -> set label -> call sheet -> display "A label" in a Text view.
On ios14 I got an empty string in self.label when in sheet closure, hence it does not display anything.
Did I missed something ? Is it an iOS 14 bug or did I had it wrong on ios13 and that got corrected.
PS: I have a couple of other variables that are passed in the closure I simplified it.
Your code have expectation of view update/creation order, but in general it is undefined (and probably changed in iOS 14).
There is explicit way to pass information inside sheet - use different sheet creator, ie. .sheet(item:...
Here is working reliable example. Tested with Xcode 12 / iOS 14
struct ContentView: View {
#State private var item: Item?
struct Item: Identifiable {
let id = UUID()
var label: String = ""
}
var body: some View {
VStack {
Button(action: {
self.item = Item(label: "A label")
}) {
Text("test")
}
}.sheet(item: $item, onDismiss: {
self.item = nil
}) {
Text($0.label)
}
}
}
This is some really strange behaviour in iOS 14, which doesn't appear to be documented.
Using the other answer here and the comment on this thread, I used #Binding to solve the issue as it seemed the cleanest and most SwiftUI-esq solution.
I have no idea why this behaviour has changed, and it seems less intuitive than before, so I'm assuming its a bug!
An example:
struct MainView: View {
#State private var message = ""
#State private var showSheet = false
var body: some View {
Button(action: {
self.message = "This will display the correct message"
self.showSheet = true
}, label: {
Text("Test Button")
})
.sheet(isPresented: self.$showSheet) {
SheetView(message: self.$message)
}
}
}
struct SheetView: View {
#Binding var message: Int
var body: some View {
Text(self.message)
}
}
The behaviour changed with SwiftUI 2.0, so it affects MacOS 11 as well, just adding a binding to the view fixes it even when that binding is never used, which makes me think this is an implementation bug.
Additionally just using the details state variable in a Text() within the body of the view also fixes it.
struct MyViewController : View {
#State var details: String?
#State var showDetails = false
// #Binding var havingAbindingFixesIt: String?
var body: some View {
VStack {
// Text(details ?? "")
Text("Tap here for details")
.onTapGesture {
self.details = "These are the details"
self.showDetails.toggle()
}
.sheet(isPresented: $showDetails) { Text(details ?? "") }
}
}
}

Issue with computed property not being updated for showing Sheet in Xcode 12 (worked before) [duplicate]

This question already has an answer here:
iOS14 introducing errors with #State bindings
(1 answer)
Closed 2 years ago.
This code has the following issue: The first click on any list item will show the sheet with "This is sheet 0" - meaning that #State property "var example: Int" is not updated as part of the button code (exit live preview and start it again, will reproduce the issue).
Any idea what is happening here !?
Code:
import SwiftUI
struct testing2: View {
#State private var showSheet = false
#State var example: Int = 0
var computedItem: String {
"This is sheet \(example)"
}
var body: some View {
List(0 ..< 5) { item in
Button("List item: \(item)") {
self.example = item
showSheet.toggle()
}
}
.sheet(isPresented: $showSheet, content: {
Text("\(computedItem)")
})
}
}
Not sure whether this would be the best answer, but this worked for me:
struct ContentView: View {
#State private var showSheet = false
#State var example: Int = 0
#State var computedItem: String = ""
var body: some View {
List(0 ..< 5) { item in
Button("List item: \(item)") {
self.example = item
self.computedItem = "This is sheet " + String(self.example)
showSheet.toggle()
}
}
.sheet(isPresented: $showSheet) {
sheetView(computedItem: $computedItem)
}
}
}
struct sheetView: View {
#Binding var computedItem: String
var body: some View {
Text(self.computedItem)
}
}

how to convert an user number in days or hours or seconds swiftUI

I am new in Swift UI, I am trying to convert a value what I get from a textfiled and picker to convert that in days, minutes or seconds, this is from the tutorial 100 days with swiftUI i am lost because I dont understand how do the operations if someone can help me and explain me a little the code please, thank you.
this is my code
struct ContentView: View {
#State private var convertir = 2
let tipConverciones = ["segundos","minutos","horas","dias"]
#State private var convertirselection = 2
let convertirA = ["segundos","minutos","horas","dias"]
#State var cantidadconvertir = ""
var convertidormetodo: Double{
//Funcion que calcula el total de personas
let conteocantidad = Double(cantidadconvertir) ?? 0
let convertirSeleccion = (convertirA)
return 0
}
var body: some View {
NavigationView{
Form {
Section (header: Text("Convertir")) {
Picker ("Convertir de", selection: $convertir){
ForEach(0 ..< tipConverciones.count){
Text("\(self.tipConverciones[$0])")
}//ForEach
}//Picker
.pickerStyle(SegmentedPickerStyle())
}//Seccion3
Section (header: Text("Ingresar Cantidad a convertir")) {
TextField("Ingresa la cuentidad", text: $cantidadconvertir)
.keyboardType(.decimalPad)
}//seccion5
Section (header: Text("Convertir a")) {
Picker ("Convertir de", selection: $convertir){
ForEach(0 ..< tipConverciones.count){
Text("\(self.tipConverciones[$0])")
}//ForEach
}//Picker
.pickerStyle(SegmentedPickerStyle())
}//Seccion4
Section{//seccion 4
Text("La cantidad convertida es: \(convertidormetodo)")
}//seccion 4
}//Form
.navigationBarTitle("Convertidor SwiftUI")
}//Navigation View
}//body
}//view
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
an example of a user input and the desired output would help. But I think what you're looking for is either the dateFormatter or numberFormatter:
https://developer.apple.com/documentation/foundation/dateformatter
https://developer.apple.com/documentation/foundation/numberformatter