TGViewer
Мобильный трудоголик Мобильный трудоголик @hardworkerit · 1.65K subscribers
Post #375 1.07K
🔢 Drag & Drop в SwiftUI: создаем перетаскиваемые элементы.

В современных приложениях пользователь привык к интерактивности: перетащил фотографию в альбом, переместил задачу между колонками, кинул файл в папку. В SwiftUI эта магия реализуется через пару модификаторов - onDrag и onDrop. Но за ними скрывается больше, чем кажется.


Что происходит на самом деле:

Когда вы начинаете тащить элемент, SwiftUI не перемещает визуальную копию по экрану. Он упаковывает данные в специальный контейнер NSItemProvider, описывает их тип через UTType (например `public.json`) и только тогда система понимает, что происходит.

По сути, это конвейер: объект -> JSON -> NSItemProvider -> передача -> JSON -> объект. Пока вы тащите палец по экрану, данные еще не переехали. Они начнут передаваться только в момент, когда вы отпустите палец.


Как сделать элемент перетаскиваемым:

Создадим простую модель задачи, которую будем перетаскивать:


struct TaskItem: Identifiable, Codable {
let id = UUID()
let title: String
let priority: Int
}


Теперь сделаем сам элемент перетаскиваемым. Ключевой момент - зарегистрировать данные в NSItemProvider и указать, что мы передаем JSON:


struct DraggableTaskView: View {
let task: TaskItem

var body: some View {
HStack {
Text(task.title)
Text("\(task.priority)")
.font(.caption)
}
.padding(12)
.background(Color.blue.opacity(0.2))
.cornerRadius(8)
.onDrag {
// 1. Кодируем задачу в JSON
guard let data = try? JSONEncoder().encode(task) else {
return NSItemProvider()
}

// 2. Создаем провайдер и регистрируем данные
let provider = NSItemProvider()
provider.registerDataRepresentation(
forTypeIdentifier: UTType.json.identifier,
visibility: .all
) { completion in
completion(data, nil)
return nil
}
return provider
}
}
}



Как подготовить зону для приема:

Создадим колонку, куда можно бросать задачи. Здесь важны две вещи: визуальный отклик при наведении (чтобы пользователь понимал, что бросать можно) и асинхронная распаковка данных:


struct TaskColumn: View {
@Binding var tasks: [TaskItem]
@State private var isDropTargeted = false

var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Активные задачи")
.font(.headline)

ForEach(tasks) { task in
DraggableTaskView(task: task)
}

if tasks.isEmpty {
Text("Перетащите задачи сюда")
.foregroundColor(.gray)
.padding()
}
}
.padding()
.frame(minWidth: 250, minHeight: 300)
.background(
RoundedRectangle(cornerRadius: 16)
.fill(isDropTargeted ? Color.green.opacity(0.15) : Color.gray.opacity(0.1))
.overlay(
RoundedRectangle(cornerRadius: 16)
.stroke(isDropTargeted ? Color.green : Color.gray, lineWidth: isDropTargeted ? 2 : 1)
)
)
.onDrop(of: [.json], isTargeted: $isDropTargeted) { providers, location in
guard let provider = providers.first else { return false }

provider.loadDataRepresentation(forTypeIdentifier: UTType.json.identifier) { data, error in
guard let data = data,
let newTask = try? JSONDecoder().decode(TaskItem.self, from: data) else {
return
}

DispatchQueue.main.async {
tasks.append(newTask)
}
}
return true
}
}
}



🔗 Читать подробнее


💡 Вывод:

Drag & Drop в SwiftUI - это не магия, а четкий контракт: источник упаковывает данные, приемник распаковывает. NSItemProvider берет на себя передачу даже между разными приложениями, а UTType помогает системе не путать, что именно перемещается. Пользователь видит плавное перемещение, а разработчик - чистую архитектуру, где перемещаются данные, а не вьюхи.


➡️ Подписаться на канал
Мобильный трудоголик
  • 👍 9
  • ❤ 4
  • 🔥 3
  • 🙏 1
More from @hardworkerit
  1. Oct 1, 2026🔢 Работа с Picture-in-Picture в iOS. Picture-in-Picture - системная функция iOS, которая…
  2. Sep 29, 2026🔢 Управление тулбарами на iPhone Duo. На iPhone Duo элементы управления навигацией, дейст…
  3. Sep 27, 2026🔢 Новые возможности Hashable в Swift 6.4 В Swift 6.4 добавили Hashable для нескольких тип…
  4. Sep 25, 2026🔢 Приватные свойства больше не ломают memberwise инициализатор в Swift 6.4 Swift автомати…
  5. Sep 24, 2026👨‍💻 Почему разработчики ненавидят своих менеджеров. Всем привет! Сегодня хочу разобрать…
  6. Sep 22, 2026🔢 Релиз Swift 6.4: главные изменения для разработчиков. Swift 6.4 вышел. Это обновление п…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →