Banner Grocer App

Weekly Design Challenge: Simplifying Innovation — building a grocery app using SwiftUI

We will be designing a mock UI for a grocery application using Apple’s brand new UI toolkit, yes you guys heard it right we will be using SwiftUI.

Vikas Kumar
9 min readJul 13, 2020

--

Introduction

SwiftUI is a new UI toolkit or framework designed and developed for the future of IOS programming. It’s set to enable users to leave behind the trouble of managing the XML, Storyboards, and ViewControllers all together. UIKit is still the most powerful UI toolkit to design IOS applications and it’s going nowhere for another 3 to 4 years. In fact, all major IOS app development is undertaken through the UIKit, making it essential for all developers to continue learning and investing in it.

We need to gradually move from adopting an imperative approach of designing apps to a more declarative or reactive way of solving problems. It’s been observed that using SwiftUI can improve the efficiency of developing applications by at least 50% while reducing effort in writing codes and focusing on business logic. Additionally, less code means fewer errors and greater visibility of the code. But it is still new and we need to keep creating content and make more developers aware of its shortcomings and benefits.

The most reliable way to predict the future is to create it. — Abraham lincoln

Well, that being said by Mr. President, let’s create something to inspire the next developer watching this post..

Let’s define Our goal

  • We will be creating a two-page app
    ☆ Home screen
    ☆ Details screen
  • Home screen will have the following reusable UI components:
    ☆ Toolbar or appbar component or navigation component
    ☆ Search bar component — products search
    ☆ Tabview component — categories list
    ☆ Gridview component — products list
  • Details screen will display the image showing the product in focus, a label showing the title, subtitle, description, delivery info, discount info, price, buttons to add, and remove product quantity, mark favorite, add the product to bag, etc
  • A way to load the images from API
  • A way to load the products and categories related to data from API services
  • A way to show the loader while fetching data from API services

App Screenshots / Mocks

Final UI For Grocer App

Let’s start with the new Xcode project

To create a new project we need to have the latest version of macOS Catalina 10.15. Xcode has a dependency on the new OS for the preview of live UI components from the canvas.

Open Xcode and click on

  • “Create a new Xcode project” * Make Sure “Single app view” is selected and click on the “Next” button. * On the next screen fill details related to “Product name”, Select the Language as “Swift”, the user interface as “SwiftUI” and click on the “Next” button to see the screen below. Next, you can see your all-new Xcode ready to strike and score some goals

But before that let’s understand some simple rules.

  • First Panel on the left is project explorer
  • The Second Panel is the code editor
  • The Third Panel is the SwiftUI widgets or Component and Modifiers list window that shows up on pressing cmd + shift + L. This comes in handy while drag and drop common components
  • The Fourth Panel is the Canvas or real device preview built-in right inside the Xcode which is one of my favorite features in Xcode. It greatly impacts productivity and uses the dynamic replacement of code to compile instantly and show the new preview in real-time as you make changes

Let’s create our first UI component

a) ToolbarView — This view is for providing a way to navigate to and fro between the screens or components.

Create a view folder inside your main project folder. Press CMD + N to create a new SwiftUI view file and name it ToolbarView.swift. Press enter and you will see a blank UI component with ‘hello world’. This is the default code we get in every SwiftUI file while creating. You can click on any view, press CMD + click to see more options related to the view and embed it inside some another UI component

Common UI components for holding the child view are

HStack, VStack, List, ZStack

In the above component, we are adding three views inside a container HStack view, HStack is used to place child views horizontally as the name implies. Here below is a rough sketch of how it is placed side-by-side. We have a Button view sitting next to Spacer which is again a view and provides space in between the elements. The third view is an Image view for showing the cart icon

ToolbarView view sketch

We have configured the Button to change the icon based on the @State hasNavigation property. SwiftUI can observe the changes within the UI component from the properties defined with @State. Whenever properties defined with @State changes within the given scope it will update or refresh the view. In our cases, it will replace the left arrow with a filter icon if navigation is set to false.

Similarly, we have properties defined with the @Envionment tag which is used for reading global properties, and any change to such property will reflect wherever it has been accessed and used. This makes it a good candidate for some global changes like applying dark modes or reading changes from core data. In our case, we are using this to close the enclosing UI component where the ToolbarView has been defined. One more interesting thing here is the PreviewProvider which is a preview generator and can be used to test different scenarios right inside the canvas. This shows us how our app will look based on different properties changes.

ToolbarView Component

b) SearchView — SearchView in our grocery app is to find the products in the currently selected tab. It is one of the interesting things I created in this app. It’s not only because of the functionality but because of the things I was able to achieve with such a small piece of code. Have a look at the code below for SearchView

I know what you guys are thinking now, who is this random guy SearchTextChangeObservable and what he does. Well fair enough, let me take you once again to the @State thing. It’s one of the ways we can listen to data changes before it is even reflected and change UI if needed or take some action but more for custom data types. In order to be an Observable, you need to implement an ObservableObject protocol and declare the field with @Published to make it a super property 🚀 , and then it can emit changes. In our case, we are using this to trigger a delegate method which we are listening to in the ContentView screen. We use @State for local properties with basic data types like String, Int, Float, etc. but ObservableObject gives us the ability to observe changes on custom data types also.

// search text change observablesclass SearchTextChangeObservable: ObservableObject { 
var searchChangeDelegate: SearchChangeDelegate?
@Published var searchText: String = "" {
didSet {
searchChangeDelegate?.onKeyChange(text: searchText.description)
}
}
}

The main idea here behind the view is to create a ZStack that holds a RoundedRectangle as the background and a HStack which holds the TextField and an Image view. Here is a preview of how a search view looks like.

SearchView Component

c) TabLayoutView — This view shows the different categories a grocery product can belong to, in this app we have simple categories like fruits, vegetables, dry fruits, nuts, and dairy. We load different products based on the selected tab. Here we are creating a HStack and adding the TabLayoutRow as an individual view for tab view using each loop. All this goes inside a ScrollView in order to scroll horizontally. We pass a CategorySelectedObservable which is again an Observable Property and notifies the child views to show the currently selected tab using a green line and the rest of the views will reset itself based on the selected tab ids.

CategoryItemModel is our data model for categories view which we will pass from the ContentView, aka Home screen. Here we have used a delegate also to notify the change in tab selection. Tab selection is being observed in the Home screen and we fetch data from API based on the selected ID and UI gets updated observing the Category Observer properties in the Home screen.

TabLayoutView Component

d) GroceryItemsView — This view is the most important component which holds our product data from the API. It is basically a GridStack component that can hold data vertically or horizontally varied by configuration. Inside GridStack we are passing a GroceryItemsRow as a single item view component

GroceryItemRow Component

e) GrocerDetailsView — This view component shows the details of the selected product. It has the most number of sub-components and is still able to show the details with much ease. This is the beauty of the SwiftUI. This view has the main details related to the product and a button to add the product to the cart, mark it as a favorite, increase and decrease the product quantity. Here we have reused the ToolbarView component as well.

GrocerDetailsView Component

f) ContentView — This is where the magic happens! All the views are glued to one another from this main UI component. ContentView has all the above UI components and works as the data observer as well as the data producer for the fellow UI components. It streams the data down the UI hierarchy using observers and state properties. On start, we have the loader showing while fetching data from the API, when data comes we change the state property isLoading to false, making the ContentView reload again and this time we show the products list. All the delegation callbacks are observed in ContentView only from SearchView as well as TabLayoutView components and show the appropriate data by changing the data models in observers.

g) Repository — We are using our beloved Alamofire as our HTTP network handler. Here is a basic structure of the API calls.

Network Architecture

We have used our Github repository as the server for serving the data over the API calls. Please visit the repo to see how the data is structured and how we are serving it when called from the app.

Final thoughts

I really enjoyed getting my hands dirty with the SwiftUI and implementing a mock UI. The ease and richness of the API’s that SwiftUI brings to the table is unmatched given the very first release till now. We will see many more superpowers coming our way. I would encourage all the IOS developers to get on board and give it a shot. This article represents more of the overview of the project and thinking that goes into it while developing it. To dive deeper 🕵and try it yourself please hit the URL below.

Credits / Links / References

https://stackoverflow.com/a/59171234/4517450
https://developer.apple.com/tutorials/swiftui/tutorials
https://material.io/develop/ios/components/snackbars/
https://github.com/pietropizzi/GridStack
https://github.com/Alamofire/Alamofire
https://dribbble.com/shots/8369400-Groceries-Shopping-Mobile-App

Disclaimer: The views, information, or opinions are personal and content or any assets created during the process are advised to be used for learning purposes only.

Suggestions / Feedbacks are always welcome

--

--