我提出了其他解决方案,使用库 自省获取 UITableView 引用,直到 Apple 改进了可用的方法。
struct LandmarkList: View {
@EnvironmentObject private var userData: UserData
@State private var tableView: UITableView?
private var disposables = Set<AnyCancellable>()
var body: some View {
NavigationView {
VStack {
List(userData.landmarks, id: \.id) { landmark in
LandmarkRow(landmark: landmark)
}
.introspectTableView { (tableView) in
if self.tableView == nil {
self.tableView = tableView
print(tableView)
}
}
}
.navigationBarTitle(Text("Landmarks"))
.onReceive(userData.$landmarks) { (id) in
// Do something with the table for example scroll to the bottom
self.tableView?.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false)
}
}
}
}
struct Message: Identifiable, Codable, Hashable {
//MARK: Attributes
var id: String
var message: String
init(id: String, message: String){
self.id = id
self.message = message
}
}
实际观点:
@ObservedObject var messages = [Message]()
@State private var scrollTarget: Int?
var scrollView : some View {
ScrollView(.vertical) {
ScrollViewReader { scrollView in
ForEach(self.messages) { msg in
Text(msg).id(message.id)
}
//When you add new element it will scroll automatically to last element or its ID
.onChange(of: scrollTarget) { target in
withAnimation {
scrollView.scrollTo(target, anchor: .bottom)
}
}
.onReceive(self.$messages) { updatedMessages in
//When new element is added to observed object/array messages, change the scroll position to bottom, or last item in observed array
scrollView.scrollTo(umessages.id, anchor: .bottom)
//Update the scrollTarget to current position
self.scrollTarget = updatedChats.first!.messages.last!.message_timestamp
}
}
}
}