Providable
让自定义类型的拖放操作更轻松。UserActivityProvidable
让拖动创建新窗口的操作更轻松。Example
文件夹中有一个应用程序,演示了此软件包的功能以及如何设置自定义类型的拖放。
File -> Add Packages
https://github.com/ryanlintott/ILikeToMoveIt
并按版本选择。import ILikeToMoveIt
导入软件包此软件包与 iOS 14+ 兼容,但辅助功能移动功能仅适用于 iOS 15+。
如果您喜欢这个软件包,请买杯咖啡感谢我!
或者您可以购买一件带有 iLikeToMoveIt 标志的 T 恤
*iOS 15+
需要两个修饰符来启用辅助功能移动操作。每个项目一个,列表本身一个。
List {
ForEach(items) { item in
Text(item.name)
.accessibilityMoveable(item)
}
}
.accessibilityMoveableList($items, label: \.name)
添加此修饰符将添加辅助功能操作,以将项目向上、向下、移动到列表顶部和底部。如果您想自定义这些操作,您可以提供自己的数组。
示例:如果您的列表很短,只想向上和向下移动。
.accessibilityMoveable(item, actions: [.up, .down])
示例:如果您的列表很长,并且希望一次移动多个步骤的选项。
.accessibilityMoveable(item, actions: [.up, .down, .up(5), .down(5), .toTop, .toBottom])
当用户触发辅助功能操作时,以下结果将通过 UIAccessibility 公告报告返回
此修饰符将移动操作的更改应用于列表,并调整辅助功能焦点以确保其停留在正确的项目上。
您传入项目数组的绑定和一个可选的标签键路径。此标签将在移动项目后读出,以使用户知道向上移动后直接下方的项目或向下移动后直接上方的项目是什么。
.accessibilityMoveableList($items, label: \.name)
此协议允许在 iOS 14 和 15 中更轻松地拖放 Codable
对象
在 iOS 16 中,Transferable
协议使拖放操作变得更加容易。旧方法使用 NSItemProvider
且设置繁琐。
使您的对象符合 Providable
。添加可读和可写类型,然后添加函数以在这些类型之间转换您的对象。
extension Bird: Providable {
static let writableTypes: [UTType] = [.bird]
static let readableTypes: [UTType] = [.bird, .plainText]
func data(type: UTType) async throws-> Data? {
switch type {
case .bird:
return try JSONEncoder().encode(self)
default:
return nil
}
}
init?(type: UTType, data: Data) throws {
switch type {
case .bird:
self = try JSONDecoder().decode(Bird.self, from: data)
case .plainText:
let string = String(decoding: data, as: UTF8.self)
self = Bird(name: string)
default:
return nil
}
}
}
您需要将任何自定义类型添加到您的项目。项目 > 目标 > Info > ExportedTypeIdentifiers
像这样向视图添加拖动选项
.onDrag { bird.provider }
像这样添加放置选项
.onDrop(of: Bird.readableTypes) { providers, location in
providers.loadItems(Bird.self) { bird, error in
if let bird {
birds.append(bird)
}
}
return true
}
甚至像这样添加插入选项
.onInsert(of: Bird.readableTypes) { index, providers in
providers.loadItems(Bird.self) { bird, error in
if let bird {
birds.insert(bird, at: index)
}
}
}
Providable
协议的扩展,用于在 iPadOS 16+ 上轻松拖动到新窗口(Transferable
不支持的功能)
将您的活动类型字符串添加到 plist 中的 NSUserActivityTypes
下,然后将相同的字符串添加到您的可编码类型上的 activityType 参数。
extension Bird: UserActivityProvidable {
static let activityType = "com.ryanlintott.draganddrop.birdDetail"
}
使用接受 UserActivityProvidable
对象的 onContinueUserActivity
重载函数来处理您的应用程序通过此活动打开时的操作。
.onContinueUserActivity(Bird.self) { bird in
/// Adjust state based on your object.
}
您还可以为您的对象定位单独的 WindowGroup。确保您仍然在视图中使用 onContinueUserActivity
以确保对象被加载。
WindowGroup {
BirdDetailView()
}
.handlesExternalEvents(matching: [Bird.activityType])
Codable
对象开始。struct Bird: Codable {
let name: String
}
项目 > 目标 > Info > Exported Type Identifiers
import UniformTypeIdentifiers
extension UTType {
static let bird = UTType("com.ryanlintott.draganddrop.bird") ?? .data
}
Providable
。Transferable
transferRepresetation
属性,并为您的自定义类型包含 CodableRepresentation
,以及为任何其他兼容类型包含 DataRepresentation
。static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .bird)
DataRepresentation(importedContentType: .plainText) { data in
let string = String(decoding: data, as: UTF8.self)
return Bird(name: string)
}
}
一旦您的类型符合 Transferable
,添加 SwiftUI 拖放修饰符就很容易了!
通过添加此修饰符使任何视图可拖动
.draggable(bird)
任何视图都可以是放置目标。使用 action 添加放置的项目,如果需要,可以使用 location 进行动画,并使用 isTargeted 闭包在可放置内容悬停时为视图添加动画。
.dropDestination(for: Bird.self) { droppedBirds, location in
birds.append(contentsOf: droppedBirds)
return true
} isTargeted: {
isTargetted = $0
}
添加到 ForEach 时,放置的项目可以插入到其他项目之间。
.dropDestination(for: Bird.self) { droppedBirds, offset in
birds.insert(contentsOf: droppedBirds, at: offset)
}