如何使用SwiftUI框架实现删除和移动功能
How to implement delete and move function using SwiftUI framework
无法删除和移动列表视图中项目的行。
Apple 在他们的培训视频中提供了这些方法,但它不起作用
删除:
array.remove(atOffsets: IndexSet)
搬家:
array.move(fromOffsets: IndexSet, toOffset: Int)
苹果文档中没有这两种方法。
您提到的方法现在可以在 Xcode 11 GM 上使用。你可以像这样使用它们。
删除元素
TLDR:
.onDelete{offsets in
self.array.remove(atOffsets: offsets)
完整代码(可复制粘贴):
导入 SwiftUI
struct MyTableView : View {
@State var array=[1,2,3,4,5]
var body: some View {
List{
ForEach(array,id:\.self){element in
Text("\(element)")
}
.onDelete{offsets in
self.array.remove(atOffsets: offsets)
}
}
}
}
struct MyTableView_Previews : PreviewProvider {
static var previews: some View {
MyTableView()
}
}
移动元素
.onMove { (offsets, targetOffset) in
self.array.move(fromOffsets: offsets, toOffset: targetOffset)
}
他们要么使用数组的自定义扩展,要么使用 public 尚不可用的 Swift 的某些版本。我实施的解决方法是:
删除
func delete(at offsets: IndexSet) {
if let first = offsets.first {
store.rooms.remove(at: first)
}
}
移动
func move(from source: IndexSet, to destination: Int) {
if let first = source.first {
store.rooms.swapAt(first, destination)
}
}
移动功能可以,但是动画不如 WWDC 2019 上的视频好。
这些方法是 Swift 5.1 标准库的一部分,Apple 将在未来的 Xcode 测试版中提供这些方法。同时,您可以使用这些扩展:
extension Array {
mutating func remove(atOffsets offsets: IndexSet) {
let suffixStart = halfStablePartition { index, _ in
return offsets.contains(index)
}
removeSubrange(suffixStart...)
}
mutating func move(fromOffsets source: IndexSet, toOffset destination: Int) {
let suffixStart = halfStablePartition { index, _ in
return source.contains(index)
}
let suffix = self[suffixStart...]
removeSubrange(suffixStart...)
insert(contentsOf: suffix, at: destination)
}
mutating func halfStablePartition(isSuffixElement predicate: (Index, Element) -> Bool) -> Index {
guard var i = firstIndex(where: predicate) else {
return endIndex
}
var j = index(after: i)
while j != endIndex {
if !predicate(j, self[j]) {
swapAt(i, j)
formIndex(after: &i)
}
formIndex(after: &j)
}
return i
}
func firstIndex(where predicate: (Index, Element) -> Bool) -> Index? {
for (index, element) in self.enumerated() {
if predicate(index, element) {
return index
}
}
return nil
}
}
无法删除和移动列表视图中项目的行。
Apple 在他们的培训视频中提供了这些方法,但它不起作用
删除:
array.remove(atOffsets: IndexSet)
搬家:
array.move(fromOffsets: IndexSet, toOffset: Int)
苹果文档中没有这两种方法。
您提到的方法现在可以在 Xcode 11 GM 上使用。你可以像这样使用它们。
删除元素
TLDR:
.onDelete{offsets in
self.array.remove(atOffsets: offsets)
完整代码(可复制粘贴): 导入 SwiftUI
struct MyTableView : View {
@State var array=[1,2,3,4,5]
var body: some View {
List{
ForEach(array,id:\.self){element in
Text("\(element)")
}
.onDelete{offsets in
self.array.remove(atOffsets: offsets)
}
}
}
}
struct MyTableView_Previews : PreviewProvider {
static var previews: some View {
MyTableView()
}
}
移动元素
.onMove { (offsets, targetOffset) in
self.array.move(fromOffsets: offsets, toOffset: targetOffset)
}
他们要么使用数组的自定义扩展,要么使用 public 尚不可用的 Swift 的某些版本。我实施的解决方法是:
删除
func delete(at offsets: IndexSet) {
if let first = offsets.first {
store.rooms.remove(at: first)
}
}
移动
func move(from source: IndexSet, to destination: Int) {
if let first = source.first {
store.rooms.swapAt(first, destination)
}
}
移动功能可以,但是动画不如 WWDC 2019 上的视频好。
这些方法是 Swift 5.1 标准库的一部分,Apple 将在未来的 Xcode 测试版中提供这些方法。同时,您可以使用这些扩展:
extension Array {
mutating func remove(atOffsets offsets: IndexSet) {
let suffixStart = halfStablePartition { index, _ in
return offsets.contains(index)
}
removeSubrange(suffixStart...)
}
mutating func move(fromOffsets source: IndexSet, toOffset destination: Int) {
let suffixStart = halfStablePartition { index, _ in
return source.contains(index)
}
let suffix = self[suffixStart...]
removeSubrange(suffixStart...)
insert(contentsOf: suffix, at: destination)
}
mutating func halfStablePartition(isSuffixElement predicate: (Index, Element) -> Bool) -> Index {
guard var i = firstIndex(where: predicate) else {
return endIndex
}
var j = index(after: i)
while j != endIndex {
if !predicate(j, self[j]) {
swapAt(i, j)
formIndex(after: &i)
}
formIndex(after: &j)
}
return i
}
func firstIndex(where predicate: (Index, Element) -> Bool) -> Index? {
for (index, element) in self.enumerated() {
if predicate(index, element) {
return index
}
}
return nil
}
}