It seems to work on the fact of refreshing the ProgressView but I get warnings that tell me I’m doing it the wrong way:
UI must be changed from the main thread.
When you change values with @Published , the UI is updated.
You can use DispatchQueue.main.async to change values from main thread.
Like this:
DispatchQueue.main.async {
p.progress += 10.0
}
Also, what I did does not update correctly the final values.
I suggest below ⬇️
Add @Published var induction = 0.0 to Params class
Change value of induction (from main thread)
Show on UI
Like this:
struct ViewMAG_MultiStep: View{
@FocusState var isFocused: Bool
@EnvironmentObject var p: Params
@State private var showResults = false
// @State private var induction = 0.0
var body: some View{
List{
Button("Compute") {
calcMultiStep(p: p)
showResults.toggle()
}
.sheet(isPresented: $showResults) {
// Text("\(induction)")
Text("\(p.induction)")
ProgressView("Progress", value: p.progress, total: 100)
}
}
.navigationTitle("Multi-step")
}
}
class Params: ObservableObject {
@Published var progress = 0.0
@Published var value = 0.0
@Published var induction = 0.0
}
func calcMultiStep(p: Params) {
var induction = 0.0
DispatchQueue.global().async {
for i in 0...5 {
induction += Double(i) * calcSingleStep(p: p)
// from main thread
DispatchQueue.main.async {
p.progress += 10.0
}
}
print("Final value of induction: \(induction)")
// from main thread
DispatchQueue.main.async {
p.induction = induction
}
}
}
I am not a native English speaker, so I apologize if my English is incorrect.
Post
Replies
Boosts
Views
Activity
I suggest the following.
Passing argument, identifier of title, to your second page. (If user use unique title in your app, you can use title as an identifier.)
Then, setting NSPredicate with argument.
An example:
import SwiftUI
import CoreData
struct exampleView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [],
animation: .default)
private var items: FetchedResults<YourClass>
var title: String
@State var isReady = false // When finish setting nsPredicate, turn true and show list.
var body: some View {
List{
if isReady {
ForEach(items){item in
Text(item.yourProperty)
}
}
}
.onAppear(perform: { search(str: self.title) })
}
private func search(str: String){
if str.isEmpty {
items.nsPredicate = nil
} else {
let predicate = NSPredicate(format: "title contains %@", str)
items.nsPredicate = predicate
}
isReady = true // Show list
}
}
And in your main page:
ForEach(notesVM.notes, id: \.id){note in
NavigationLink(destination: exampleView(title: "groceries")){
NotesCell(note: note)
}
}
I don't know details of your CoreData object. So please customize it yourself for your project.
At last, I apologize if my English is incorrect because I'm not a native English speaker.
You want to change SwiftUI Views by pressing the button, right?
If so, you can use NavigationLink with NavigationView.
An example:
NavigationView{
NavigationLink(destination: {
view2()
}, label: {
Text("Press Me")
.foregroundColor(.white) // Set the modifiers to your liking.
.padding(.vertical)
.padding(.horizontal, 50)
.background(.blue)
.cornerRadius(10)
})
.navigationTitle("Home") // You can set the title that displayed at the top of the view.
}
More information, see Apple Developer Documentation.
NavigationView
NavigationLink
However, NavigationView is deprecated in iOS16.
It seems that we can use new navigation types in iOS16 or later.
I created a project like yours. However, my project seems to work fine.
Could you show me any error messages that were shown in your project?
but it still shows the other text from ContentView()
Do you want to hide text like below?
If so, you can hide it by adding .navigationBarHidden(true) in view2() like this:
struct view2: View {
var body: some View {
VStack {
Text("Some Text...")
Text("Some Text...")
Text("Some Text...")
}
.navigationBarHidden(true)
}
}
Also, if you want to add a button to return to ContentView(), you can use dismiss() action.
How to use:
struct view2: View {
@Environment(\.isPresented) var isPresented
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
Text("Some Text...")
Text("Some Text...")
Text("Some Text...")
if isPresented {
Button(action: {
dismiss()
}, label: {
Text("Back")
})
}
}
.navigationBarHidden(true)
}
}
Hello,
I also devised way to switch Views without NavigationView.
It use switch statement.
Sample here:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var pageManager: PageManager
var body: some View {
switch pageManager.page {
case .top:
top()
case .view2:
view2()
}
}
}
struct top: View {
@EnvironmentObject var pageManager: PageManager
var body: some View{
VStack {
Text("Top")
.padding()
Button("To view2"){
pageManager.page = .view2
}
.padding()
}
}
}
struct view2: View {
@EnvironmentObject var pageManager: PageManager
var body: some View {
VStack {
Text("View2")
.padding()
Button("To top"){
pageManager.page = .top
}
.padding()
}
}
}
enum Page {
case top
case view2
}
class PageManager: ObservableObject{
@Published var page: Page = .top
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(PageManager())
}
}
Hello,
To pass parameters to the sheet view, use sheet(item:onDismiss:content:).
ContentView:
struct ContentView: View {
// @State var isPresented: Bool = false
@State var items = ["item1", "item2"]
@State var sheetParameter: MyItem? = nil // 'MyItem' have to conform to 'Identifiable'
var body: some View {
List{
// Using array's index for id.
ForEach(Array(items.enumerated()), id: \.element){index, item in
Button(action: {
self.sheetParameter = MyItem(id: index, text: item)
}, label: {
Text(item)
})
.sheet(item: $sheetParameter) {parameter in
CustomView(text: parameter.text)
}
}
.onDelete{ indexSet in
items.remove(atOffsets: indexSet)
}
}
}
}
MyItem -- structure that conforms 'Identifiable':
struct MyItem: Identifiable {
var id: Int
var text: String
}
CustomView doesn't have to change.
The first parameter of sheet(item:onDismiss:content:) requires argument its type conform to 'Identifiable'.
In my example, using array's index for id.
However, if your 'item' has other unique elements, you can use it for id.
To use EnvironmentObject, you have to attach the modifier .environmentObject(Model()) to ContentView() which is in struct ImageRendererWithEnvironmentApp.
Like below,
import SwiftUI
@main
struct ImageRendererWithEnvironmentApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(Model()) // You have to add this.
}
}
}