Rediscovering Structs: Your Chatbot UI for ChatGPT

Computer Science Diaries
8 min readMar 29, 2023

--

How to Build a Chatbot Interface in SwiftUI Using Structs

Have you ever wanted to create a chatbot interface for your app using SwiftUI? If so, you’re in luck! In this article, I’ll show you how to build a chatbot interface in SwiftUI using structs. Structs are a powerful way to model data and logic in Swift, and they work well with SwiftUI’s declarative syntax. By the end of this article, you’ll have a chatbot interface that looks something like this:

What is a chatbot interface?

A chatbot interface is a user interface that allows users to interact with a chatbot. A chatbot is a software program that can simulate a conversation with a human using natural language. Chatbots can be used for various purposes, such as customer service, entertainment, education, or information retrieval.

A chatbot interface typically consists of two main components: an input field where users can type their messages, and an output area where users can see the chatbot’s responses. The input field may also have some features such as voice recognition, autocorrect, or suggestions. The output area may also have some features such as images, emojis, or buttons.

Photo by Andrew Neel on Unsplash

Why use SwiftUI?

SwiftUI is a modern framework for building user interfaces in Swift. It has many advantages over the traditional UIKit framework, such as:

  • Declarative syntax: SwiftUI lets you describe what your UI should look like, rather than how to create it. This makes your code more readable, concise, and maintainable.
  • State-driven updates: SwiftUI automatically updates your UI when your data changes, without requiring you to write any boilerplate code. This makes your UI more responsive and consistent.
  • Live previews: SwiftUI lets you see your UI in real time as you write your code, without having to run your app on a simulator or device. This makes your development process faster and easier.
  • Cross-platform compatibility: SwiftUI lets you build UIs for various platforms, such as iOS, macOS, watchOS, and tvOS, using the same code base. This makes your app more scalable and adaptable.
Photo by Levart_Photographer on Unsplash

How to use structs?

Structs are a type of value type in Swift. They are used to define custom data types that can store properties and methods. Structs are ideal for modeling data and logic that are independent and immutable. For example, you can use structs to represent entities such as users, messages, books, etc.

Structs have many benefits over classes, such as:

  • Value semantics: Structs are copied by value when passed around, rather than by reference. This means that each instance of a struct has its own copy of the data, and modifying one instance does not affect another. This makes your code more predictable and safe.
  • Mutability control: Structs are immutable by default, meaning that their properties cannot be changed after initialization. This prevents accidental mutations and inconsistencies in your data. If you need to change the properties of a struct, you can use the mutating keyword to mark the methods that can modify the state.
  • Performance optimization: Structs are stored on the stack, rather than on the heap. This means that they are allocated and deallocated faster than classes, which reduces memory overhead and improves performance.

To use structs in SwiftUI, you need to conform them to the Codable protocol. This protocol allows you to encode and decode structs from various formats, such as JSON or plist. This is useful for storing and retrieving data from local or remote sources.

How to build a chatbot interface in SwiftUI using structs?

Now that we have covered the basics of SwiftUI and structs, let’s see how we can build a chatbot interface in SwiftUI using structs. We will follow these steps:

  1. Define the model layer using structs
  2. Define the view layer using SwiftUI
  3. Define the controller layer using @State and @Binding
  4. Test the chatbot interface using live previews

Step 1: Define the model layer using structs

The first step is to define the model layer using structs. The model layer is responsible for storing and managing the data and logic of our app. In our case, we need two structs: one for representing a message, and one for representing a user.

The message struct will have three properties: an id, a text, and a sender. The id will be a UUID that uniquely identifies each message. The text will be a string that contains the content of the message. The sender will be an enum that indicates whether the message was sent by the user or by the chatbot.

The user struct will have two properties

a name and an avatar. The name will be a string that contains the user’s name. The avatar will be a string that contains the URL of the user’s profile picture.

Here is the code for the message and user structs:

// Message struct
struct Message: Codable, Identifiable {
var id: UUID
var text: String
var sender: Sender

enum Sender: String, Codable {
case user
case chatbot
}
}
// User struct
struct User: Codable, Identifiable {
var id: UUID
var name: String
var avatar: String
}

Step 2: Define the view layer using SwiftUI

The next step is to define the view layer using SwiftUI. The view layer is responsible for displaying and updating the user interface of our app. In our case, we need two views: one for representing a message cell, and one for representing the chat screen.

The message cell view will have two subviews: an image view that shows the sender’s avatar, and a text view that shows the message text. The message cell view will also have some modifiers to adjust its appearance and layout, such as padding, background color, corner radius, alignment, etc.

The chat screen view will have three subviews: a navigation bar that shows the title of the chat, a scroll view that shows the list of messages, and a text field that allows users to input their messages. The chat screen view will also have some state variables to store the current input text and the array of messages.

Here is the code for the message cell and chat screen views:

// Message cell view
struct MessageCellView: View {
var message: Message

var body: some View {
HStack(alignment: .bottom) {
if message.sender == .user {
Spacer()
}
Image(message.sender.rawValue)
.resizable()
.frame(width: 40, height: 40)
.clipShape(Circle())
Text(message.text)
.padding()
.background(message.sender == .user ? Color.blue : Color.gray)
.foregroundColor(.white)
.cornerRadius(10)
if message.sender == .chatbot {
Spacer()
}
}
}
}
// Chat screen view
struct ChatScreenView: View {
@State private var inputText = ""
@State private var messages = [Message]()
var body: some View {
NavigationView {
VStack {
ScrollView {
ForEach(messages) { message in
MessageCellView(message: message)
}
}
TextField("Type something...", text: $inputText)
.padding()
.background(Color(UIColor.systemGray6))
.cornerRadius(10)
.padding(.horizontal)
}
.navigationBarTitle("Chatbot")
}
}
}

Step 3: Define the controller layer using @State and @Binding

The final step is to define the controller layer using @State and @Binding. The controller layer is responsible for handling the user interactions and updating the data and UI accordingly. In our case, we need to implement two functions: one for sending a message from the user to the chatbot, and one for receiving a message from the chatbot to the user.

To send a message from the user to the chatbot, we need to do three things:

  • Append the input text to the messages array as a user message
  • Clear the input text field
  • Call a function that generates a response from the chatbot

To receive a message from the chatbot to the user, we need to do one thing:

  • Append the response text to the messages array as a chatbot message

To implement these functions, we need to use two property wrappers: @State and @Binding. @State allows us to declare state variables that can be mutated and trigger UI updates. @Binding allows us to pass state variables as references to other views or functions.

Here is the code for sending and receiving messages:

// Send a message from the user to the chatbot
func sendMessage() {
// Append the input text as a user message
let userMessage = Message(id: UUID(), text: inputText, sender: .user)
messages.append(userMessage)

// Clear the input text field
inputText = ""
// Generate a response from the chatbot
generateResponse(userMessage.text)
}
// Receive a message from the chatbot to the user
func receiveMessage(_ responseText: String) {
// Append the response text as a chatbot message
let chatbotMessage = Message(id: UUID(),
text: responseText, sender: .chatbot) messages.append(chatbotMessage) }

Step 4: Test the chatbot interface using live previews

The last step is to test the chatbot interface using live previews. Live previews are a feature of SwiftUI that allow you to see your UI in real time as you write your code, without having to run your app on a simulator or device. Live previews are useful for debugging and experimenting with your UI.

To use live previews, you need to add a preview provider struct at the bottom of your code file. This struct conforms to the PreviewProvider protocol and provides a static property called previews that returns a view. You can customize the preview by adding modifiers such as .previewLayout, .previewDevice, or .previewDisplayName.

Here is the code for the preview provider struct:

// Preview provider struct
struct ChatScreenView_Previews: PreviewProvider {
static var previews: some View {
ChatScreenView()
.previewLayout(.sizeThatFits)
.previewDevice("iPhone 12")
.previewDisplayName("Chatbot Interface")
}
}

To see the live preview, you need to open the canvas by clicking on the resume button at the top right corner of your code editor. You should see something like this:

You can interact with the live preview by typing in the text field and clicking on the submit button. You should see your messages and the chatbot’s responses appear in the scroll view. You can also change the code and see how it affects the UI instantly.

Conclusion

In this article, we learned how to build a chatbot interface in SwiftUI using structs. We covered the basics of SwiftUI and structs, and how to use them to create a simple chatbot app. We also learned how to use live previews to test and debug our UI.

I hope you enjoyed this article and learned something new. If you have any questions or feedback, feel free to leave a comment below. Thanks for reading!

References

--

--