GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

SOLVED: Day 37 - Closing Sheets

Forums > SwiftUI

Given the following line from the video...

@Environment(\.dismiss) var dismiss
...
dismiss() //called when user presses a button

I'm trying to understand what is happening here. I tried using Environment.dismiss() and it would not work.

  1. What is the @ denoting? Is it like attributes in c# above class/functions?

    • ANSWERED by Obelix (@ before something means it is something called a Property Wrapper)
  2. What does \. before something mean?

    • ANSWERED by Obelix (it is something we will learn later called a keypath)
  3. Is dismiss in this case a function pointer (closure)? I.E. var dismiss: Closure = ?????

    • ANSWERED (dismiss is a DismissAction struct that can be used as a function (see Methods with Special Names), but the actual function is hidden from the user somehow).

Coming from C#/Java and trying to sort this out in my head.

Thanks guys!

   

Some of your questions are beyond the knowledge needed for Day 37 lessons.

The syntax in the parenthesis is called a key path.

//  Key Path    👇
@Environment(\.dismiss) var dismiss

At higher levels of your application, SwiftUI has set up an application-wide structure that provides a ton of piping, bracing, wires, fuse boxes, faucets, and glue to hold your application together. Some of these application-wide variables can be exposed to your application's logic and manipulated. You'll learn about more key path variables in later assignments.

The slash-dot syntax allows you to "follow a path" down to the variable that you seek. Here are some made up key paths to illustrate this concept:

// Not real! These are made up:
// Follow a path to find the >key<      👇🏼
@Environment(\.systemColors\darkmode\okButton)  var okButtonColor   
@Environment(\.systemColors\lightmode\okButton) var okButtonColorLightMode
@Environment(\.speaker\volume)                  var speakerVolume // <-- Set it to 11 !!

You also use key paths in ForEach()view builder loops. You'll use key paths to tell the ForEach() view builder what part of a structure makes it unique from other views it is building.

Keep Coding

Here's another answer I provided about ForEach() view factory. Find the key path in my example!

See -> Find the Key Path

1      

Obelix,

Thank you for the response!

I did some digging, and found that the dismiss variable I am creating is a DismissAction struct So,

@Environment(\.dismiss) var dismiss: DismissAction

works with my code and verifies the type (If structs are identified just like classes as types).

So, a DismissAction struct is gathered into the variable dismiss in the code.

DismissAction structs contain one func (according to xCode's reference cited below)

public func callAsFunction()

The example of these "Methods with Special Names" that have callAsFunction() func in them allow the user reference them directly. I. E. dismiss() vs. dismiss.callAsFunction() OK, that makes sense, but what I don't understand is what function is being called. Calling dismiss() is a shortcut to an actual function somewhere, I just cannot see what it is.

To clarify, the dismiss variable is a DismissAction struct as far as I can tell, and has but one method: callAsFunction(). The specific dismiss struct in question is acquired by referencing @Environment (whatever that is) and passing (\.dismiss) as it's keypath (which you indicated would be explained later).

So, a question would be: why can the mapped func not directly be called (whatever the actual function is)?

I am so confused about why structs (instead of objects), but I suppose I'll learn that later. It seems enormous effort was taken to not use objects.

And I am still confused as to what @Environment is.

Again, thanks for the response. I have my mind set on understanding SwiftUI.

Here's the SwiftUI documentation I found about DismissAction structs:

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public struct DismissAction {

    /// Dismisses the view if it is currently presented.
    ///
    /// Don't call this method directly. SwiftUI calls it for you when you
    /// call the ``DismissAction`` structure that you get from the
    /// ``Environment``:
    ///
    ///     private struct SheetContents: View {
    ///         @Environment(\.dismiss) private var dismiss
    ///
    ///         var body: some View {
    ///             Button("Done") {
    ///                 dismiss() // Implicitly calls dismiss.callAsFunction()
    ///             }
    ///         }
    ///     }
    ///
    /// For information about how Swift uses the `callAsFunction()` method to
    /// simplify call site syntax, see
    /// [Methods with Special Names](https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID622)
    /// in *The Swift Programming Language*.
    public func callAsFunction()
}

   

What does the @ denote?

@Environment and @State are known in Swift as Property Wrappers.

But the same syntax is also used to mark Swift macros. (This was introduced in 2023's World WIde Devlopers Conference.)

Hold the option key ⌥ whilst hovering over the word @Environment. Your cursor will change to a question mark. Click for more detail.

Property Wrappers can't be addressed in a forum post. I think there are many online tutorials covering PropertyWrappers in great detail.

Hacking With Swift Explanation

@twoStraws has some articles. Start here.
See -> All about property wrappers

   

Thanks for the help. I marked your answer as the solution. I know much more about Swift digging into this, and look forward to learning about Key Paths, Properties, and Property Wrappers!

   

Hacking with Swift is sponsored by Alex.

SPONSORED Alex is the iOS & Mac developer’s ultimate AI assistant. It integrates with Xcode, offering a best-in-class Swift coding agent. Generate modern SwiftUI from images. Fast-apply suggestions from Claude 3.5 Sonnet, o3-mini, and DeepSeek R1. Autofix Swift 6 errors and warnings. And so much more. Start your 7-day free trial today!

Try for free!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.