Swift UIRefresh Control Перетащите для обновления в UITableView вызывает сбой приложения - PullRequest
1 голос
/ 22 октября 2019

У меня есть UIRefreshControll, внутри моего TableView. Все работает нормально, но если я слишком быстро вытащу таблицу, приложение вылетает. Ошибка: фатальная ошибка: индекс выходит за пределы диапазона

Когда я вызываю функцию refreshData из Button, сбой не появляется. Это немного странно, потому что refreshControll не делает что-то отличное от вызова действия. Я надеюсь, что кто-нибудь сможет мне помочь.

private let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(self.refreshData), for: .valueChanged)

if #available(iOS 10.0, *) {
                    self.tableView.refreshControl = self.refreshControl
                } else {
                    self.tableView.addSubview(self.refreshControl)
                }

@objc private func refreshData() {

    if isRefreshing {
        self.refreshControl.endRefreshing()
        return
    }
    isRefreshing = true
    print("refresh")

    guard let url = URL(string: taskURL) else {
        return
    }

    let request = URLRequest(url: url)

    urlSessionBackground.dataTask(with: request) { (dataOpt, response, error) in

        if error != nil {
            DispatchQueue.main.async {
                let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
                    self.refreshControl.endRefreshing()
                }))
                self.present(alert, animated: true)
            }
            return
        }else {
            self.data.removeAll()
            self.userImage.removeAll()
            self.currentData.removeAll()
            self.taskDetails.removeAll()
        }

        guard let dataNew = dataOpt else {
            return
        }

        let appdata = try? JSONDecoder().decode(TaskList.self, from: dataNew)

        for data in appdata!{

              self.data.append(CellData.init(image: UIImage(named: "Profile"), message: data.name, checkImage: data.status))
                self.userImage.append("")

              self.taskDetails.append(TaskDetails.init(status: data.status, assigned: data.assigneUid, time: data.duedateTsUTC, priority: data.priority, desc: data.desc, uid: data.uid))


        }

        self.currentData = self.data

        DispatchQueue.main.async {
            self.tableView.reloadData()
            self.searchBar.text = ""
            self.isRefreshing = false
            self.refreshControl.endRefreshing()
        }

    }.resume()
}

Исправлено: использовались временные переменные для сохранения данных и последующего использования. Удаление данных было проблемой.

Ответы [ 2 ]

0 голосов
/ 22 октября 2019

Просто попробуйте это

var dataTask: URLSessionDataTask?
let defaultSession = URLSession(configuration: .background)

@objc private func refreshData() {

if isRefreshing {
    self.refreshControl.endRefreshing()
    return
}
isRefreshing = true
print("refresh")
guard let url = URL(string: taskURL) else {
    return
}
dataTask?.cancel()
let request = URLRequest(url: url)

dataTask = 
defaultSession.dataTask(with: url) { [weak self](dataOpt, response, error) in 
defer {
  self?.dataTask = nil
}

if let error = error {
  DispatchQueue.main.async {
            let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
                self.refreshControl.endRefreshing()
            }))
            self.present(alert, animated: true)
        }
        return

} else if 
  let data = dataOpt,
  let response = response as? HTTPURLResponse,
  response.statusCode == 200 {  
        self.data.removeAll()
        self.userImage.removeAll()
        self.currentData.removeAll()
        self.taskDetails.removeAll()      
    let appdata = try? JSONDecoder().decode(TaskList.self, from: data)

    for data in appdata!{

          self.data.append(CellData.init(image: UIImage(named: "Profile"), message: data.name, checkImage: data.status))
            self.userImage.append("")

          self.taskDetails.append(TaskDetails.init(status: data.status, assigned: data.assigneUid, time: data.duedateTsUTC, priority: data.priority, desc: data.desc, uid: data.uid))


    }

    self.currentData = self.data

    DispatchQueue.main.async {
        self.tableView.reloadData()
        self.searchBar.text = ""
        self.isRefreshing = false
        self.refreshControl.endRefreshing()
    }
}
}


dataTask?.resume()

}
0 голосов
/ 22 октября 2019

Попробуйте это

    if error != nil {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: "Loading Error", message: "No Internet Connection. Please try again later.", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {(action: UIAlertAction!) in
                self.refreshControl.endRefreshing()
            }))
            self.present(alert, animated: true)
        }
        return
    }else {
        if self.data != nil{            
           self.data.removeAll()
        }
        if self.userImage != nil{            
           self.userImage.removeAll()
        }
        if self.currentData != nil{            
           self.currentData.removeAll()
        }
        if self.taskDetails != nil{            
           self.taskDetails.removeAll()
        }
    }
...