{"data":{"post":{"title":"Unexplained SwiftUI - The Programming Language Nature of SwiftUI","subtitle":"","isPublished":true,"createdTime":"2022-03-06T00:00:00.000Z","lastModifiedTime":null,"license":null,"tags":["Unexplained SwiftUI","SwiftUI","Swift"],"category":"Programming","file":{"childMdx":{"excerpt":"Preface Apple introduced SwiftUI at WWDC 2019. Most people may seem SwiftUI as yet another UI…","code":{"body":"function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nconst layoutProps = {};\nreturn class MDXContent extends React.Component {\n  constructor(props) {\n    super(props);\n    this.layout = null;\n  }\n\n  render() {\n    const _this$props = this.props,\n          {\n      components\n    } = _this$props,\n          props = _objectWithoutProperties(_this$props, [\"components\"]);\n\n    return React.createElement(MDXTag, {\n      name: \"wrapper\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Preface`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Apple introduced SwiftUI at WWDC 2019. Most people may seem SwiftUI as yet another UI framework likes `, React.createElement(MDXTag, {\n      name: \"em\",\n      components: components,\n      parentName: \"p\"\n    }, `Flutter`), `, `, React.createElement(MDXTag, {\n      name: \"em\",\n      components: components,\n      parentName: \"p\"\n    }, `React.js`), ` or `, React.createElement(MDXTag, {\n      name: \"em\",\n      components: components,\n      parentName: \"p\"\n    }, `Vue.js`), ` which rides on the trend of `, React.createElement(MDXTag, {\n      name: \"em\",\n      components: components,\n      parentName: \"p\"\n    }, `declarative`), ` `, React.createElement(MDXTag, {\n      name: \"em\",\n      components: components,\n      parentName: \"p\"\n    }, `stateless`), ` UI programming. Even though there are some common points between them, SwiftUI is far different from those UI frameworks I mentioned above from design to implementation.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `In fact, SwiftUI is a programming language more than a UI framework. Don’t believe it? Let me show you an example which computes Fibonacci number with “native” SwiftUI code:`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `import SwiftUI\n\nstruct ContentView: View {\n    \n    var body: some View {\n        Fibonacci(ordinal: 10)\n    }\n    \n}\n\nstruct Fibonacci: View {\n    \n    var ordinal: Int\n    \n    private var value: Value\n\n    init(ordinal: Int) {\n        self.init(ordinal: ordinal, value: .zero)\n    }\n\n    private init(ordinal: Int, value: Value) {\n        self.ordinal = ordinal\n        self.value = value\n    }\n    \n    var body: some View {\n        if ordinal == 0 {\n            Text(\"\\\\(value.description)\")\n        } else {\n            Fibonacci(ordinal: ordinal - 1, value: value.next())\n        }\n    }\n\n    private enum Value: CustomStringConvertible {\n\n        case zero\n\n        case one\n\n        case more(last: Int, current: Int)\n\n        func next() -> Value {\n            switch self {\n            case .zero: return .one\n            case .one:  return .more(last: 0, current: 1)\n            case .more(let last, let current):\n                return .more(last: current, current: last + current)\n            }\n        }\n\n        var description: String {\n            switch self {\n            case .zero:                         return \"0\"\n            case .one:                          return \"1\"\n            case .more(let last, let current):  return \"\\\\(last + current)\"\n            }\n        }\n\n    }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `By adding two lines of code, we can preview the code above in Swift Playground.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `import PlaygroundSupport\n\nPlaygroundPage.current.setLiveView(ContentView())\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/c41ed74d5550f47ced8c9b7efbde17e8/94001/fibonacci-number-on-swift-playground.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c41ed74d5550f47ced8c9b7efbde17e8/4ae7e/fibonacci-number-on-swift-playground.jpeg\",\n        \"srcSet\": [\"/static/c41ed74d5550f47ced8c9b7efbde17e8/aeae1/fibonacci-number-on-swift-playground.jpeg 178w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/3465b/fibonacci-number-on-swift-playground.jpeg 356w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/4ae7e/fibonacci-number-on-swift-playground.jpeg 712w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/01d22/fibonacci-number-on-swift-playground.jpeg 1068w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/accbd/fibonacci-number-on-swift-playground.jpeg 1424w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/c44b2/fibonacci-number-on-swift-playground.jpeg 2136w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/ac69a/fibonacci-number-on-swift-playground.jpeg 2732w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c41ed74d5550f47ced8c9b7efbde17e8/943f6/fibonacci-number-on-swift-playground.webp\",\n        \"srcSet\": [\"/static/c41ed74d5550f47ced8c9b7efbde17e8/b1d2a/fibonacci-number-on-swift-playground.webp 178w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/c91cd/fibonacci-number-on-swift-playground.webp 356w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/943f6/fibonacci-number-on-swift-playground.webp 712w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/8a6dd/fibonacci-number-on-swift-playground.webp 1068w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/fee22/fibonacci-number-on-swift-playground.webp 1424w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/fbb66/fibonacci-number-on-swift-playground.webp 2136w\", \"/static/c41ed74d5550f47ced8c9b7efbde17e8/94001/fibonacci-number-on-swift-playground.webp 2732w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c41ed74d5550f47ced8c9b7efbde17e8/94001/fibonacci-number-on-swift-playground.webp\",\n        \"alt\": \"Fibonacci Number run on Swift Playground\",\n        \"title\": \"Fibonacci Number run on Swift Playground\",\n        \"width\": 712,\n        \"height\": 534,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            Fibonacci Number run on Swift Playground\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `As you see, we computed Fibonacci number with “native” SwiftUI code. But being able to write a program which computes Fibonacci number with things come from SwiftUI does not mean that SwiftUI is a programming language. We can only say that SwiftUI is programming language unless it offers real “language structures” which make the program ran.`), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Unexplained View Protocol`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `To understand the “language structure” of SwiftUI, we have to understand the unexplained part of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol firstly.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Basically, a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Veiw`), ` protocol looks like below:`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `public protocol View {\n\n    associatedtype Body: View\n\n    @ViewBuilder\n    var body: Body { get }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `We can see that once a type conforms to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol, its instance has a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` property which returns an instance whose type also conforms to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol. This leads an interesting phenomenon: if we get the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance then we can get the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of this `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance. Since the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance is also a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance, thus we can continuously get its `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), `. Theoretically, we can repeat this pattern infinitely.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/7db2c008a266dea684c261a8ffdfa58e/d4e8c/execution-pattern.png\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"a\",\n      props: {\n        \"title\": \"Execution Pattern of SwiftUI\",\n        \"alt\": \"Execution Pattern of SwiftUI\",\n        \"src\": \"/static/7db2c008a266dea684c261a8ffdfa58e/d4e8c/execution-pattern.png\",\n        \"srcSet\": [\"/static/7db2c008a266dea684c261a8ffdfa58e/d4e8c/execution-pattern.png 1x\", \"/static/8904106481aa27eadbe86cb9c4a0f4af/4c6f7/execution-pattern%402x.png 2x\", \"/static/3397ae046d0c0559183c372af0b01c63/876d1/execution-pattern%403x.png 3x\"],\n        \"loading\": \"lazy\"\n      }\n    })), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            Execution Pattern of SwiftUI\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Yes. You may have noticed that the design of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol is recursive. In fact, this recursive design of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol offers `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `the basic language structure`), ` of SwiftUI which introduces a recursive-able execution pattern. SwiftUI’s internal mechanism can continually get the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance unless the recursion ended.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `But when does the recursion end?`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `SwiftUI extends the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), ` type in Swift Standard Library to conform to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` protocol. In this extension, `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), `’s  `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` also returns `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), `. Thus we can know that this is the recursion end.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `extension Never: View { }\n\nextension Never {\n\n    public typealias Body = Never\n\n    public var body: Never { get }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `In SwiftUI’s internal implementation, once the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance is `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), ` type, SwiftUI stops getting the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instance and switches to the `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `built-in`), ` logic of the view. If the `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `built-in`), ` logic does not hand over the execution to other `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instances, the recursion ends.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `SwiftUI ships with a lot of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` types whose `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` is `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), ` type. Since this kind of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` types have their own `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `built-in`), ` logic, they are also called `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `built-in views`), `.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `In the example of Fibonacci number I showed above, the recursion ends when the “program” of SwiftUI reaches the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Text`), ` view in the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` — because the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Text`), ` view’s `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` is `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Never`), ` type and the built-in logic of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Text`), ` view would not hand over the execution to other `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instances.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `extension Text : View {\n\n    public typealias Body = Never\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Other Language Structures`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `In previous descriptions, I narrowed the condition of the end of the recursion in SwiftUI’s execution pattern to be:`), React.createElement(MDXTag, {\n      name: \"blockquote\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"p\",\n      components: components,\n      parentName: \"blockquote\"\n    }, `A `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `built-in`), ` view whose logic does not hand over the execution to other `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instances`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `From this description, you may infer that there are built-in views in SwiftUI which hand over execution to other `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `View`), ` instances. And yes, there are.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `To help understand the language structures offered by SwiftUI in the Fibonacci number example I shown above, I would introduce one of them here — the language structure brought by `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if...else...`), ` statement in the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` — `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_ConditionalContent`), `.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `struct Fibonacci: View {\n\n    var body: some View {\n        // The \\`if...else...\\` statement\n        // would finally generates a\n        // \\`_ConditionalContent\\` instance\n        if ordinal == 0 {\n            // ...\n        } else {\n            // ...\n        }\n    }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_ConditionalContent`), ` is not exposed in SwiftUI’s public documentation. But we can find it in SwiftUI’s `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `swiftinterface`), ` file.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `public struct _ConditionalContent<TrueContent, FalseContent> {\n\n  internal enum Storage {\n    case trueContent(TrueContent)\n    case falseContent(FalseContent)\n  }\n\n  internal let storage: Storage\n\n}\n\nextension _ConditionalContent : View where TrueContent : View, FalseContent : View {\n\n  public typealias Body = Never\n\n  internal init(storage: Storage)\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"blockquote\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"p\",\n      components: components,\n      parentName: \"blockquote\"\n    }, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `swiftinterface`), ` file to a Swift module is just like header files to a clang module.`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `At the same time, there is an extension for SwiftUI’s `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ViewBuilder`), ` which shows when we using `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if...else...`), ` statements in a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `@ViewBuilder`), ` marked-up function, the Swift compiler would generate codes which wrap branches of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if...else...`), ` statement into a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_ConditionalContent`), ` at compile-time: when the expression after `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if`), ` evaluated into `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `true`), `, the generated code invokes first `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `buildEither`), ` function; when the expression evaluated into `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `false`), `, the generated code invokes the second `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `buildEither`), ` function.`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `extension ViewBuilder {\n\n  public static func buildEither<TrueContent : View, FalseContent : View>(first: TrueContent) -> ConditionalContent<TrueContent, FalseContent> {\n    .init(storage: .trueContent(first))\n  }\n\n  public static func buildEither<TrueContent : View, FalseContent : View>(second: FalseContent) -> ConditionalContent<TrueContent, FalseContent> {\n   .init(storage: .falseContent(second))\n  }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `By combining what we found in `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ViewBuilder`), ` extension and the design of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_ConditionalContent`), `, we can infer that a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_ConditionalContent`), ` instance is able to carry two kinds of instance — one refers to the content under `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `true`), ` branch of the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if...else..`), ` statement and the other refers to the content under `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `false`), ` branch.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `For example, in the Fibonacci number example, when the expression after `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `if`), ` evaluated into `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `true`), `, the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` equals to the following code:`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `struct Fibonacci: View {\n\n    var body: some View {\n        _ConditionalContent(storage: .trueContent(Text(...)))\n    }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `when the expression evaluated into `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `false`), `, the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` equals to the following code:`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `struct Fibonacci: View {\n\n    var body: some View {\n        _ConditionalContent(storage: .falseContent(Fibonacci(...)))\n    }\n\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `And the built-in logic of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"strong\"\n    }, `_ConditionContent`), ` would finally hand over the execution to the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"strong\"\n    }, `View`), ` instance stored in its `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"strong\"\n    }, `storage`), `.`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Thus we can know that unless the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ordianal`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` is equal to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `0`), `, the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), `’s `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` always recursively generates another `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), `. And when the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ordinal`), ` of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), ` is equal to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `0`), `, the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), `’s `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `body`), ` generates a `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Text`), ` view which renders the output value of `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Fibonacci`), `.`), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Conclusion`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `With previous analysis, we can clearly know that SwiftUI does offer the critical language structures for the execution in the example of computing Fibonacci number above — which include:`), React.createElement(MDXTag, {\n      name: \"ul\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `The View protocol which introduces recursive-able execution pattern.`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `A View protocol conformed type: _ConditionalContent which enables conditional branching.`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `which is quite like a real programming language. Thus we can say that SwiftUI is a programming language more than a UI framework.`), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `A Formal Perspective`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Actually, the Fibonacci example shows that SwiftUI is Turing complete: if a procedure can re-enter itself, and the procedure itself can change its behavior infinitely, then the language behind the procedure is Turing complete.`));\n  }\n\n}\nMDXContent.isMDXComponent = true;","scope":""},"headings":[{"value":"Preface","depth":2},{"value":"Unexplained View Protocol","depth":2},{"value":"Other Language Structures","depth":2},{"value":"Conclusion","depth":2},{"value":"A Formal Perspective","depth":2}]}}},"earlierPostExcerpt":{"slug":"/post/2019/09/conforming-to-codable-for-associated-value-enums-in-swift-9e3c","title":"Conforming to Codable for Associated Value Enums in Swift","subtitle":"","createdTime":"2019-09-10T00:00:00.000Z","tags":["Swift","Codable","Associated Value Enum"],"category":"Programming","file":{"childMdx":{"excerpt":"Understanding Associated Value Enums Why there are associated value enums in Swift? I mean, why the Swift core\nteam designed associated value enum？ To understand it, firstly, let's take a look at the following example in C: The C  struct   Device  represents a device. The member  pointer  is an…"}}},"laterPostExcerpt":{"slug":"/post/2022/08/using-functional-binding-to-observe-in-swiftui-19a8","title":"Using Functional Binding to Observe in SwiftUI","subtitle":"","createdTime":"2022-08-19T00:00:00.000Z","tags":["SwiftUI","Binding","Swift","Observer"],"category":"Programming","file":{"childMdx":{"excerpt":"Story This week, my colleague asked me a question: how to observe user selection\nbehaviors on SwiftUI's  Picker ? This is a question came from real bussiness. Thus I think it worth to take\nme time to solve it. The example code is as shown below and my colleague wanted to observe user's\nbehaviors on…"}}}},"pageContext":{"postId":"f06c1b0c-88ad-59b4-9a2c-690037a03ade","earlierPostId":"8e601448-778d-51ca-a66b-b68b06248377","laterPostId":"e1149583-4058-5dd4-8fc3-25534469b2b2"}}