skip to Main Content

I’m reading SwiftUI materials and it’s said that view modifiers for example:

struct ByeView: View {
    var body: some View {
        Text("Bye bye, world!")
            .font(.headline)
    }
}

creates a new view with .headline font and returns the view.

So I wonder if it’s more like:

func font(_ font: UIFont) -> Text {
    Text(text, font: font)
}

rather than:

func font(_ font: UIFont) -> Text {
    self.font = font
    return self
}

I feel for event modifiers, since they may not have to modify the view, there’s no need to "create a new view with modified aspects", but not sure about the modifiers that do adjust the views.

Thanks!

2

Answers


  1. TLDR

    We can’t know for sure as the implementation detail is hidden.

    My point of view

    I might be wrong but I think it’s possible that neither of modifying an instance of a View or assigning to a property that you have described are actually happening, but we can’t know for sure since the implementation is private.

    Since SwiftUI is a declarative framework, where you describe what you want to get and the OS takes care of that, it could be even that by writing:

    SomeView()
        .padding()
        .background(Color.red)
        .cornerRadius(8)
    

    Internally it could become just about any representation such as JSON that the parser could read.

    Essentially no instance of any object (apart from the description) representing a View, Color or CornerRadius could exist before its initialization based on the description and current state, thus there would be no instance holding properties (such as font) that could be assigned or altered before the final View is initialized.

    Login or Signup to reply.
  2. First, note that an implementation such as

    func font(_ font: UIFont) -> Text {
        self.font = font
        return self
    }
    

    does not compile. font would need to be mutating for this to work, but it isn’t mutating. That said, this would have compiled:

    self.someReferenceType.font = font
    

    But this has another problem. This means that font now has a side effect:

    var body: some View {
        let x = Text("foo")
        x.font(.headline)
        return x // this should have non-headline font, but if the 
                 // implementation above were used, it would have headline font
    }
    

    So I think it is very likely that the actual implementation involves calling the initialiser, rather than return self. This also matches the wording in the documentation’s wording that a "new view" is "created".

    For modifiers that return some View, you can check the type they return using type(of:). You will most likely see that the type they return is different from self, which means they definitely do not return self! After all, that’s one of the reasons why the opaque type some View is used in the signature – to hide the internal types Apple used to implement these modifiers.

    // doesn't work in a playground for some reason
    // make a .swift file, compile and run
    let x = Text("foo").onAppear {}
    print(type(of: x))
    

    For me, this prints: ModifiedContent<Text, _AppearanceActionModifier>, not Text, so clearly a new view is created here. (See also ModifiedContent)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search