英文:
swift reaching bottom of scroll view not working right
问题
抱歉,您的代码段中包含了一些特殊字符和代码注释,我会尽量保持原样并进行必要的翻译。以下是您的代码段的翻译部分:
import SwiftUI
import UIKit
struct FeedView: View {
@State private var scrollViewHeight = CGFloat.infinity
@Namespace private var scrollViewNameSpace
var body: some View {
mainInterFaceView
}
}
extension FeedView {
var mainInterFaceView: some View {
ZStack() {
ScrollView {
LazyVStack {
ForEach(viewModel.tweets) { tweet in
Button {
} label: {
someView()
.background(
GeometryReader { proxy in
Color.clear
.onChange(of: proxy.frame(in: .named(scrollViewNameSpace))) { newFrame in
if newFrame.minY < scrollViewHeight {
print("called")
}
}
}
)
}
}
}
}
.background(
GeometryReader { proxy in
Color.clear
.onChange(of: proxy.size, perform: { newSize in
let _ = print("ScrollView: ", newSize)
scrollViewHeight = newSize.height
})
}
)
.coordinateSpace(name: scrollViewNameSpace)
}
}
}
希望这有助于您理解您的代码。如果您有任何进一步的问题或需要额外的翻译,请随时提问。
英文:
Hello I have a scroll view and I would like to know when the user swipes to the bottom of it so that I can populate more data into it. The code I have below isn't working quite right. When the sim launches "hello" is printed about 5 times, and when I barely move it "hello" is printed like 10 more times, by the time I get to the bottom of the scroll view, "Hello" was printed like 100 times. How can I fix my code so that Hello is only printed when the bottom is reached.
import SwiftUI
import UIKit
struct FeedView: View {
@State private var scrollViewHeight = CGFloat.infinity
@Namespace private var scrollViewNameSpace
var body: some View {
mainInterFaceView
}
}
extension FeedView{
var mainInterFaceView: some View{
ZStack(){
ScrollView {
LazyVStack {
ForEach(viewModel.tweets) { tweet in
Button {
} label: {
someView()
.background(
GeometryReader { proxy in
Color.clear
.onChange(of: proxy.frame(in: .named(scrollViewNameSpace))) { newFrame in
if newFrame.minY < scrollViewHeight {
print("called")
}
}
}
)
}
}
}
}
.background(
GeometryReader { proxy in
Color.clear
.onChange(of: proxy.size, perform: { newSize in
let _ = print("ScrollView: ", newSize)
scrollViewHeight = newSize.height
})
}
)
.coordinateSpace(name: scrollViewNameSpace)
}
}
}
答案1
得分: 0
有一个比使用GeometryReader
和尝试计算偏移量更简单的方法来实现这个目标。
如果有更多的数据页面可用,您只需要在VStack
底部显示一个视图(ProgressView
很适合),然后在它出现时加载更多数据(使用.task
修饰符)。
struct Tweet: Identifiable {
let id = UUID()
let text: String
}
@MainActor
final class TweetModel: ObservableObject {
private let pageSize = 20
private (set) var tweets: [Tweet] = []
private (set) var moreTweetsAvailable = false
private var nextPage = 0
func loadFirstPage() async {
nextPage = 0
await loadPage()
}
func loadNextPage() async {
await loadPage()
}
private func loadPage() async {
let tweets = await // load tweets for nextPage
moreTweetsAvailable = tweets.count == pageSize
self.tweets.append(contentsOf: tweets)
nextPage += 1
}
}
struct ContentView: View {
@StateObject var tweetModel = TweetModel()
var body: some View {
ScrollView {
LazyVStack {
ForEach(tweetModel.tweets) { tweet in
Text(tweet.text)
}
if tweetModel.moreTweetsAvailable {
ProgressView()
.task {
await tweetModel.loadNextPage()
}
}
}
}
.task {
await tweetModel.loadFirstPage()
}
}
}
英文:
There's a much simpler way to do this than to use GeometryReader
s, and to try and calculate the offset.
If more pages of data are available, you just need to display a view (ProgressView
works nicely) at the bottom of your VStack
, and then load more data when it appears (using .task
modifier)
struct Tweet: Identifiable {
let id = UUID()
let text: String
}
@MainActor
final class TweetModel: ObservableObject {
private let pageSize = 20
private (set) var tweets: [Tweet] = []
private (set) var moreTweetsAvailable = false
private var nextPage = 0
func loadFirstPage() async {
nextPage = 0
await loadPage()
}
func loadNextPage() async {
await loadPage()
}
private func loadPage() async {
let tweets = await // load tweets for nextPage
moreTweetsAvailable = tweets.count == pageSize
self.tweets.append(contentsOf: tweets)
nextPage += 1
}
struct ContentView: View {
@StateObject var tweetModel = TweetModel()
var body: some View {
ScrollView {
LazyVStack {
ForEach(tweetModel.tweets) { tweet in
Text(tweet.text)
}
if tweetModel.moreTweetsAvailable {
ProgressView()
.task {
await tweetModel.loadNextPage()
}
}
}
}
.task {
await tweetModel.loadFirstPage()
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论