Технологии

Vibe coding на SwiftUI + Qwen. Как c помощью ИИ сделать простое TODO-приложение на SwiftUI

Искусственный интеллект на сегодняшний день играет важную и быстро растущую роль в разработке программного обеспечения. Его использование охватывает множество аспектов, от автоматизации задач до помощи в принятии решений. 1. Генерация кода AI-ассистенты по написанию кода , такие как GitHub Copilot, Amazon CodeWhisperer, Tabnine и др., помогают разработчикам: Автоматически генерировать функции. Заполнять шаблоны. Предлагать варианты завершения кода. Обучены 2. Тестирование и отладка ИИ используется для: Генерации тестовых сценариев. Поиска багов и уязвимостей в коде. Автоматического исправления ошибок. Инструменты вроде DeepCode, Snyk, CodiumAI 3. Автоматизация документирования Системы ИИ могут: Автоматически создавать документацию к коду. Писать комментарии. Генерировать описание API и примеры использования. 4. Анализ требований и планирование проектов ИИ помогает при: Переводе пользовательских требований в технические спецификации. Оценке трудозатрат. Управлении задачами и приоритетами (например, в Jira + AI). 5. UI/UX дизайн и прототипирование Инструменты на основе ИИ позволяют: Преобразовывать текстовые описания в макеты интерфейсов. Генерировать дизайны. Создавать прототипы приложений без участия человека. 6. DevOps и автоматизация CI/CD ИИ применяется в: Анализе логов и предсказании сбоев. Автоматической оптимизации процессов деплоя. Мониторинге производительности и рекомендациях по улучшению. 7. Безопасность и обнаружение угроз ИИ помогает: Обнаруживать подозрительное поведение в системе. Выявлять уязвимости в коде. Реагировать на атаки в реальном времени. 8. Low-code / No-code платформы с ИИ Современные low-code платформы (например, Microsoft Power Apps, Bubble, Retool) всё чаще используют ИИ для: Генерации логики приложений по описанию. Упрощения создания MVP без глубоких технических знаний. 9. Персонализация и адаптивность продуктов ИИ используется в финальных продуктах, особенно в: Рекомендательных системах. Адаптации интерфейса под пользователя. Чат-ботах и голосовых помощниках. По некоторым прогнозам К 2030 году ожидается, ИИ будет использоваться почти во всех этапах разработки ПО. Возможно появление полностью автономных агентов , способных самостоятельно создавать приложения по текстовому описанию. Однако, человеческий контроль и экспертиза останутся важными для проверки качества, безопасности и соответствия требованиям. Я решил проверить на сколько уже сейчас с помощью ИИ возможно написать простое приложение по текстовому описанию имея лишь минимальные знания программирования. Для проекта я выбрал SwiftUI так как это современный декларативный фреймворк Apple для создания пользовательских интерфейсов. Он позволяет писать меньше кода и быстрее создавать приложения. В качестве ИИ ассистента я выбрал Qwen так как он имеет бесплатную версию и доступен через вэб-интерфейс. Я создал проект в Xcode, открыл https://chat.qwen.ai и написал первый промпт: «Ты опытный iOS разработчик. Напиши простейшее TODO-List приложение на SwiftUI» Немного подумав ИИ выдал следующий код: import SwiftUI struct ContentView: View { @State private var todos: [Todo] = [] @State private var newTodoText: String = "" var body: some View { NavigationView { VStack { HStack { TextField("New task", text: $newTodoText) .textFieldStyle(RoundedBorderTextFieldStyle()) Button(action: addTodo) { Image(systemName: "plus") .foregroundColor(.blue) } } .padding() List { ForEach($todos) { $todo in HStack { Button { todo.completed.toggle() } label: { Image(systemName: todo.completed ? "checkmark.circle.fill" : "circle") .foregroundColor(todo.completed ? .green : .gray) } Text(todo.title) .strikethrough(todo.completed, color: .gray) .foregroundColor(todo.completed ? .gray : .primary) } } .onDelete(perform: deleteTodos) } } .navigationTitle("TODO List") } } func addTodo() { guard !newTodoText.trimmingCharacters(in: .whitespaces).isEmpty else { return } todos.append(Todo(title: newTodoText)) newTodoText = "" } func deleteTodos(at offsets: IndexSet) { todos.remove(atOffsets: offsets) } } // MARK: - Models struct Todo: Identifiable { let id = UUID() var title: String var completed: Bool = false } // MARK: - Preview struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } Должен отметить, что скопировав код и вставив его в Xcode я получил готовое рабочее приложение. Править и дописывать ничего не пришлось. Результат представлял собой одноэкранное приложение со строкой ввода и кнопкой +, чтобы добавлять дела в свой список и ниже сам список с названием пункта и чекбоксом. При нажатии пункт отмечался как выполненный. Текст зачеркивался, а чек-бокс становился зеленым. Я решил немного расширить приложение и добавить для каждого пункта из списка дел экран деталей. Мой второй промпт был таким: «Сделай так чтобы при нажатии на айтем в списке происходил переход на экран деталей» ИИ сгенерировал новый год, добавив возможность перехода на экран деталей. import SwiftUI struct ContentView: View { @State private var todos: [Todo] = [] @State private var newTodoText: String = "" var body: some View { NavigationView { VStack { HStack { TextField("New task", text: $newTodoText) .textFieldStyle(RoundedBorderTextFieldStyle()) Button(action: addTodo) { Image(systemName: "plus") .foregroundColor(.blue) } } .padding() List { ForEach($todos) { $todo in NavigationLink(destination: DetailView(todo: $todo)) { HStack { Button { todo.completed.toggle() } label: { Image(systemName: todo.completed ? "checkmark.circle.fill" : "circle") .foregroundColor(todo.completed ? .green : .gray) } Text(todo.title) .strikethrough(todo.completed, color: .gray) .foregroundColor(todo.completed ? .gray : .primary) } } } .onDelete(perform: deleteTodos) } } .navigationTitle("TODO List") } } func addTodo() { guard !newTodoText.trimmingCharacters(in: .whitespaces).isEmpty else { return } todos.append(Todo(title: newTodoText)) newTodoText = "" } func deleteTodos(at offsets: IndexSet) { todos.remove(atOffsets: offsets) } } // MARK: - Detail View struct DetailView: View { @Binding var todo: Todo var body: some View { Form { TextField("Task", text: $todo.title) Toggle("Completed", isOn: $todo.completed) } .navigationTitle("Edit Task") } } // MARK: - Models struct Todo: Identifiable { let id = UUID() var title: String var completed: Bool = false } // MARK: - Preview struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } У Qwen есть довольно полезная опция. Он описывает, какие изменения он внес в код. 🧠 Что изменилось?NavigationLink добавлен для каждой строки списка: Открывает DetailView , передавая$todo по ссылке (через@Binding ). DetailView : Позволяет редактировать заголовок задачи. Переключать статус выполнения. Редактирование происходит "на лету" , так как используется @Binding . В итоге получился ожидаемый результат. Главный экран остался без изменений. Экран деталей на котором мы можем изменить название айтема и отметить отметить его как выполненный или наоборот с помощью свитчера. Отметим пункт как завершенный Главный экран с завершенной задачей Изменим название Результат Все работает. Теперь чекбокс перед названием айтема кажется лишним так как мы его не используем.Попробуем избавиться от него. Так как цель написать приложение на 100% с помощью ии, то и все правки поручим ИИ. Мой промпт для удаления чекбокса был следующим: «Убери круг перед названием пункта и если пункт выполнен то изменяй цвет его текста на зеленый» Немного подумав Qwen отчитался о проделанной работе: И выдал измененный код import SwiftUI struct ContentView: View { @State private var todos: [Todo] = [] @State private var newTodoText: String = "" var body: some View { NavigationView { VStack { HStack { TextField("New task", text: $newTodoText) .textFieldStyle(RoundedBorderTextFieldStyle()) Button(action: addTodo) { Image(systemName: "plus") .foregroundColor(.blue) } } .padding() List { ForEach($todos) { $todo in NavigationLink(destination: DetailView(todo: $todo)) { Text(todo.title) .foregroundColor(todo.completed ? .green : .primary) .strikethrough(todo.completed, color: todo.completed ? .green : nil) } } .onDelete(perform: deleteTodos) } } .navigationTitle("TODO List") } } func addTodo() { guard !newTodoText.trimmingCharacters(in: .whitespaces).isEmpty else { return } todos.append(Todo(title: newTodoText)) newTodoText = "" } func deleteTodos(at offsets: IndexSet) { todos.remove(atOffsets: offsets) } } // MARK: - Detail View struct DetailView: View { @Binding var todo: Todo var body: some View { Form { TextField("Task", text: $todo.title) Toggle("Completed", isOn: $todo.completed) } .navigationTitle("Edit Task") } } // MARK: - Model struct Todo: Identifiable { let id = UUID() var title: String var completed: Bool = false } // MARK: - Preview struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } Как обычно подсветил что было сделано На этот раз снова получился тот результат, который и ожидался. Пункт списка дел без чекбокса спереди. При переводе пункта в разряд выполненных Текст меняется на зеленый и зачеркивается «Продолжим развивать приложение» решил я и задал следующий промпт: «Сделай бэкграунд основного экрана оранжевым» На этот раз ИИ не стал регенерить код полностью, а выдал краткий ответ: На первый взгляд получили как раз то, что хотели Но если добавить дело в список, то получим не совсем тот результат, который ожидался. Моим принципиальным решением было не исправлять код самому, а проверить то на сколько сам ИИ сможет написать приложение по текстовому описанию. После нескольких запросов на исправление текущего кода и получение желаемого результата, при котором фон списка так же должен быть всегда оранжевым стабильно работающего решения получить от ИИ не удалось. Тут сыграл момент с галлюцинациями ИИ, когда ИИ дает уверенный ответ, но на практике он оказывается не верным. Отложив вопрос с фоном списка дел, решил дополнить приложение еще одной небольшой фичей. Мой промпт выглядел следующим образом: «Дополни код так чтобы если выполненных пунктов больше чем не выполненных фон экрана становился светло-зеленым» ИИ уже знакомо отозвался: И выдал код: import SwiftUI struct ContentView: View { @State private var todos: [Todo] = [] @State private var newTodoText: String = "" // 🟢 Вычисляемое свойство для определения цвета фона var backgroundColor: Color { let completedCount = todos.filter { $0.completed }.count let uncompletedCount = todos.count - completedCount return completedCount > uncompletedCount ? Color.green.opacity(0.3) : Color.orange.opacity(0.3) } var body: some View { NavigationView { VStack { HStack { TextField("New task", text: $newTodoText) .textFieldStyle(RoundedBorderTextFieldStyle()) Button(action: addTodo) { Image(systemName: "plus") .foregroundColor(.blue) } } .padding() List { ForEach($todos) { $todo in NavigationLink(destination: DetailView(todo: $todo)) { Text(todo.title) .foregroundColor(todo.completed ? .green : .primary) .strikethrough(todo.completed, color: todo.completed ? .green : nil) } } .onDelete(perform: deleteTodos) } .listStyle(PlainListStyle()) // Убираем стандартный стиль списка .background(Color.clear) // Делаем фон списка прозрачным, чтобы он не мешал основному фону } .background( ZStack { backgroundColor .ignoresSafeArea() } ) .navigationTitle("TODO List") } } func addTodo() { guard !newTodoText.trimmingCharacters(in: .whitespaces).isEmpty else { return } todos.append(Todo(title: newTodoText)) newTodoText = "" } func deleteTodos(at offsets: IndexSet) { todos.remove(atOffsets: offsets) } } // MARK: - Detail View struct DetailView: View { @Binding var todo: Todo var body: some View { Form { TextField("Task", text: $todo.title) Toggle("Completed", isOn: $todo.completed) } .navigationTitle("Edit Task") } } // MARK: - Model struct Todo: Identifiable { let id = UUID() var title: String var completed: Bool = false } // MARK: - Preview struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } Отметим два пункта из трех как выполненные и получаем зеленый бэкграунд Удалим один выполненный пункт Цвет фона вновь станет оранжевым, так как выполненных пунктов не больше чем не выполненных. Все соответствует запросу. Какие выводы можно сделать исходя из данного эксперемента и практически ежедневного применения ИИ в работе? Использование искусственного интеллекта в программировании уже сегодня позволяет значительно ускорить и упростить процесс разработки. ИИ отлично справляется с рутинными и стандартными задачами — от генерации простого кода до автоматического написания тестов и документации. Однако при работе над более сложными и нетиповыми задачами , результаты, предоставляемые ИИ, зачастую требуют внимательного контроля, доработки и проверки со стороны опытных разработчиков . Одной из ключевых проблем остаются галлюцинации ИИ — ситуация, когда система уверенно предлагает логически выглядящие, но фактически неверные или неработающие решения. Это делает невозможным полное доверие к выводам модели без участия человека. Таким образом, на данном этапе развития технологии ИИ является мощным вспомогательным инструментом , а не самостоятельным разработчиком. Его эффективность напрямую зависит от квалификации специалиста, способного оценить качество сгенерированного кода и вовремя исправить возможные ошибки.

Фильтры и сортировка