UITableView 滚动到不需要的索引或位置
UITableView Scrolls To Undesired Index or Position
基本上,任务是在用户在 UITableView
中向下滚动时加载新的 API 响应,而不停止用户交互并保持当前位置(Facebook 和 Instagram 等实时订阅)。
我想要做的是使用自定义单元格解析并查看 Rest API 在 UITableView
中的响应。
问题是,当用户滚动到底部时,会进行 API 调用,并且 table 视图会滚动到用户所在的其他位置。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "xxxxx", for:indexPath) as! xxxxxxxx
return cell;
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if scrollView == tableView {
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height) {
print("Scroll Ended")
fetchDataFromApi()
}
}
}
func fetchDataFromApi() {
let jsonUrlString = "xxxxxxx"
guard let url = URL(string: jsonUrlString) else {
return
}
print(url)
URLSession.shared.dataTask(with: url) {(data,response,err) in
guard let data = data else {
return
}
do {
let apiResponseData = try JSONDecoder().decode(ApiResponse.self, from: data)
if apiResponseData.httpStatusCode == HttpStatusCode.OK {
if let apiResponse = apiResponseData.data{
self.array.append(contentsOf: apiResponse)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
else {
print("API Response Error : \(apiResponseData.httpStatusCode) \(apiResponseData.errorMessage)")
}
}catch let jsonErr {
print("Serialization Error \(jsonErr)")
}
}.resume()
}}
试试这个
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "xxxxx", for:indexPath) as! xxxxxxxx
let lastRowIndex = tableView.numberOfRows(inSection: tableView.numberOfSections-1)
if (indexPath.row == lastRowIndex - 1) {
//print("last row selected")
fetchDataFromApi()
}
return cell;
}
如果你正在使用这个就不需要调用这个方法
scrollViewDidEndDragging
尝试insertCellAtIndexPath
替换
中的tableview.reloadData()
if let apiResponse = apiResponseData.data{
self.array.append(contentsOf: apiResponse)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
......
有几种方法可以实现这一点。据我所知,最有利的是实现分页 API 并在 UITableView 的最后一项后调用 API 。您可以使用:
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let botEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (botEdge >= scrollView.contentSize.height)
{
// Call API and reload TableView on completion handler.
}
}
在 API 方法的完成处理程序上调用 tableView 重新加载。
或者你可以用稍微笨拙的方式来做:
public var indexPathsForVisibleRows: [NSIndexPath]? { get }
获取当前可见单元格的索引路径数组,并在重新加载 UITableView 后滚动到索引:
tableView.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.None, animated: false)
这是因为我在 table 视图中设置了动态单元格大小
基本上,任务是在用户在 UITableView
中向下滚动时加载新的 API 响应,而不停止用户交互并保持当前位置(Facebook 和 Instagram 等实时订阅)。
我想要做的是使用自定义单元格解析并查看 Rest API 在 UITableView
中的响应。
问题是,当用户滚动到底部时,会进行 API 调用,并且 table 视图会滚动到用户所在的其他位置。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "xxxxx", for:indexPath) as! xxxxxxxx
return cell;
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if scrollView == tableView {
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height) {
print("Scroll Ended")
fetchDataFromApi()
}
}
}
func fetchDataFromApi() {
let jsonUrlString = "xxxxxxx"
guard let url = URL(string: jsonUrlString) else {
return
}
print(url)
URLSession.shared.dataTask(with: url) {(data,response,err) in
guard let data = data else {
return
}
do {
let apiResponseData = try JSONDecoder().decode(ApiResponse.self, from: data)
if apiResponseData.httpStatusCode == HttpStatusCode.OK {
if let apiResponse = apiResponseData.data{
self.array.append(contentsOf: apiResponse)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
else {
print("API Response Error : \(apiResponseData.httpStatusCode) \(apiResponseData.errorMessage)")
}
}catch let jsonErr {
print("Serialization Error \(jsonErr)")
}
}.resume()
}}
试试这个
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "xxxxx", for:indexPath) as! xxxxxxxx
let lastRowIndex = tableView.numberOfRows(inSection: tableView.numberOfSections-1)
if (indexPath.row == lastRowIndex - 1) {
//print("last row selected")
fetchDataFromApi()
}
return cell;
}
如果你正在使用这个就不需要调用这个方法
scrollViewDidEndDragging
尝试insertCellAtIndexPath
替换
tableview.reloadData()
if let apiResponse = apiResponseData.data{
self.array.append(contentsOf: apiResponse)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
......
有几种方法可以实现这一点。据我所知,最有利的是实现分页 API 并在 UITableView 的最后一项后调用 API 。您可以使用:
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let botEdge = scrollView.contentOffset.y + scrollView.frame.size.height;
if (botEdge >= scrollView.contentSize.height)
{
// Call API and reload TableView on completion handler.
}
}
在 API 方法的完成处理程序上调用 tableView 重新加载。
或者你可以用稍微笨拙的方式来做:
public var indexPathsForVisibleRows: [NSIndexPath]? { get }
获取当前可见单元格的索引路径数组,并在重新加载 UITableView 后滚动到索引:
tableView.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.None, animated: false)
这是因为我在 table 视图中设置了动态单元格大小