Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Function declares an opaque return type [...]" error when declaring a view as a variable inside the body of a View in SwiftUI

Tags:

swift

swiftui

Assume I have a View with an Image that has a shadow property:

struct ContentView: View {
    var body: some View {
        Image("turtlerock").shadow(radius: 10)
    }
}

Now imagine I want to access the value of the shadow radius. I assumed I could do this:

struct ContentView: View {
    var body: some View {
        let myImage = Image("turtlerock").shadow(radius: 10)
        print(myImage.modifier.radius)
    }
}

However, this returns an error:

Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type

Is there a way to accomplish this somehow?

like image 789
Tamás Sengel Avatar asked Jun 08 '19 11:06

Tamás Sengel


3 Answers

When modifying and building views, you can do this without a return statement and a building block one above the other without commas. This is called a multi-statement closure. When you try to create a variable inside a multi-statement closure, the compiler is going to complain because there is a mismatch in types (you can only combine views one after another, nothing more). See this answer for more details: https://stackoverflow.com/a/56435128/7715250

A way to fix this is to explicitly return the views you are combining, so you don't make use of the multi-closure statements:

struct MyView: View {
    var body: some View {
        let image = Image("Some image").shadow(radius: 10)
        let myRadius = image.modifier.radius

        // Do something with myRadius

        return image // No multi closure statements.
    }
}
like image 158
J. Doe Avatar answered Nov 19 '22 21:11

J. Doe


If your view you want to reference is inside a stack, you should declare it outside the stack like this:

var body: some View {
    let myImage = Image("image").shadow(radius: 10)

    let stack = HStack {
        myImage
        Image("image2")
    }

    return stack
}
like image 3
Tamás Sengel Avatar answered Nov 19 '22 21:11

Tamás Sengel


You can define the image outside body:

let myImage = Image("turtlerock").shadow(radius: 10)

var body: some View {
  myImage
}

To print the radius you can do like so:

var body: some View {
  myImage
    .tapAction {
      print(self.myImage.modifier.radius) // 10.0
  }
}
like image 1
M Reza Avatar answered Nov 19 '22 21:11

M Reza