How does SwiftUI hides private protocol requirements of SwiftUI.View protocol

nm'ing SwiftUI I can see the following symbols:

000000000090a700 t protocol witness for static SwiftUI.View._makeView(view: SwiftUI._GraphValue<A>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs in conformance SwiftUI.Text : SwiftUI.View in SwiftUI
0000000000a29cd0 T protocol witness for static SwiftUI.View._makeViewList(view: SwiftUI._GraphValue<A>, inputs: SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs in conformance SwiftUI.Text : SwiftUI.View in SwiftUI
0000000000a2adf0 T protocol witness for static SwiftUI.View._viewListCount(inputs: SwiftUI._ViewListCountInputs) -> Swift.Int? in conformance SwiftUI.Text : SwiftUI.View in SwiftUI
0000000000a29d00 T protocol witness for SwiftUI.View.body.getter : A.Body in conformance SwiftUI.Text : SwiftUI.View in SwiftUI

So, apparently SwiftUI.View has hidden requirements _makeView(), _makeViewList() and _viewListCount(), which are implemented by the system views (the ones with Body = Never), while client views probably get them from the protocol extension.

nm'ing a demo app, I can see similar methods generated for custom views:

0000000100009420 t protocol witness for static SwiftUI.View._makeView(view: SwiftUI._GraphValue<A>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs in conformance Demo.ContentView : SwiftUI.View in Demo
0000000100009430 t protocol witness for static SwiftUI.View._makeViewList(view: SwiftUI._GraphValue<A>, inputs: SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs in conformance Demo.ContentView : SwiftUI.View in Demo
0000000100009440 t protocol witness for static SwiftUI.View._viewListCount(inputs: SwiftUI._ViewListCountInputs) -> Swift.Int? in conformance Demo.ContentView : SwiftUI.View in Demo

But I don't see any of these requirements in SwiftUI.View when viewing it in Xcode. In the client code it is not possible to have access control for individual protocol requirements and it is not possible to inherit protocol from more restricted protocol.

So how does SwiftUI do this? Is this an actual access control or Xcode follows some convention and hides symbols with leading underscores when showing framework contents?

4 Likes

Looks like its the later. I was able to implement these requirements manually:

struct ContentView: View {
    static func _makeView(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs {
        fatalError("Boom!")
    }

    static func _makeViewList(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs {
        fatalError("Boom!")
    }

    static func _viewListCount(inputs: SwiftUI._ViewListCountInputs) -> Int? {
        fatalError("Boom!")
    }
    ...
}
3 Likes

Thank you very much, your saving my life <3

You’re welcome! I’m curious how you were able to use this information on practice. Would you mind sharing?

Xcode (and whatever tool generates Apple's documentation files) hides a symbol in the public SDK if the symbol starts with an _. That's why you don't see those symbols.

Those methods have default implementations that are used for all types you define that conform to View.

You can see the full definition of protocol View by searching the Xcode bundle for a directory named SwiftUI.swiftmodule in the Xcode bundle. (There is one such folder for each SDK.) Inside that folder, look at arm64.swiftinterface. Here is the full definition as of Xcode 13:

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
@_typeEraser(AnyView) public protocol View {
  static func _makeView(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs
  static func _makeViewList(view: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs
  @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
  static func _viewListCount(inputs: SwiftUI._ViewListCountInputs) -> Swift.Int?
  associatedtype Body : SwiftUI.View
  @SwiftUI.ViewBuilder @_Concurrency.MainActor(unsafe) var body: Self.Body { get }
}
10 Likes