{"componentChunkName":"component---src-templates-article-js","path":"/article/swiftui-smarthomesettings-ui","result":{"data":{"contentfulArticle":{"title":"Smart Home Settings UI","image":"https://res.cloudinary.com/liquidcoder/image/upload/v1597489113/smarthomesettings/um3a8juchh4xcpvuizjq.jpg","createdDate":"Thursday, 01 August 2019","videoUrl":"KjDuVAvQOzk","updatedDate":"2 years ago","isNewLayout":null,"previews":null,"slug":"swiftui-smarthomesettings-ui","author":{"email":"john@liquidcoder.com","name":"John"},"tags":[{"title":"Article"},{"title":"Free"},{"title":"Swift UI"},{"title":"UI Design"}],"allChapters":null,"code":null,"explanation":null,"downloads":[{"name":"Project source code","url":"https://github.com/liquidcoder1/SmartHomeSettings/archive/master.zip"}],"resources":[{"name":"Apple developer documentation","url":"https://developer.apple.com/documentation/swiftui"},{"name":"Hacking with swift","url":"https://www.hackingwithswift.com"},{"name":"Swift by sundell","url":"https://www.swiftbysundell.com"}],"body":{"childMdx":{"tableOfContents":{"items":[{"url":"#introduction","title":"Introduction"},{"url":"#requirements","title":"Requirements"},{"url":"#get-started","title":"Get started"},{"url":"#grid-view","title":"Grid View"},{"url":"#place-view","title":"Place View"},{"url":"#sliderview","title":"SliderView"},{"url":"#slider-component","title":"Slider component"},{"url":"#create-places-list-component","title":"Create Places List Component"},{"url":"#putting-everything-together","title":"Putting everything together"}]},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _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\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h2\", null, \"Introduction\"), mdx(\"p\", null, \"This article will be a 2 parts series divided like this: \"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Part 1: The user interface\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Part 2: Persist data with core data\")), mdx(\"h2\", null, \"Requirements\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Xcode 12 or greater\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"MacOS Catalina or greater\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Swift 5.0 or greater\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"iOS 14 or greater\")), mdx(\"h2\", null, \"Get started\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Open Xcode\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Create a new Xcode project\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Select single view app and click next\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Name your app (Mine will be SmartHomeSettings) and make sure the user interface is Swift UI and also include \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"CoreData\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Last, click Finish.\")), mdx(\"p\", null, \"Rename the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ContentView\"), \" filename and struct to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SmartHomeSettings\"), \", and make sure you rename its reference in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SceneDelegate\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {\\n    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.\\n    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.\\n    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).\\n\\n    // Create the SwiftUI view that provides the window contents.\\n    let smartHomeSettings = SmartHomeSettings()\\n\\n    // Use a UIHostingController as window root view controller.\\n    if let windowScene = scene as? UIWindowScene {\\n        let window = UIWindow(windowScene: windowScene)\\n        window.rootViewController = UIHostingController(rootView: smartHomeSettings)\\n        self.window = window\\n        window.makeKeyAndVisible()\\n    }\\n}\\n\")), mdx(\"p\", null, \"Change everywhere you see \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ContentView\"), \" referenced to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SmartHomeSettings\"), \".\"), mdx(\"h2\", null, \"Grid View\"), mdx(\"p\", null, \"After making the above changes, the first thing to do is to create a folder named \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Views\"), \" , and inside it add a swiftUI file named GridView. The gridView will represent the number of lights in a particular room or place.\"), mdx(\"p\", null, \"Add the following properties at the top of the file:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \" var numberOfLights:CGFloat = 13.0\\n var numberOfColumn:CGFloat = 4.0\\n var lightSize: CGFloat = 20\\n var vSpacing: CGFloat = 10\\n var hSpacing: CGFloat = 20\\n var placeName = \\\"Work\\\"\\n\")), mdx(\"p\", null, \"Then in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"body\"), \" block, replace what\\u2019s there with the following:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"let numberOfRows = Int(numberOfLights / numberOfColumn)\\n        let remainingRows = ceil(numberOfLights.truncatingRemainder(dividingBy: numberOfColumn))\\n        \\n        return Group{\\n            VStack(alignment: .leading, spacing: vSpacing) {\\n                ForEach(0..<numberOfRows){ i in\\n                    HStack( spacing: self.hSpacing) {\\n                        ForEach(0..<Int(self.numberOfColumn)){_ in\\n                            Circle()\\n                                .frame(width: self.lightSize, height: self.lightSize)\\n                                .foregroundColor(Color.gray)\\n                        }\\n                    }\\n                    \\n                }\\n                HStack( spacing: hSpacing) {\\n                    ForEach(0..<Int(remainingRows)){_ in\\n                        Circle()\\n                            .frame(width: self.lightSize, height: self.lightSize)\\n                            .foregroundColor(Color.gray)\\n                    }\\n                }\\n            }\\n        }\\n\")), mdx(\"p\", null, \"That block of code creates a grid of circles.\\n\", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"\\xA0Previews\"), \"\\n\", mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1572469317/smarthomesettings/j3epofmvishv7fqhgvao.png\",\n    \"alt\": null\n  }))), mdx(\"h2\", null, \"Place View\"), mdx(\"p\", null, \"In the same folder, create a file named PlaceView and add this at the top  of the struct:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"    var brightnessLevel: CGFloat = 0\\n    var isSelected  = false\\n    var numberOfLights:CGFloat = 13\\n    var numberOfColumn:CGFloat = 4.0\\n    var lightSize: CGFloat = 20\\n    var vSpacing: CGFloat = 10\\n    var hSpacing: CGFloat = 10\\n    var placeName = \\\"Work\\\"\\n    var lightColor = \\\"neatRed\\\"\\n\")), mdx(\"p\", null, \"Most of these properties are just duplicates of the ones that we have in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GridView\"), \". You will see how they will be used shortly. \"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"            HStack {\\n                Circle()\\n                    .foregroundColor(Color(lightColor)).frame(width: 30, height: 30)\\n                \\n                HStack(spacing: 30) {\\n                    VStack(alignment: .leading) {\\n                        Text(\\\"\\\\(self.placeName)\\\").fontWeight(.bold).foregroundColor(Color(\\\"bg\\\"))\\n                        Text(\\\"\\\\(Int(self.numberOfLights)) lights\\\").font(.footnote).foregroundColor(Color(lightColor))\\n                        \\n                        GridView(numberOfLights: self.numberOfLights, numberOfColumn: self.numberOfColumn, lightSize: self.lightSize, vSpacing: self.vSpacing, hSpacing: self.hSpacing, placeName: self.placeName)\\n                    }\\n                    \\n                    VStack(spacing: -7) {\\n                        GeometryReader { gr in\\n                            Rectangle().offset(y: gr.size.height * (1 - self.brightnessLevel))\\n                                .foregroundColor(Color(self.lightColor))\\n                        }\\n                    }.frame(width: 10)\\n                        .background(Color(self.lightColor).opacity(0.2))\\n                        .cornerRadius(50)\\n                    \\n                }.padding().modifier(Border(cornerRadius: 5, width: 1, color: isSelected ? Color(lightColor) : Color.gray.opacity(0.5)))\\n        }\\n\")), mdx(\"p\", null, \"This block of code does the following things:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Creates a circle aligned on the left.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Creates \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"VStack\"), \" container that holds 2 Texts and the lights gridView.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Creates a progress bar that will reflect the brightness level of lights.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"And Wraps them into a HStack.\\n\", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Previews\"))), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1572470965/smarthomesettings/z8gakygy7x8lgoiukkfs.png\",\n    \"alt\": null\n  }))), mdx(\"h2\", null, \"SliderView\"), mdx(\"p\", null, \"We will need to create a new swiftUI file named \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SliderView\"), \". It will be the control that we will use to adjust the brightness level. We will create it in such a way that it will be reused easily. \"), mdx(\"p\", null, \"In \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SliderView\"), \" struct, add these properties:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"    \\n    @Binding var lightColor: String\\n    @State var offsetY: CGFloat = 0.0\\n    var onChange: ((_ value: CGFloat)->()) = {_ in }\\n    var sliderWidth:CGFloat = 80\\n    \\n\")), mdx(\"p\", null, \"All those properties, except the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onChange\"), \" , do not need  any explanation, as for the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onChange\"), \", it will be called every time the sliderView changes value by sliding the handle up or down, and the value will be a range between  0  and 1.\"), mdx(\"p\", null, \"Now, in the body block replace everything in there with the following:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"     GeometryReader { gr in\\n            VStack(spacing: -7) {\\n                ZStack() {\\n                    Rectangle().frame(width: 100, height: 3).foregroundColor(Color(\\\"bg\\\"))\\n                    Rectangle().frame(width: 70, height: 15).cornerRadius(7.5).foregroundColor(Color(\\\"bg\\\"))\\n                }.offset( y: self.offsetY)\\n                    .gesture(DragGesture().onChanged({ drag in\\n                        self.offsetY = min(max(drag.location.y, 0), gr.size.height - 7)\\n                        let value = 1 - self.offsetY / (gr.size.height - 7)\\n                        self.onChange(value)\\n                    }))\\n                \\n                Rectangle().frame(height: gr.size.height - 7).offset(y: self.offsetY)\\n                    .foregroundColor(Color(self.lightColor))\\n            }.frame(width: self.sliderWidth, height: gr.size.height, alignment: .bottom)\\n                .background(Color(self.lightColor).opacity(0.2))\\n                .cornerRadius(50)\\n        }\\n\")), mdx(\"p\", null, \"You will get an error that you can fix by adding this in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SliderView()\"), \" call in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SliderView_Previews\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"lightColor: .constant(\\\"neatRed\\\")\\n\")), mdx(\"p\", null, \"The above block of code does the following:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Creates the handle by putting 2 rectangles in a \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ZStack\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Stacks Vertically the handle with a new rectangle that will indicate the progress.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Surrounds everything with a \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"GeometryReader\"), \" container to make the control responsive on any screen size.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Adds a drag gesture on the handle to update the yOffset of the rectangle that represent the progress.  And in the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onChange\"), \" block, we will call the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onChange\"), \" closure with the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"percent\"), \" value.\")), mdx(\"h2\", null, \"Slider component\"), mdx(\"p\", null, \"Create a folder named \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Components\"), \" and inside it create a file named \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SliderComponent\"), \". Replace everything inside that file with the following:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"import SwiftUI\\n\\nstruct SliderComponentt: View {\\n    @Binding var selectLightColor: String\\n    @Binding var brightnessLevel: CGFloat\\n    \\n    var body: some View {\\n        GeometryReader { gr in\\n            VStack {\\n                Image(systemName: \\\"sun.min.fill\\\")\\n                    .resizable()\\n                    .frame(width: 30, height: 30)\\n                    .foregroundColor(Color(self.selectLightColor))\\n                    .shadow(color: Color(self.selectLightColor), radius: 7, x: 0, y: 0)\\n                    .opacity(0.2 + Double(self.brightnessLevel))\\n                \\n                SliderView(lightColor: self.$selectLightColor, onChange: { value in\\n                    self.brightnessLevel = value\\n                })\\n                    .frame(height: gr.size.height * 0.7)\\n                Image(systemName: \\\"sun.max\\\")\\n                    .resizable()\\n                    .frame(width: 30, height: 30)\\n                    .foregroundColor(Color(self.selectLightColor))\\n            }\\n        }\\n    }\\n}\\n\\nstruct SliderComponentt_Previews: PreviewProvider {\\n    static var previews: some View {\\n        SliderComponentt(selectLightColor: .constant(\\\"neatRed\\\"), brightnessLevel: .constant(0.5))\\n    }\\n}\\n\\n\")), mdx(\"p\", null, \"That block of code is pretty simple. It just creates the following component:\"), mdx(\"p\", null, mdx(\"img\", _extends({\n    parentName: \"p\"\n  }, {\n    \"src\": \"https://res.cloudinary.com/liquidcoder/image/upload/v1572552470/smarthomesettings/oefceoqehnym8cem2alb.png\",\n    \"alt\": null\n  }))), mdx(\"h2\", null, \"Create Places List Component\"), mdx(\"p\", null, \"Before creating this component,  create a new folder named \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Models\"), \" and inside it add\\na file named \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Place\"), \". Add the following code inside the file:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"import SwiftUI\\n\\n\\nstruct Place:  Hashable, Identifiable{\\n    \\n    var id = UUID()\\n    let name: String\\n    let numberOfLights: Int\\n    let lightColor: String\\n    let brightnessLevel: CGFloat\\n    \\n    init(name: String = \\\"\\\", numberOfLights: Int = 0, lightColor: String = \\\"\\\", brightnessLevel: CGFloat = 0) {\\n        self.name = name\\n        self.numberOfLights = numberOfLights\\n        self.lightColor = lightColor\\n        self.brightnessLevel = brightnessLevel\\n    }\\n    \\n    \\n    static func getDummyData() -> [Place] {\\n        [\\n            Place(name: \\\"Work\\\", numberOfLights: 5, lightColor: \\\"brightGreen\\\", brightnessLevel: 0.7),\\n            Place(name: \\\"Floor\\\", numberOfLights: 11, lightColor: \\\"heavenBlue\\\", brightnessLevel: 0.2),\\n            Place(name: \\\"Kitchen\\\", numberOfLights: 8, lightColor: \\\"justPurple\\\", brightnessLevel: 0.4),\\n            Place(name: \\\"Bedroom\\\", numberOfLights: 15, lightColor: \\\"neatRed\\\", brightnessLevel: 0.8),\\n            Place(name: \\\"Living Room\\\", numberOfLights: 17, lightColor: \\\"notYellow\\\", brightnessLevel: 0.5)\\n        ]\\n    }\\n    \\n}\\n\\n\")), mdx(\"p\", null, \"The above code just creates some dummy data that we can use to populate the place list view. \"), mdx(\"p\", null, \"Create a new file in the component folder named \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"PlacesListComponent\"), \" and put the following code inside:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"import SwiftUI\\n\\nstruct PlacesListComponent: View {\\n    \\n    @Binding var brightnessLevel: CGFloat\\n    var places: [Place] = Place.getDummyData()\\n    @Binding var selectLightColor: String\\n    @Binding var selectedPlace: Place\\n    \\n    var body: some View {\\n        ScrollView( showsIndicators: false) {\\n            ForEach(places, id: \\\\.id){ place in\\n                Button(action: {\\n                    withAnimation{\\n                        self.selectLightColor = place.lightColor\\n                        self.selectedPlace = place\\n                    }\\n                }) {\\n                    PlaceView(brightnessLevel: self.selectedPlace.id == place.id ? self.brightnessLevel : CGFloat(0.5), isSelected: self.selectedPlace.id == place.id ,numberOfLights: CGFloat(place.numberOfLights),placeName: place.name , lightColor: place.lightColor)\\n                }\\n            }.padding(.horizontal)\\n        }.onAppear{\\n            self.selectLightColor = self.places.first?.lightColor ?? \\\"neatRed\\\"\\n            self.selectedPlace = self.places.first ?? Place()\\n        }\\n    }\\n}\\n\\nstruct PlacesListComponent_Previews: PreviewProvider {\\n    static var previews: some View {\\n        PlacesListComponent(brightnessLevel: .constant(0.5), selectLightColor: .constant(\\\"neatRed\\\"), selectedPlace: .constant(Place.getDummyData()[0]))\\n    }\\n}\\n\\n\")), mdx(\"p\", null, \"The above block of code does the following:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Iterates through the places array and for each place, create a button with \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"PlaceView\"), \" as content. The button action will handle the selection and deselection of the placeView.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Set the first item in the array selected in the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onAppear\"), \" block.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Then wraps everything in a \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"scrollView\"), \".\")), mdx(\"h2\", null, \"Putting everything together\"), mdx(\"p\", null, \"Now, open the SmartHomeSettings file and  put these properties at the top:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"  @State var brightnessLevel: CGFloat = 0.9\\n    private let places = Place.getDummyData()\\n    @State var selectLightColor = \\\"justPurple\\\"\\n    @State var selectedPlace = Place()\\n    @State var placeName: String  = \\\"\\\"\\n    @State var numberOfLights: String  = \\\"\\\"\\n\")), mdx(\"p\", null, \"Don\\u2019t worry we\\u2019ve already dealt with most of those properties.\"), mdx(\"p\", null, \"Replace what\\u2019s in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"body\"), \" with the following:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"NavigationView {\\n                HStack {\\n                    PlacesListComponent(brightnessLevel: self.$brightnessLevel, places: self.places, selectLightColor: self.$selectLightColor, selectedPlace: self.$selectedPlace)\\n                    SliderComponentt(selectLightColor: self.$selectLightColor, brightnessLevel: self.$brightnessLevel)\\n                    \\n                }.navigationBarItems(leading: Button(action: {\\n                }) {\\n                    Image(systemName: \\\"arrow.left\\\").resizable().modifier(NavIconStyle())\\n                }, trailing: trailingButton())\\n\\n        }\\n\")), mdx(\"p\", null, \"You will get an error because there\\u2019s no \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"trailingButton()\"), \" method. Add the following  in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"body\"), \" block to fix the error:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \"    \\n    private func trailingButton() -> some View{\\n        return Button(action: {\\n  \\n                print(\\\"Add new place\\\")\\n            \\n        }) {\\n            Image(systemName: \\\"plus\\\")\\n                .resizable()\\n                .modifier(NavIconStyle())\\n        }\\n    }\\n\")), mdx(\"p\", null, \"If you want to see the preview in dark mode, add the following modifier to  \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SmartHomeSettings\"), \" call in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SmartHomeSettings_Previews\"), \": \"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-swift\"\n  }), \".environment(\\\\.colorScheme, .dark)\\n\")), mdx(\"p\", null, \"That\\u2019s it for the first part. Stay tuned for the second part. Subscribe for more.\"));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"Introduction This article will be a 2 parts series divided like this:  Part 1: The user interface Part 2: Persist data with core data Requirements Xcode 12 or greater MacOS Catalina or greater Swift 5.0 or greater iOS 14 or greater Get started Open Xcode Create a new Xcode project Select single view…"}}}},"pageContext":{"slug":"swiftui-smarthomesettings-ui"}},"staticQueryHashes":["1047155515","1278771865","2517639938","2517639938","2537039069","3452127246","3566879862","3891201089","439617394","670651827"]}