Can't find environment variable in ancestors SwiftUI error - view

Here's my UserProfile Component
struct UserProfile: View {
#EnvironmentObject var session: SessionStore
...
var body: some View {
VStack {
Text("uid: \(session.session?.uid ?? "")")
Text("email: \(session.session?.email ?? "")")
Button(action: signOut, label: {
Text("Log out")
})
}
}
}
And the parent of the userProfile view has this in it
NavigationLink(destination: UserProfile()){
Image(systemName: "person.circle").resizable()
.frame(width: 25.0, height: 25.0)
}
And for some reason when I get to the userProfile component I get the error
No ObservableObject of type SessionStore found. A View.environmentObject(_:) for SessionStore may be missing as an ancestor of this view.
The session is definitely available in the parent view view because this works
NavigationLink(destination: Text("\(session.session!.uid)")){
Image(systemName: "person.circle").resizable()
.frame(width: 25.0, height: 25.0)
}
and for some reason this works too
NavigationLink(destination: UserProfile().environmentObject(session)){
Image(systemName: "person.circle").resizable()
.frame(width: 25.0, height: 25.0)
}
Any explanations?

I think I know the answer. It's that the destination of a NavigationLink isn't considered a child of the parent view and thus won't inherit its environment. Thus the only way to solve this is to send in, again, the environmentObject that you want to pass down.

Related

view display on the right of the window

hello i have an issue with my project on Xcode when I use navigation view, the window display not normally and appear on the right of the window already displayed,
here is the code.
NavigationLink(destination: Acceuil())
{
HStack{
Image("icone_connexion")
.font(.system(size: 15))
// .scaledToFill()
Text("se connecter")
.font(.system(size: 30))
}.cornerRadius(60)
.frame(width: 400, height: 60)
} .background(Capsule().fill(Color(red: 55/255, green: 66/255, blue: 114/255, opacity:1)))
.frame(width: 400, height: 60) //fin navigationlink
.buttonStyle(PlainButtonStyle())
I would like that the new window replace the older one:)
On macOS it is the standard behavior in NavigationView to show the views (parent view and destination view) next to each other: https://developer.apple.com/design/human-interface-guidelines/macos/windows-and-views/column-views/
If you don't want that you can do:
NavigationView {
...
}
.navigationViewStyle(.stack)
so I found this code
import SwiftUI
struct ContentView: View {
#State private var show = false
var body: some View {
VStack{
if !show {
RootView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.transition(AnyTransition.move(edge: .leading)).animation(.default)
}
if show {
NextView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.green)
.transition(AnyTransition.move(edge: .trailing)).animation(.default)
}
}
}
}
struct RootView: View {
#Binding var show: Bool
var body: some View {
VStack{
Button("Next") { self.show = true }
Text("This is the first view")
}
}
}
it work grate for me so thanks you for your help

How to set a max width on a subview of HSplitView

I'm having some trouble with HSplitView on macOS, and I'm not sure if it's a bug or something I'm doing wrong.
I'm trying to create an app with a [Sidebar | Main Content | Inspector] layout. This is similar to the SF Symbols app, where you can view more information about a selected icon.
The approach I've taken is to have the Main Content and Inspector views be in an HSplitView. Having three views in a NavigationView only seems to use the Mail pattern of [List | List | Detail], which is not the layout I'm looking for.
The problem I'm seeing is that when I set a maxWidth on the Inspector view and drag the divider to the left, the Main Content view resizes to be smaller than the available space. The parent HSplitView doesn't resize, so I'm not sure if I'm using the wrong modifiers or using them in the wrong places.
I've setup a basic test case on github. If y'all could offer and help or guidance, that would be amazing.
Observed behaviour
Expected behaviour
import SwiftUI
struct A: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text("Pane A")
Spacer()
}
Spacer()
}
.frame(
minWidth: 200,
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .leading
)
.background(Color.red)
.foregroundColor(.black)
.layoutPriority(1)
}
}
struct B: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text("Pane B")
Spacer()
}
Spacer()
}
.frame(
minWidth: 200,
idealWidth: 250,
maxWidth: 300,
maxHeight: .infinity
)
.background(Color.purple)
.foregroundColor(.black)
}
}
struct ContentView: View {
var body: some View {
HSplitView {
A()
B()
}
.frame(
minWidth: 0,
maxWidth: .infinity,
maxHeight: .infinity
)
.background(Color.blue)
}
}e
Thanks!
I've had the same problem for several days, and I solved it in a flash.
Need to drag View
HSplitView {
View1()
View2()
}
Intuitively, we will set the maximum width of View1, but when SwiftUI drags, View1 exceeds the maximum width, it will display an inexplicable error
HSplitView {
View1()
.frame(maxWidth: 300)
View2()
}
Solutions
Set the minimum width of View2, and let View automatically fill all spaces. There will be no drag problem
HSplitView {
View1()
View2()
.frame(minWidth: 500)
}
Embedding one split view inside other may work.
Some problems arise if using GeometryReader.
HSplitView
{
View1()
HSplitView
{
View2()
View3()
}
}

SwiftUI : How to set image in MacOs?

please help me to set image in macOs application using swiftUI
Here is my Implementation:
import SwiftUI
struct SigninView: View {
var body: some View {
VStack{
Image("Profile")
.resizable()
.foregroundColor(.white)
}
}
}
but image is not visible in View
import SwiftUI
struct SigninView: View {
var body: some View {
VStack{
Image("Profile") // this is image name from xcassets
// Image(nsImage: NSImage(named: NSImage.folderName) ?? NSImage()) // method for system image
.resizable()
.scaledToFill()
.frame(width: 75, height: 75)
.clipped()
.aspectRatio(contentMode: .fill)
.padding()
}
}
}

How to make modal non-dismissible in SwiftUI

I’m creating an app where I have create first screen (it will be short description of application) and on the screen I have a next Button if I click on next button it should be dismiss otherwise it must not be dismiss either pull down.
If user pull down a sheet, it should be again re-position.
The problem is, that the user can dismiss the modal by swiping it down and application dashboard screen show that should be prevented.
How can we prevent to dismiss the Model by pull down.
struct ModalView : View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Rectangle()
.fill(Color.orange)
.frame(width: 400, height: 650)
.overlay(
VStack{
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image(systemName: "chevron.left")
Text("Dismiss")
}.padding(10.0)
.overlay(
RoundedRectangle(cornerRadius: 10.0)
.stroke(lineWidth: 2.0)
)
}.accentColor(.white)
})
.border(Color.blue)
.gesture( DragGesture())
}
}
ContentView
struct ContentView: View {
//MARK: Properties
//isPresented:- Present's a Welcome Screen in the form of cards.
#State private var isPresented = true
var body: some View {
VStack{
DashboardView()
.sheet(isPresented: $isPresented){
//IntroductionView(isPresentingSheet: self.$isPresented)
ModalView()
}
}
}
}
DashboardView
struct DashboardView: View {
var body: some View {
Text("Hello SwiftUI")
}
}
You can try this solution:
struct ModalWrapper: View {
var body: some View {
ModalView().highPriorityGesture(DragGesture())
}
}
struct ModalView : View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Rectangle()
.fill(Color.orange)
.frame(width: 400, height: 650)
.overlay(
VStack{
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image(systemName: "chevron.left")
Text("Dismiss")
}.padding(10.0)
.overlay(
RoundedRectangle(cornerRadius: 10.0)
.stroke(lineWidth: 2.0)
)
}.accentColor(.white)
})
.border(Color.blue)
.highPriorityGesture(DragGesture())
}
}
struct ContentView: View {
//MARK: Properties
//isPresented:- Present's a Welcome Screen in the form of cards.
#State private var isPresented = true
var body: some View {
VStack{
DashboardView()
.sheet(isPresented: $isPresented){
//IntroductionView(isPresentingSheet: self.$isPresented)
ModalWrapper()
}
}
}
}
struct DashboardView: View {
var body: some View {
Text("Hello SwiftUI")
}
}
Here I have added ModalWrapper for wrap the modal view Or else you will have to add highPriorityGesture(DragGesture()) to all subviews of the ModalView So it is better to keep one wrapper view.
Hope this will help you.

SwiftUI round button deforms when clicked

I have created a round button with following code:
struct RoundButton : View {
var value = "..."
var body: some View {
GeometryReader { geometry in
Button(action: {}) {
VStack {
Text(self.value)
.font(.headline)
.color(Color("NightlyDark"))
Text("MIN")
.font(.footnote)
.color(.white)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
.clipShape(Circle())
}
}
}
But when clicking the button, the shape gets deformed. Any idea why this happens ?
Same happens when i use .mask(Circle())
Is this a beta thing or normal behavior ? And does anyone maybe know a better way to create rounded buttons ?
what happens here is Button Considers all screen[width + height] as their frame by default.
so you have to set Button also.
I think it's the default behavior in watchOS
Here Your Code :
struct RoundButton: View {
var value = "..."
var body: some View {
GeometryReader { geometry in
Button(action: {}) {
VStack {
Text(self.value)
.font(.headline)
.foregroundColor(Color("NightlyDark"))
Text("MIN")
.font(.footnote)
.foregroundColor(.white)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
.frame(width: geometry.size.width, height: geometry.size.height)
.clipShape(Circle())
}
}
}
Note: i'm using Xcode 11 Beta 4

Resources