When defining a SwiftUI view, it comes automatic to write struct MyView: View followed by var body: some View { ... }:
all our views are composed by other views, but at some point SwiftUI needs to draw something on the screen: when does it end? How does SwiftUI know that it has reached the bottom of a view hierarchy?

In this article, let’s continue our exploration of SwiftUI’s inner workings.

The View protocol

Every SwiftUI view is a type conforming to the View protocol:

public protocol View {
  associatedtype Body: View
  @ViewBuilder var body: Self.Body { get }
}

Since this is a Swift protocol, we can make any type conform to it, for example String:

extension String: View {
  public var body: some View {
    Text(self)
  }
}

Note: this is just an example, not a suggestion nor a best practice.

Which allows us to write a String directly into a View declaration:

struct ContentView: View {
  var body: some View {
    "Hello world!"
  }
}

As we’re using the Text primitive in String’s body, this will work as expected, but what if we didn’t? Let’s build a new SwiftUI view which uses none of SwiftUI’s primitives:

struct MyView: View {
  var body: some View {
    self
  }
}

In this case we’re defining a new View called MyView, here we use it in ContentView:

struct ContentView: View {
  var body: some View {
    MyView()
  }
}

This builds fine, however, as MyView’s’ body is the view itself, we’re stuck on an infinite recursion, which will make SwiftUI terminate our app.

Despite the View protocol letting us conform pretty much anything to it, if we want to use those declarations in SwiftUI, we must use SwiftUI primitives, or be ready to see our app crash.

What do these SwiftUI primitives have that make them special, allowing SwiftUI to break the infinite recursion we’ve found ourselves in? The answer is in their body type: Never.

Never

Swift 3.0 has brought us Never, an uninhabited type: Never is a type with no possible values, making it impossible for us to get or create an instance.

We might have met Never for example:

Let’s declare a view with body type Never:

struct ImpossibleView: View {
  var body: Never
}

This builds! However we have no way to properly use it: we can’t instantiate it without passing something like fatalError(). Regardless, let’s implement the body and run our app:

struct ImpossibleView: View {
  var body: Never {
    fatalError("This will make our app 💥")
  }
}

Here’s our ContentView:

struct ContentView: View {
  var body: some View {
    ImpossibleView()
  }
}

Unsurprisingly, our app will crash once again, however the crash reason is Fatal error: ImpossibleView may not have Body == Never: file SwiftUI, line 0, not our This will make our app 💥.

Reading throughout the stack trace, we will see that there’s an assertionFailure within an internal SwiftUI’s BodyAccessor.makeBody(container:inputs:fields:) method, which apparently is not happy with our ImpossibleView body type.

This is the same method that will crash our app if we pass a class instance instead of a value type.

Only views declared within SwiftUI are allowed to have body type Never: despite not having access to BodyAccessor’s code, it’s clear that those views would either pass this assertion, or that they’d take a different, special path.

SwiftUI can’t keep asking for view bodys forever: it needs a special set of views, a.k.a. a set of primitives, that it can draw without asking for their body. This is why Text, ZStack, Color, etc have Never as their body type.

Is Never a View?

A type conforming to View needs to return a body that is also a View, therefore, from what we’ve seen above, this is the case: Never is a view.

SwiftUI knows to not to ask for the body of views with body type Never, either by crashing if it’s not a primitive, or do something else otherwise. However, since we must make our code compile, SwiftUI needs to extend Never to be a View: the ultimate, impossible view.

To confirm this, we can inspect SwiftUI’s headers, where we will find the following declaration (spread in a few places):

extension Never: View {
    public typealias Body = Never
    public var body: Never { get }
}

The SwiftUI team could have declared another special type to be used instead of Never, however I find this solution very elegant and perfectly fitting for the use case.

Conclusions

In this article we’ve explored how SwiftUI breaks the infinite recursion challenge when drawing views, and how it uses the special Swift type Never in order to elegantly achieve that.

I hope you’ve found this article useful: please let me know if I’ve missed anything!

Thank you for reading and stay tuned for more SwiftUI articles!

Bonus track

Since the article is about impossible views, just for fun I want to share another completely legal and 100% crashing way to “build” views: declare nothing but any modifier.

struct ContentView: View {
  var body: some View {
    border(Color.black)
  }
}

// or

struct ContentView: View {
  var body: some View {
    padding()
  }
}

// or

struct ContentView: View {
  var body: some View {
    ignoresSafeArea()
  }
}

// etc

So many possibilities! 💣

Are you aware of any another interesting way to crash SwiftUI? I’d love to know!

⭑⭑⭑⭑⭑