what am I missing on PreviewProvider - swift

my code works on the simulator here (it works here)
#main
struct sideMenu3App: App {
let persistenceController = PersistenceController.shared
#StateObject var viewRouter = ViewRouter()
var body: some Scene {
WindowGroup {
let context = persistenceController.container.viewContext
let dateHolder = DateHolder(context)
MotherView(viewRouter: viewRouter)
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(dateHolder)
}
}}
on my PreviewProvider
struct MotherView_Previews: PreviewProvider {
//#StateObject var viewRouter: ViewRouter
static var previews: some View {
MotherView(viewRouter: ViewRouter()).environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}}
the app crashes on the preview

Related

How to fix TextField popping back to root on cancel?

I have a simple test watchOS application with a TextField in a secondary view (navigated to from a NavigationLink).
However, when the TextField is canceled or submitted, it will pop back out to the root view instead of staying in the current view. I can't find any information on this anywhere else. Any fixes?
ContentView:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView{
NavigationLink("what", destination: DestinationView())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
DestinationView:
import SwiftUI
struct DestinationView: View {
#State private var message: String = ""
var body: some View {
TextField(
"Send Something...",
text: $message
)
}
}
struct DestinationView_Previews: PreviewProvider {
static var previews: some View {
DestinationView()
}
}
I found the issue..
I was using a NavigationView, which is deprecated. I removed it and now it's working as intended. (XCode 13.2.1, watchOS 8.3)
*facepalm*

Content preview unable to load

Any idea why the preview doesn't work here??
When I use the Text field, the preview comes up with a following error:
MessageSendFailure: Message send failure for update
==================================
| MessageError: Connection interrupted
import SwiftUI
import UIKit
struct ContentView: View {
#EnvironmentObject var userSettings: UserSettings
#State var loginmode = false
#State private var showingAlert = false
#State var selectedTab = "Home"
#State var showMenu = false
#State var visible = false
#State var color = Color.black.opacity(0.7)
var body: some View {
TextField("Enter your email address", text: $userSettings.email)
}
}
struct RegisterView: View {
var body: some View {
Text("Hello World")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Content of another file:
import Foundation
import SwiftUI
import Combine
class UserSettings: ObservableObject
{
#Published var email = String()
}
The content of main file is as below:
import SwiftUI
#main
struct kokoburraApp: App {
#StateObject var userSettings = UserSettings()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(userSettings)
}
}
}
Previews do not work without the necessary environment objects.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(UserSettings())
}
}

Trouble getting EnvironmentObject to update the UI

I originally posted another question asking this in the context of a project I was trying to develop, but I can't even get it to work in a vacuum so I figured I'd start with the basics. As the title suggests, my EnvironmentObjects don't update the UI as they should; in the following code, the user enters text on the ContentView and should be able to see that text in the next screen SecondView.
EDITED:
import SwiftUI
class NameClass: ObservableObject {
#Published var name = ""
}
struct ContentView: View {
#StateObject var myName = NameClass()
var body: some View {
NavigationView {
VStack {
TextField("Type", text: $myName.name)
NavigationLink(destination: SecondView()) {
Text("View2")
}
}
}.environmentObject(myName)
}
}
struct SecondView: View {
#EnvironmentObject var myself: NameClass
var body: some View {
Text("\(myself.name)")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(NameClass())
}
}
However, the SecondView doesn't show the text that the user has written, but the default value of name (blank). What am I doing wrong here?
class NameClass: ObservableObject {
#Published var name = ""
}
struct ContentView: View {
#StateObject var myName = NameClass()
var body: some View {
NavigationView {
VStack {
TextField("Type", text: $myName.name)
NavigationLink(destination: SecondView()) {
Text("View2")
}
}
}.environmentObject(myName)
}
}
struct SecondView: View {
#EnvironmentObject var myself: NameClass
var body: some View {
Text("\(myself.name)")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(NameClass())
}
}

Xcode preview crashes on DB loop read SwiftUI

When I call Core Data using:
#FetchRequest(
entity: Entity.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \Entity.id, ascending: true),
]
) var myData: FetchedResults<Entity>
then inside the View:
VStack {
ForEach(myData, id: \.self) { data in
Text("Test")
}
}
Xcode live preview crashes, if I remove the ForEach with a simple text it would work, how can I fix this? This is my current preview:
struct HomeItemListView_Previews: PreviewProvider {
static var previews: some View {
HomeItemListView()
}
}
This is the error it shows:
PotentialCrashError: MyApp.app may have crashed
MyApp.app may have crashed. Check ~/Library/Logs/DiagnosticReports for any crash logs from your application.
==================================
| Error Domain=com.apple.dt.ultraviolet.service Code=12 "Rendering service was interrupted" UserInfo={NSLocalizedDescription=Rendering service was interrupted}
As side note, the code compiles fine and displays fine on the normal simulator, it's the live one that has issues.
UPDATE:
So I have a viewRouter that controls the first screen, example Onboarding, if true, it goes to onboarding, if false it goes to HomeView.
This is how I have setup SceneDelegate:
let viewRouter = ViewRouter()
let contentView = MotherView()
.environment(\.managedObjectContext, context)
.environmentObject(viewRouter)
// Set the MotherView as the root view
window.rootViewController = UIHostingController(rootView: contentView)
On my MotherView, I have the Preview like this:
struct MotherView_Previews: PreviewProvider {
static var previews: some View {
MotherView().environmentObject(ViewRouter())
}
}
And on the Home view I have it like this:
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
HomeView()
}
}
So, most probably, your HomeItemListView preview should be set as follows
struct HomeItemListView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return HomeItemListView()
.environment(\.managedObjectContext, context)
.environmentObject(ViewRouter())
}
}

Switching Views With Observable Objects in SwiftUI

I am practicing trying to switch views using observable objects in SwiftUI, but my code isn't working. I know I can do this with #State, but I would like to get this working with observable objects. When I click on the image in the content view, the image doesn't change. Can someone help me?
ContentView.swift
import SwiftUI
struct ContentView: View {
#ObservedObject var viewRouter: ViewRouter
var body: some View {
VStack {
Button(action: {self.viewRouter.currentPage = "Page2"}) {
Image(viewRouter.currentPage)
}
if viewRouter.currentPage == "Page1" {
Page1(viewRouter: viewRouter)
}else if viewRouter.currentPage == "Page2" {
Page2(viewRouter: viewRouter)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(viewRouter: ViewRouter())
}
}
ViewRouter.swift
import Foundation
import SwiftUI
import Combine
class ViewRouter: ObservableObject {
let objectWillChange = PassthroughSubject<ViewRouter, Never>()
#Published var currentPage: String = "Page1"
}
Page1.swift
import SwiftUI
struct Page1: View {
#ObservedObject var viewRouter:ViewRouter
var body: some View {
VStack {
Image("ET-LondonBridge")
}
}
}
struct Page1_Previews: PreviewProvider {
static var previews: some View {
Page1(viewRouter: ViewRouter())
}
}
Page2.swift
import SwiftUI
struct Page2: View {
#ObservedObject var viewRouter:ViewRouter
var body: some View {
VStack {
Image("BigBen")
.aspectRatio(contentMode: .fit)
}
}
}
struct Page2_Previews: PreviewProvider {
static var previews: some View {
Page2(viewRouter: ViewRouter())
}
}
You don't need this line to make all things work. Just comment out this line
//let objectWillChange = PassthroughSubject<ViewRouter, Never>()