Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
362 views
in Technique[技术] by (71.8m points)

swiftui - How to add/remove views from a paged ScrollView (TabView)

I am trying to create a paged scrollview I have used a TabView to create this.

here is my code

struct TT: Identifiable {
    let id = UUID()
    var v: String
}

struct TTest: View {
    @State var currentIndex = 0
    @State var data = [
        TT(v: "0")
    ]
    var body: some View {
        VStack {
            SwiftUI.TabView(selection: $currentIndex) {
                ForEach(data.indexed(), id: .1.id) { index, value in
                    TTestConsomer(data: $data[index]).tag(index)
                }
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            Spacer()
            HStack {
                Image(systemName: "plus")
                    .resizable()
                    .frame(width: 50, height: 50)
                    .onTapGesture(perform: add)
                Image(systemName: "minus")
                    .resizable()
                    .frame(width: 50, height: 5)
                    .onTapGesture(perform: delete)
            }
            Text("(currentIndex + 1)/(data.count)")
        }
        
    }
    
    func add() {
        data.append(TT(v: "(data.count)") )
    }
    
    func delete() {
        data.remove(at: currentIndex)
    }
}

struct TTestConsomer: View {
    @Binding var data: TT
    var body: some View {
        Text(data.v)
            .padding(30)
            .border(Color.black)
    }
}

// You also need this extension
extension RandomAccessCollection {
    func indexed() -> IndexedCollection<Self> {
        IndexedCollection(base: self)
    }
}

struct IndexedCollection<Base: RandomAccessCollection>: RandomAccessCollection {
    typealias Index = Base.Index
    typealias Element = (index: Index, element: Base.Element)

    let base: Base

    var startIndex: Index { base.startIndex }

    var endIndex: Index { base.endIndex }

    func index(after i: Index) -> Index {
        base.index(after: i)
    }

    func index(before i: Index) -> Index {
        base.index(before: i)
    }

    func index(_ i: Index, offsetBy distance: Int) -> Index {
        base.index(i, offsetBy: distance)
    }

    subscript(position: Index) -> Element {
        (index: position, element: base[position])
    }
}

When I click on the + button, I can add more tabs. But when I click on the delete button, My app crashes. What is the problem here? There does not seem to be anything wrong with the code.

question from:https://stackoverflow.com/questions/65660333/how-to-add-remove-views-from-a-paged-scrollview-tabview

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

No, I don't think you're doing anything wrong. I submitted an issue to Apple about a related issue on the TabView a few months ago but never heard anything back. The debug comes from the collection view coordinator:

#0  0x00007fff57011ca4 in Coordinator.collectionView(_:cellForItemAt:) ()

It seems like after removing an item, the underlying collection view doesn't get updated. In UIKit, we would probably call .reloadData() to force it to update. In SwiftUI, you could redraw the collection view on the screen to force it to update. Obviously, this affects the UI and isn't a perfect solution.

struct TabViewTest: View {
    
    @State var isLoading: Bool = false
    @State var data: [String] = [
        "one",
        "two"
    ]
    
    var body: some View {
        if !isLoading, !data.isEmpty {
            TabView {
                ForEach(data, id: .self) { item in
                    Text(item)
                        .tabItem { Text(item) }
                }
            }
            .tabViewStyle(PageTabViewStyle())
            .overlay(
                HStack {
                    Text("Add")
                        .onTapGesture {
                            add()
                        }
                    
                    Text("remove")
                        .onTapGesture {
                            remove()
                        }
                }
                , alignment: .bottom
            )
        }
    }
    
    func add() {
        data.append("three")
        print(data)
    }
    
    func remove() {
        isLoading = true
        data.removeFirst()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            isLoading = false
        }
        print(data)
    }
}

struct TabVIewTest_Previews: PreviewProvider {
    static var previews: some View {
        TabViewTest()
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...