{"id":9136,"date":"2022-10-10T20:45:25","date_gmt":"2022-10-10T20:45:25","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=9136"},"modified":"2022-10-10T20:45:25","modified_gmt":"2022-10-10T20:45:25","slug":"properties-binding-property-wrappers-and-mvvm-with-swift","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/properties-binding-property-wrappers-and-mvvm-with-swift\/","title":{"rendered":"Properties, Binding, Property Wrappers and MVVM with Swift"},"content":{"rendered":"<p>Swift includes properties within the language (see <a href=\"https:\/\/docs.swift.org\/swift-book\/LanguageGuide\/Properties.html#\" rel=\"noopener\" target=\"_blank\">Properties<\/a>), but also supports (what we&#8217;d call in C#) property or data binding mechanisms.<\/p>\n<p>Before we get started, I&#8217;m writing this post as a learning exercise, I&#8217;d suggest you checkout the references at the bottom of the post for a much more in depth look at this subject.<\/p>\n<p>If you&#8217;re still reading, then let&#8217;s get started&#8230;<\/p>\n<p>To begin with we&#8217;ll look at how we declare properties in Swift first. For those coming from C# or similar languages, then the simplest stored property looks just like a field<\/p>\n<p><strong>Property Declarations<\/strong><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstruct MyModel {\r\n    var id: String;\r\n}\r\n<\/pre>\n<p>The above declaration is known as a stored property, in that we can store values with the specific instance of the <em>MyModel<\/em> type, this is really the equivalent of having a property with a default getter and setter.<\/p>\n<p>We can also declare properties as readonly like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstruct MyModel {\r\n    var id: String {\r\n        return &quot;SomeId&quot;\r\n    }\r\n}\r\n<\/pre>\n<p>Both of the above examples are basically properties using &#8220;shorthand syntax&#8221;, like C# we can also create properties with <em>get <\/em> and <em>set<\/em> keywords &#8211; of course these are useful if the setting of the property (for example) does more than just assign a value, hence we have a form (notice you can use <em>return<\/em> or in these example we&#8217;re using <em>implicit return<\/em><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstruct MyModel {\r\n    private var _id: String = &quot;SomeId&quot;\r\n        \r\n    var id: String {\r\n        get {\r\n            _id\r\n        }\r\n        set {\r\n            _id = newValue\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Property Observer<\/strong><\/p>\n<p>Property observers allow us to monitor a property change. For example if you have a struct\/class with the shorthand syntax for a property then we can <em>willSet<\/em> and\/or <em>didSet<\/em> to our property, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nstruct MyModel {\r\n    var id: String = &quot;&quot; {\r\n        willSet(newTitle) {\r\n            print(&quot;About to set value&quot;)\r\n        }\r\n        didSet {\r\n            if title != oldValue {\r\n                print(&quot;Set Value&quot;)\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Now when the property is about to be set, the <em>willSet<\/em> code is called and when a value changes <em>didSet<\/em> will be called. Obviously you wouldn&#8217;t want to do anything within these methods that could affect performance.<\/p>\n<p><strong>Property Wrapper<\/strong><\/p>\n<p>A Property Wrapper allows us to (well as the name suggests) wrap a property within a type that we can separate the storage of the property from functionality that acts upon that property. For example if our <em>title<\/em> has a length constraint, we might create a property wrapper to implement this functionality<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n@propertyWrapper\r\nstruct LengthConstraint {\r\n    private var value = &quot;&quot;\r\n    var wrappedValue: String {\r\n        get { value }\r\n        set { value = String(newValue.prefix(5)) }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Property Binding<\/strong><\/p>\n<p>So what&#8217;s this got to do with binding\/data binding\/property binding? Well we&#8217;ve now seen how we declare propeties and can add property wrappers to the property. Within SwiftUI we can use the <em>@Published<\/em> property wrapper to our property which gets observed by a UI element and when the value changes updates the UI or in the case of TextField, when changes are made to the text field it&#8217;s placed into our property.<\/p>\n<p>There are several different property wrappers for this type of functionality<\/p>\n<ul>\n<li>@Published &#8211; this is used on property classes, such as ObservableObject subclasses.<\/li>\n<li>@StateObject &#8211; this is used within a view to store an instance of an ObservableObject subclassed type<\/li>\n<li>@State &#8211; this allows us to store bindable data within a view<\/li>\n<li>@Binding &#8211; this is used in views which need to mutate a property owned by an ancestor view. In essences it&#8217;s like connecting to a parent&#8217;s property<\/li>\n<li>@EnvironmentObject &#8211; this is a shared object stored within the environment and is used in situations where passing properties through a UI hierarchy or the likes becomes too cumbersome.<\/li>\n<li>@Environment &#8211; this is used to connect to actual environment properties, such as reading whether the application is in dark theme or other SwiftUI properties<\/li>\n<\/ul>\n<p><strong>MVVM<\/strong><\/p>\n<p>We can declares @State and @Binding property wrappers (for example) within our view, but of course this can pollute the UI with view model state. If we prefer to go with a MVVM approach, i.e. separate the view from the view model, then we will start off by subclassing ObservableObject, for example here&#8217;s a minimal view model<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n@MainActor class ViewModel: ObservableObject {\r\n    @Published var title: String = &quot;&quot;\r\n}\r\n\r\n@StateObject private var viewModel = ViewModel()\r\n<\/pre>\n<p>In the above code we declare and subclass of the ObservableObject and then we declare the properties that we wish to expose. The @StateObject line is what you&#8217;ll have in your ContentView to create an instance of the ObservableObject.<\/p>\n<p>The @MainActor is used to denote that this class runs code on the main queue &#8211; essentially if you&#8217;re used to Windows UI programming this can be seen as equivalent to running code on the UI thread.<\/p>\n<p>This of course might seem simpler to just declare properties like this, but then our model ends up more tightly coupled to the view than we might want<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n@State var title: String = &quot;&quot;\r\n<\/pre>\n<p><strong>References<\/strong><\/p>\n<p><a href=\"https:\/\/www.hackingwithswift.com\/quick-start\/swiftui\/all-swiftui-property-wrappers-explained-and-compared\" rel=\"noopener\" target=\"_blank\">All SwiftUI property wrappers explained and compared<\/a><br \/>\n<a href=\"https:\/\/www.hackingwithswift.com\/quick-start\/concurrency\/how-to-use-mainactor-to-run-code-on-the-main-queue\" rel=\"noopener\" target=\"_blank\">How to use @MainActor to run code on the main queue<\/a><br \/>\n<a href=\"https:\/\/www.hackingwithswift.com\/quick-start\/swiftui\/what-is-the-environment-property-wrapper\" rel=\"noopener\" target=\"_blank\">What is the @Environment property wrapper?<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Swift includes properties within the language (see Properties), but also supports (what we&#8217;d call in C#) property or data binding mechanisms. Before we get started, I&#8217;m writing this post as a learning exercise, I&#8217;d suggest you checkout the references at the bottom of the post for a much more in depth look at this subject. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[286,287],"tags":[],"class_list":["post-9136","post","type-post","status-publish","format-standard","hentry","category-swift","category-swiftui"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=9136"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9136\/revisions"}],"predecessor-version":[{"id":9148,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9136\/revisions\/9148"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=9136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=9136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=9136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}