{"data":{"post":{"title":"Conforming to Codable for Associated Value Enums in Swift","subtitle":"","isPublished":true,"createdTime":"2019-09-10T00:00:00.000Z","lastModifiedTime":null,"license":null,"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…","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    }, `Understanding Associated Value Enums`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Why there are associated value enums in Swift? I mean, why the Swift core\nteam designed associated value enum？`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `To understand it, firstly, let's take a look at the following example in C:`), 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-c\"\n      }\n    }, `struct Printer;\n\nstruct Scanner;\n\nenum DeviceType {\n    DeviceTypePrinter = 0,\n    DeviceTypeScanner = 1,\n};\n\nstruct Device {\n    union {\n        struct Printer * printer;\n        struct Scanner * scanner;\n    } pointer;\n    enum DeviceType device_type;\n};\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `The C `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), ` `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Device`), ` represents a device. The member `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `pointer`), ` is an\nanonymous union which has two members `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `printer`), ` and `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `scanner`), ` and can help\nspecialize the type of the pointer. The member `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `device_type`), ` indicates\nwhich type of device pointer this `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), ` stores.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `And then we can get the stored pointer with the following C 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-c\"\n      }\n    }, `struct Device device;\n\nPrinter * printerPtr = NULL;\nScanner * scannerPtr = NULL;\n    \nswitch (device.device_type) {\n    case DeviceTypePrinter:\n        printerPtr = device.pointer.printer;\n        break;\n    case DeviceTypeScanner:\n        scannerPtr = device.pointer.scanner;\n        break;\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `After I've described the purpose of the C `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), ` above, you can quick\nrealize that you can interpret it into Swift like 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 Printer {}\nstruct Scanner {}\n\nenum Device {\n    case printer(Printer)\n    case scanner(Scanner)\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `And we can get the stored pointer with the following Swift 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    }, `let device: Device = .printer(Printer());\n\nvar printer: Printer!\nvar scanner: Scanner!\n\nswitch device {\ncase let .printer(p):\n    printer = p\ncase let .scanner(s):\n    scanner = s\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Yes. The design purpose of associated value enums is just to simplify the\ndeclaration and usage for data structures like the previous `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Device`), `\nexample in C. Similar C `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), `s like the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Device`), ` `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), ` are\nubiquitous in code bases of operating systems or other infrastructures\nwritten in C, which is just another approach exercises `, React.createElement(MDXTag, {\n      name: \"strong\",\n      components: components,\n      parentName: \"p\"\n    }, `polymorphism`), `.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `I mean polymorphism. Yes, polymorphism.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Polymorphism is not a concept only exists in Object-Oriented world. Once\nan entity has multiple potential forms, then we can call this entity\nexercises polymorphism.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Since the associated value enum is designed to simply the expression of\npolymorphism in plain-old data structure, we can express an associated\nvalue enum with another polymorphism approach -- the Object-Oriented one.`), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Expressing Associated Value Enum in Object-Oriented World`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `The first pattern we can come up with to express an associated value enum\nin Object-Oriented World is abstract factory.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Yes. Actually, I always use the abstract factory pattern to illustrate\nassociated value enums in Object-Oriented World.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `For the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Device`), ` `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `struct`), ` in Swift which we have shown in the previous\nexample, we can write an equivalent Object-Oriented Swift 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    }, `enum DeviceType {\n    printer\n    scanner\n}\n\nclass DeviceObject {\n    var type: DeviceType { preconditionFailure(\"Abstract class\") }\n\n    var deviceValue: Device { preconditionFailure(\"Abstract class\") } \n\n    static func make(device: Device) -> DeviceObject {\n        switch device {\n            case let .printer(printer): return makePrinter(printer)\n            case let .scanner(scanner): return makeScanner(scanner)\n        }\n    }\n\n    static func makePrinter(_ printer: Printer) -> DeviceObject {\n        return PrinterObject(printer: printer)\n    }\n\n    static func makeScanner(_ scanner: Scanner) -> DeviceObject {\n        return ScannerObject(scanner: scanner)\n    }\n}\n\nclass PrinterObject: DeviceObject {\n    override var type: DeviceType { return .printer }\n\n    override var deviceValue: Device { return .printer(printer) }\n\n    let printer: Printer\n\n    init(printer: Printer) {\n        self.printer = printer\n    }\n}\n\nclass ScannerObject: DeviceObject {\n    override var type: DeviceType { return .scanner }\n\n    override var deviceValue: Device { return .scanner(scanner) }\n\n    let scanner: Scanner\n\n    init(scanner: Scanner) {\n        self.scanner = scanner\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Then we have expressed an associated value enum with the Object-Oriented\napproach now.`), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `Conforming to Codable`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `With the `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `DeviceObject`), ` class, conforming to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Codable`), ` comes to be very\neasy now. Firstly, we have to make `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `DeviceObject`), `  to conform to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Codable`), `.`), 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    }, `enum DeviceType: UInt8, Codable {\n    case printer\n    case scanner\n}\n\nclass DeviceObject: Codable {\n    var type: DeviceType { preconditionFailure(\"Abstract class.\") }\n\n    var deviceValue: Device { preconditionFailure(\"Abstract class.\") }\n\n    private enum _CodingKeys: CodingKey {\n        case type\n    }\n    \n    init() {\n        \n    }\n    \n    required init(from decoder: Decoder) throws {\n        \n    }\n\n    func encode(to encoder: Encoder) throws {\n        var container = encoder.container(keyedBy: _CodingKeys.self)\n        try container.encode(type, forKey: .type)\n    }\n\n    static func make(device: Device) -> DeviceObject {\n        switch device {\n            case let .printer(printer): return makePrinter(printer)\n            case let .scanner(scanner): return makeScanner(scanner)\n        }\n    }\n\n    static func makePrinter(_ printer: Printer) -> DeviceObject {\n        return PrinterObject(printer: printer)\n    }\n\n    static func makeScanner(_ scanner: Scanner) -> DeviceObject {\n        return ScannerObject(scanner: scanner)\n    }\n    \n    static func make(decoder: Decoder) throws -> DeviceObject {\n        let container = try decoder.container(keyedBy: _CodingKeys.self)\n        let deviceType: DeviceType = try container.decode(DeviceType.self, forKey: .type)\n        switch deviceType {\n            case .printer:\n                return try PrinterObject(from: decoder)\n            case .scanner:\n                return try ScannerObject(from: decoder)\n        }\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `The key point here is the static 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    }, `static func make(decoder: Decoder) throws -> DeviceObject\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `This is a factory method for `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `DeviceObject`), `.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `You may doubt that in ObjectiveC, we often call \"factory method\" with syntax\nlike`), 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-objectivec\"\n      }\n    }, `Foo * foo = [Foo foo];\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `For a concrete example, like `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `NSCalender`), `:`), 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-objectivec\"\n      }\n    }, `NSCalendar * calendar = [NSCalendar calendarWithIdentifier: NSCalendarIdentifierGregorian];\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `returns an instance of type `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_NSCopyOnWriteCalendarWrapper`), `, which is a\nderived class of abstract class `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `NSCalendar`), `.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `The class method `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `[NSCalendar +calendarWithIdentifier:]`), ` actually calls\n`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `[NSCalendar +alloc]`), ` on `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `NSCalendar`), ` firstly and then this function calls\ninto `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `[NSCalendar +allocWithZone:]`), `, then calls the designated initializer\n`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `[NSCalendar -initWithCalendarIdentifier:]`), ` on the returned instance by the\nprevious method call -- this is what we called two-stage initialization --\nthe allocation stage and initialization stage, which is often compared with\nthe concept \"RAII\" (resource acquisition is initialization) oftenly used in\nC++.`), 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/ca10d5e5f4bfff7d4471ef101246df78/88eb9/nscalender-two-stage-initialization.png\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"a\",\n      props: {\n        \"title\": \"NSCalendar Two-Stage Initialization\",\n        \"alt\": \"NSCalendar Two-Stage Initialization\",\n        \"src\": \"/static/ca10d5e5f4bfff7d4471ef101246df78/88eb9/nscalender-two-stage-initialization.png\",\n        \"srcSet\": [\"/static/ca10d5e5f4bfff7d4471ef101246df78/88eb9/nscalender-two-stage-initialization.png 1x\", \"/static/cfa89498c1a02f69e390a92b08d0505b/10a61/nscalender-two-stage-initialization%402x.png 2x\", \"/static/e586e7352656abc6b95183f30311ec03/47be9/nscalender-two-stage-initialization%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            NSCalendar Two-Stage Initialization\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `To return an instance with derrived class of the abstract class, here is\n`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `NSCalendar`), `, we need to dispatch the returned instance in the allocation\nstage, which is `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `[NSCalendar +allocWithZone:]`), `. But since Swift keeps the\nallocation stage \"under-the-hood\", we are no longer able to do that way when\nmigrated to Swift.`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Thus we use a dedicated static function as a \"factory method\". And since\n`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `DeviceObject`), ` is an abstract class, the designated initializer `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `init()`), `\nand `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `init(from:)`), ` does nothing here (Yes, because that they are\ninitializers).`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Then implement `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Codable`), ` in `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `DeviceObject`), `'s derived classes.`), 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    }, `class PrinterObject: DeviceObject {\n    private enum _CodingKeys: CodingKey {\n        case printer\n    }\n\n    override var type: DeviceType { return .printer }\n\n    override var deviceValue: Device { return .printer(printer) }\n\n    let printer: Printer\n\n    init(printer: Printer) {\n        self.printer = printer\n        super.init()\n    }\n\n    required init(from decoder: Decoder) throws {\n        let container = try decoder.container(keyedBy: _CodingKeys.self)\n        printer = try container.decode(Printer.self, forKey: .printer)\n        \n        try super.init(from: decoder)\n    }\n\n    override func encode(to encoder: Encoder) throws {\n        var container = encoder.container(keyedBy: _CodingKeys.self)\n        try container.encode(printer, forKey: .printer)\n\n        try super.encode(to: encoder)\n    }\n}\n\nclass ScannerObject: DeviceObject {\n    private enum _CodingKeys: CodingKey {\n        case scanner\n    }\n\n    override var type: DeviceType { return .scanner }\n\n    override var deviceValue: Device { return .scanner(scanner) }\n\n    let scanner: Scanner\n\n    init(scanner: Scanner) {\n        self.scanner = scanner\n        super.init()\n    }\n\n    required init(from decoder: Decoder) throws {\n        let container = try decoder.container(keyedBy: _CodingKeys.self)\n        scanner = try container.decode(Scanner.self, forKey: .scanner)\n\n        try super.init(from: decoder)\n    }\n\n    override func encode(to encoder: Encoder) throws {\n        var container = encoder.container(keyedBy: _CodingKeys.self)\n        try container.encode(scanner, forKey: .scanner)\n\n        try super.encode(to: encoder)\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Then we can make `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Device`), ` to conform to `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Codable`), ` now.`), 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 Printer: Codable {}\nextension Scanner: Codable {}\n\nextension Device: Codable {\n    init(from decoder: Decoder) throws {\n        let deviceObject = try DeviceObject.make(decoder: decoder)\n        self = deviceObject.deviceValue\n    }\n    \n    func encode(to encoder: Encoder) throws {\n        try DeviceObject.make(device: self).encode(to: encoder)\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `Finally, all things done.`));\n  }\n\n}\nMDXContent.isMDXComponent = true;","scope":""},"headings":[{"value":"Understanding Associated Value Enums","depth":2},{"value":"Expressing Associated Value Enum in Object-Oriented World","depth":2},{"value":"Conforming to Codable","depth":2}]}}},"earlierPostExcerpt":{"slug":"/post/2019/03/a-glimpse-into-generic-meta-programming-in-swift-d2cd","title":"A Glimpse into Swift Generic Meta-Programming","subtitle":"Make VFL Reborn in Swift with Compile-Time Safety","createdTime":"2019-03-27T00:00:00.000Z","tags":["Swift","MetaProgramming","Generic","VFL","AutoLayout","macOS","iOS","tvOS"],"category":"Programming","file":{"childMdx":{"excerpt":"Preface What is the most critical thing swings your decision when you choose a\nprogramming language? Some people may say, the less lines of code they write, the better the\nlanguage itself is. (Nope, the best programming language is PHP.) OK. It might be true. But writing less code is not an…"}}},"laterPostExcerpt":{"slug":"/post/2022/03/unexplained-swiftui-the-programming-language-nature-of-swiftui-d20e","title":"Unexplained SwiftUI - The Programming Language Nature of SwiftUI","subtitle":"","createdTime":"2022-03-06T00:00:00.000Z","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 framework likes  Flutter ,  React.js  or  Vue.js  which rides on the trend of  declarative   stateless  UI programming. Even though there are some common points between them, SwiftUI is far different from…"}}}},"pageContext":{"postId":"8e601448-778d-51ca-a66b-b68b06248377","earlierPostId":"ce1c7301-5889-59f8-821a-d4832b9a64b6","laterPostId":"f06c1b0c-88ad-59b4-9a2c-690037a03ade"}}