ChatGPT and iOS App Development— The Buzzword of 2023

Developing iOS applications with the ChatGPT talks!!!
Jan 11 2023 · 10 min read

What is ChatGPT?

ChatGPT is a variant of the GPT (Generative Pre-trained Transformer) language model, which is a tool for generating natural language text.

A new Gold Standard of AI-based language generation to create written content at the speed of thought.

It has been trained on a large dataset by OpenAI which is capable of generating human-like text based on the input it receives.

For example, you could use ChatGPT to generate text for user interfaces, such as button labels or error messages. You could also use ChatGPT to generate code snippets or sample data for testing or other purposes.

However, it is important to keep in mind that ChatGPT is a machine-learning model, so the quality of its output will depend on the quality and relevance of the input it receives.

Therefore, it is important to carefully consider the prompts you provide and to review the generated output to ensure it is accurate and appropriate for your needs.

How to use ChatGPT?

To use ChatGPT for these purposes, you would simply need to provide it with relevant prompts and then use the generated text as needed in your app development process.

For example, you might input the prompt “Write a short story about a person who discovers a hidden treasure” to get ChatGPT to generate a short story about finding a hidden treasure.

Here are a few tips for using ChatGPT effectively:

  • Start with a clear and concise prompt that sets the context for the text you want ChatGPT to generate.
  • Use specific and descriptive language in your prompt to give ChatGPT a better idea of what you are looking for.
  • If you want ChatGPT to generate longer pieces of text, you may need to provide a longer prompt with enough context that is enough to give ChatGPT a good understanding of the topic you are interested in.
  • If you are not happy with the text that ChatGPT generates, you can try adjusting your prompt or rephrasing it to get a different result.
  • Be patient and give ChatGPT enough time to process your prompt and generate text.

Today we’ll create a TODO app by using ChatGPT and we’ll learn how to question ChatGPT for getting proper output from it.

ChatGPT Conversation

Everything that follows from this point forward is my input prompts, followed by ChatCGP’s responses, complete with sample code.

Let’s start with our first question.

Its answer may not be the same for you as it may vary all the time. Even for me, if I ask the same question within 1–2 minutes, it will give different responses!

1. Basic Startup

Can you create a simple todo app in SwiftUI?

Yes, I can provide an example of a simple to-do app built with SwiftUI. Here is an example of a basic Todo app that allows users to add, remove, and mark tasks as complete:

import SwiftUI

class Todo {
    var task: String
    var isComplete: Bool
}

struct TodoList: View {
    @State var todos: [Todo] = []
    
    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(todos.indices) { index in
                        HStack {
                            Text(self.todos[index].task)
                            Spacer()
                            Button(action: {
                                self.todos[index].isComplete.toggle()
                            }) {
                                Image(systemName: self.todos[index].isComplete ? "checkmark.square" : "square")
                            }
                        }
                    }
                    .onDelete { indexSet in
                        self.todos.remove(atOffsets: indexSet)
                    }
                }
                HStack {
                    TextField("New task", text: $newTask)
                    Button(action: {
                        self.todos.append(Todo(task: self.newTask, isComplete: false))
                        self.newTask = ""
                    }) {
                        Image(systemName: "plus")
                    }
                }
                .padding()
            }
            .navigationBarTitle("Todo")
            .navigationBarItems(trailing: EditButton())
        }
    }
    
    @State private var newTask = ""
}

struct TodoList_Previews: PreviewProvider {
    static var previews: some View {
        TodoList()
    }
}

This example uses a struct called Todo to represent a task in the app, which contains the task itself and a isComplete flag. The TodoList struct displays the list of todos and a text field for adding new tasks, with a button that appends the new task to the list when tapped.

The list of todos is stored in an array, and the app uses the List and ForEach views to display the tasks. Tasks can be marked as complete by tapping on the corresponding button and can be deleted by swiping left and hitting the delete button.

You can also customize the UI to your specific needs and it is just a simple example, it doesn’t include all the functionalities you may need in a complete Todo App.

2. Organize the View Structure

But I’m not satisfied with this answer as its data class doesn’t have the id field that we need and the created view structure for UI is also not that much clear.

To get an answer with all the requirements we have to ask a more clarified question to ChatGPT with all details, like

Can you design a todo application that includes a data class with an “id” field, and also has a well-organized, view-divided structure?

But as the ChatGPT allows us continuous questioning we can ask it accordingly like,

Can you provide its data class that has an id field and then create a todo app in a proper way that has a view-divided structure?

As given in the above question, it’s not required to mention all the core things in the question each time when we are asking for assistance, we can phrase our questions as if we were speaking to a person.

And it’ll give us a proper answer like this,

Sure! Here’s an example of a Todo data class that includes an id field, and a more structured version of the Todo app that separates the views into different structs:

import SwiftUI

class Todo: Identifiable {
    var id = UUID()
    var task: String
    var isComplete: Bool

    init(task: String, isComplete: Bool = false) {
        self.task = task
        self.isComplete = isComplete
    }
}

class TodoListViewModel: ObservableObject {
    @Published var todos: [Todo]

    init(todos: [Todo] = []) {
        self.todos = todos
    }

    func addTodo(task: String) {
        todos.append(Todo(task: task))
    }

    func deleteTodo(at indexSet: IndexSet) {
        todos.remove(atOffsets: indexSet)
    }

    func toggleComplete(id: UUID) {
        if let index = todos.firstIndex(where: {$0.id == id}) {
            todos[index].isComplete.toggle()
        }
    }
}

struct TodoListView: View {
    @ObservedObject var viewModel: TodoListViewModel = .init()

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(viewModel.todos) { todo in
                        TodoRow(todo: .constant(todo), toggleComplete: self.viewModel.toggleComplete)
                    }
                    .onDelete { indexSet in
                        self.viewModel.deleteTodo(at: indexSet)
                    }
                }

                TodoTextField(addTodo: self.viewModel.addTodo)
            }
            .navigationBarTitle("Todo")
            .navigationBarItems(trailing: EditButton())
        }
    }
}

struct TodoRow: View {

    @Binding var todo: Todo

    var toggleComplete: (UUID) -> Void

    var body: some View {
        HStack {
            Text(todo.task)
            Spacer()
            Button {
                self.toggleComplete(self.todo.id)
            } label: {
                Image(systemName: todo.isComplete ? "checkmark.square" : "square")
            }
        }
    }
}

struct TodoTextField: View {
    var addTodo: (String) -> Void
    @State private var newTask = ""

    var body: some View {
        HStack {
            TextField("New task", text: $newTask)
            Button {
                self.addTodo(self.newTask)
                self.newTask = ""
            } label: {
                Image(systemName: "plus")
            }
        }
        .padding()
    }
}

In this version, the Todo class conforms to the Identifiable protocol and includes an id field. The TodoListView struct displays the list of todos and a text field for adding new tasks. It has a TodoListViewModel as an observed object, which provides the data and logic for the view.

The TodoListView uses List and ForEach views to display each task. Each task is represented by a TodoRow struct that is being reused for each to-do in the list.

The TodoTextField struct contains the text.

3. Structuring an Architecture if needed

Now, based on our understanding, we can separate all the views in different files according to our project architecture needs.

But if we need to test ChatGPT for that then we can also do that by asking,

I want to make this app with MVVM architecture, can you arrange views and class according to that?

If you are not satisfied with the answer even if your question is proper then you can also Regenerate Response.

4. Solve the problems

If you have used this code and tried to run it, then you may have noticed that the to-do item cell is not able to toggle the value of isCompleted.

Now let’s try to solve that problem with the help of ChatGPT by asking,

From the given code I’m not able to update the state of `isCompleted` flag, can you help me out to find out the cause of this issue?

And maybe its answer will not help us to fix this issue even if tried with the Regenerate Response option so many times, because ChatGPT can not be correct all the time.

We can not expect to get 100% correct answers from the ChatGPT prompt, after all, it’s an AI not human in this case our knowledge will help.

Here the problem is we have added the TODO data class as Class not Struct. The model class should be added as a struct in any case.

Let’s fix it and try to run.

5. Add Unit Test

Now if we want to write a unit test for the ViewModel class then also we can do that easily.

Can you write unit test for it’s viewmodel class?

Sure! Here’s an example of how you might write unit tests for the TodoListViewModel class using the XCTest framework:

import XCTest
@testable import TodoApp

class TodoListViewModelTests: XCTestCase {
    var viewModel: TodoListViewModel!

    override func setUp() {
        viewModel = TodoListViewModel()
    }

    override func tearDown() {
        viewModel = nil
    }

    func testAddTodo() {

        viewModel.addTodo(task: "Test Todo")
        XCTAssertEqual(viewModel.todos.count, 1)
        XCTAssertEqual(viewModel.todos.first?.task, "Test Todo")
        XCTAssertEqual(viewModel.todos.first?.isComplete, false)
    }

    func testDeleteTodo() {
        viewModel.todos = [Todo(task: "Test Todo 1"), Todo(task: "Test Todo 2")]
        viewModel.deleteTodo(at: IndexSet(integer: 0))
        XCTAssertEqual(viewModel.todos.count, 1)
        XCTAssertEqual(viewModel.todos.first?.task, "Test Todo 2")
    }

    func testToggleC                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  omplete() {
        viewModel.todos = [Todo(task: "Test Todo")]
        viewModel.toggleComplete(id: viewModel.todos.first!.id)
        XCTAssertEqual(viewModel.todos.first?.isComplete, true)
        viewModel.toggleComplete(id: viewModel.todos.first!.id)
        XCTAssertEqual(viewModel.todos.first?.isComplete, false)
    }
}

Now if you have doubts about any written test then you can confirm or ask for write correct one, like

I don’t think that the deleteTODO function test is correct, can you please write its correct test?

I apologize for any confusion. The test testDeleteTodo() provided previously was checking the count of elements after removing one element and checking its value.

But the better way to test the deleteTodo(at:) method is to check if the element you want to delete is really removed from the to-do list, using XCTAssertEqual or other assertion methods. Here's an example of how you could test the deleteTodo(at:) function:

func testDeleteTodo() {
    let task1 = Todo(task: "Test Todo 1")
    let task2 = Todo(task: "Test Todo 2")
    viewModel.todos = [task1, task2]
    let id = task1.id
    viewModel.deleteTodo(at: IndexSet(integer: 0))
    XCTAssertEqual(viewModel.todos.count, 1)
    XCTAssertNil(viewModel.todos.first(where: { $0.id == id }))
}

It first creates two Todo objects, then adds these objects to the todos array, deletes the first element, and then tests if it’s removed by checking its id is not available in the todo array.

Please let me know if you have any further questions or if there is anything else that I can help you with.

6. Use of Mocking Dependency Library

Now, if we are mocking our project dependency using a third-party library and want to write a test using the same, then let’s see how we can do that.

Let’s ask,

Can you mock its dependency using cuckoo and then write a test with that library?

But if you ask like this it will consider the previous question and answer accordingly, like it’ll write a test only for the deleteTodo method, you can try but for now, I'll ask,

Can you mock the project’s dependency using cuckoo and then write a unit test with that library for the ViewModel?

Sure, here’s an example of how you could write unit tests for the TodoListViewModel class using Cuckoo :

import XCTest
import Cuckoo

class TodoListViewModelTests: XCTestCase {
    var viewModel: TodoListViewModel!
    var mockViewModel: MockTodoListViewModel!
    
    override func setUp() {
        mockViewModel = MockTodoListViewModel()
        viewModel = mockViewModel
    }

    func testAddTodo() {
        let task = "Test Todo"
        mockViewModel.stub(mockViewModel.addTodo(task: task))
        viewModel.addTodo(task: task)
        mockViewModel.verify(mockViewModel.addTodo(task: task), times(1))
    }

    func testDeleteTodo() {
        let indexSet = IndexSet(integer: 0)
        mockViewModel.stub(mockViewModel.deleteTodo(at: indexSet))
        viewModel.deleteTodo(at: indexSet)
        mockViewModel.verify(mockViewModel.deleteTodo(at: indexSet), times(1))
    }

    func testToggleComplete() {
        let id = UUID()
        mockViewModel.stub(mockViewModel.toggleComplete(id: id))
        viewModel.toggleComplete(id: id)
        mockViewModel.verify(mockViewModel.toggleComplete(id: id), times(1))
    }
}

Here in each test method, first, you’re stubbing the corresponding method of mockViewModel and then calling the actual method on viewModel object and finally you're verifying that the corresponding method on mockViewModel has been called the expected number of times (1 in this case).

By using this library, you can write the test of ViewModel without its dependency, and also it will increase the speed of your test. If you have any questions or run into any issues, please let me know.

7. Add a Second Screen with a Navigation

It’s enough if we want to create a single-screen app but what if we want to add a navigation view and add more than 1 screen?

Let’s explore that with GPT,

Make sure to ask questions with enough detail so that ChatGPT can give a proper answer.

Can you design the to-do task detail screen that has all the detail related to the task and that can be opened with the click of the task cell from the home screen?

Sure! Here’s an example of how you could design a TodoTaskDetailView that displays all the details of a Todo task and can be opened with the click of a task cell on the home screen:

struct TodoTaskDetailView: View {
    @ObservedObject var todo: Todo

    var body: some View {
        VStack {
            Text(todo.task)
            Spacer()
            HStack {
                if todo.isComplete {
                    Text("Completed")
                        .foregroundColor(.green)
                } else {
                    Text("Incomplete")
                        .foregroundColor(.red)
                }
                Spacer()
            }
        }
        .padding()
        .navigationBarTitle("Task Detail")
    }
}

You can open this TodoTaskDetailView by implementing NavigationLink inside the ForEach loop of the home screen's List view. The NavigationLink will be used to navigate to this detail screen and will pass the selected Todo object through the todo property.

struct TodoListView: View {
    @ObservedObject var viewModel: TodoListViewModel = .init()

    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.todos) { todo in
                    NavigationLink(destination: TodoTaskDetailView(todo: todo)) {
                        TodoRow(todo: .constant(todo), toggleComplete: self.viewModel.toggleComplete)
                    }
                }
                .onDelete { indexSet in
                    self.viewModel.deleteTodo(at: indexSet)
                }
            }
            .navigationBarTitle("Todo")
            .navigationBarItems(trailing: EditButton())
        }
    }
}

You can also use Button or onTapGesture instead of NavigationLink if you want to present the detail view modally instead of pushing it onto a navigation stack. Please let me know if you have any questions or if you need further assistance.


That’s it for now as a start-up app. You can explore ChatGPT by questioning in multiple ways.

It’s just about how to ask someone to get proper information or an answer same as the PQA (Precision Questions & Answers).

Hope it’ll help you get basic insights and the usage of ChatGPT.

Have fun with ChatGPT!!!

Keep Chatting… ⌨️🤖

Conclusion

Revolutionizing the way we interact with machines, bringing us one step closer to creating truly intelligent, human-like AI

Sometimes it’s possible with ChatGPT that it may give different answers if we ask for the same question many times, So you can try that too by trying with the same or different questions until you get your expected output.

ChatGPT is a powerful and versatile tool that can be used for a wide range of applications.

Don’t be afraid to experiment and have fun with it — you never know what exciting and creative ideas you might come up with!


Code, Build, Repeat.
Stay updated with the latest trends and tutorials in Android, iOS, and web development.
amisha-i image
Amisha Italiya
iOS developer @canopas | Sharing knowledge of iOS development
amisha-i image
Amisha Italiya
iOS developer @canopas | Sharing knowledge of iOS development
canopas-logo
We build products that customers can't help but love!
Get in touch
background-image

Get started today

Let's build the next
big thing!

Let's improve your business's digital strategy and implement robust mobile apps to achieve your business objectives. Schedule Your Free Consultation Now.

Get Free Consultation
footer
Follow us on
2024 Canopas Software LLP. All rights reserved.