Есть 2 контроллера
import Foundation
import UIKit
import SwiftyJSON
class HistoryController: UIViewController{
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var uStorage : UserStorage?
var ds : [Any] = Array()
@IBOutlet weak var bValues: UIButton!
@IBOutlet weak var bBills: UIButton!
@IBOutlet weak var bPays: UIButton!
@IBOutlet weak var historyTable: UITableView!
@IBAction func showValues(_ sender: Any) {
updateStatus(0)
}
@IBAction func showBills(_ sender: Any) {
updateStatus(1)
}
@IBAction func showPays(_ sender: Any) {
updateStatus(2)
}
var pageStatus : Int = 0
func updateStatus(_ status: Int) {
........// some actions
appDelegate.getApiService(self, sourceGetSuccess, sourceGetFail)
.getHistory((uStorage?.getCurrentPa().nls)!, pageStatus)
}
override func viewDidLoad() {
uStorage = appDelegate.getUserStorage()
let clValue = UINib(nibName: "HistoryValueCell", bundle: nil)
let cl2Value = UINib(nibName: "HistoryTwoValueCell", bundle: nil)
historyTable.register(clValue.self, forCellReuseIdentifier: "value_cell")
historyTable.register(cl2Value.self, forCellReuseIdentifier: "value_2_cell")
historyTable.dataSource = self
// historyTable.rowHeight = 65
historyTable.separatorColor = UIColor.clear
// Rounded buttons
bValues.cornederRadius(radius: 10)
bBills.cornederRadius(radius: 10)
bPays.cornederRadius(radius: 10)
}
override func viewDidAppear(_ animated: Bool) {
updateStatus(0)
}
func sourceGetSuccess(_ buf: Data)-> Void {
do {
let data = try JSON.init(data: buf);
...//обработка данных с сервера
historyTable.dataSource = self
historyTable.reloadData()
} catch {
appDelegate.showErrorMessage(error.localizedDescription, self)
}
}
func sourceGetFail(_ buf: Data) -> Void {
appDelegate.showErrorMessage(String(data: buf, encoding: .utf8)!, self)
}
}
extension HistoryController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ds.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch pageStatus {
...//обработка данных - создание ячеек
}
}
и
import Foundation
import UIKit
import SwiftyJSON
class RequestsListViewController: UIViewController{
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var uStorage : UserStorage?
var HistoryChangePM: Array<RequestEntry> = []
@IBOutlet weak var requestsListTView: UITableView!
let cellId = "request_cell";
override func viewDidLoad() {
uStorage = appDelegate.getUserStorage()
let cellType = UINib(nibName: "RequestViewCell", bundle: nil)
requestsListTView.register(cellType.self, forCellReuseIdentifier: cellId)
requestsListTView.separatorColor = UIColor.clear
requestsListTView.dataSource = self
requestsListTView.rowHeight = 100
appDelegate.getApiService(self, sourceGetSuccess, sourceGetFail)
.getRequests((uStorage?.getCurrentPa().nls)!)
}
func sourceGetSuccess(_ buf: Data)-> Void {
print("sourceGetSuccess");
do {
let data = try JSON.init(data: buf);
if data["HistoryChangePM"].exists(){
HistoryChangePM = [];
...//обработка данных
}
print("reloading data")
requestsListTView.reloadData()
} catch {
appDelegate.showErrorMessage(error.localizedDescription, self)
}
print("end")
}
func sourceGetFail(_ buf: Data)-> Void {
// print("sourceGetFail");
// print(buf)
}
}
extension RequestsListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return HistoryChangePM.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! RequestViewCell;
let item = HistoryChangePM[indexPath.row]
cell.counterType.text = item.mTypeMeteringDevice
return cell;
}
}
appDelegate
методы getApiService, showBusy (показывает прелоадер) и hideBusy(скрывает прелоадер)
func getApiService(_ view: UIViewController, _ handler: ((Data)->Void)!, _ errorHandeler: ((Data)->Void)!) -> SomeApi {
return SomeApi(app: self, cView: view, handler: handler, error_handler: errorHandeler)
}
func showBusy(_ view : UIViewController) {
let alert = UIAlertController(title: "", message: "Пожалуйста подождите...", preferredStyle: .alert)
let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
loadingIndicator.hidesWhenStopped = true
loadingIndicator.style = UIActivityIndicatorView.Style.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
view.present(alert, animated: true, completion: nil)
}
func hideBusy(_ view: UIViewController, handler: @escaping (() -> Void)) {
DispatchQueue.main.async {
view.dismiss(animated: false, completion: handler)
}
}
метод SomeApi.getRequests и конструктор SomeApi
init(app: AppDelegate, cView : UIViewController, handler: @escaping ((Data)->Void), error_handler: @escaping ((Data)->Void)) {
requestHandler = handler
requestErroHandler = error_handler
self.app = app
self.view = cView
self.url = URL(string: "https://some_server.ru")!
}
func getRequests(_ pa: String) {
if(app.cookie != nil) {
app.showBusy(self.view)
var request = URLRequest(url: self.url)
request.httpMethod = "POST"
request.addValue("Content-Type", forHTTPHeaderField: "application/x-www-form-urlencoded")
request.addValue("Cookie", forHTTPHeaderField: app.cookie!)
let body: Data = makeBody(REQUESTS, "{\"accountNumber\":\"\(pa)\"}")
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let task = session.uploadTask(with: request, from: body)
task.resume()
} else {
DispatchQueue.main.sync {
self.requestErroHandler("Нет авторизации".data(using: .utf8)!)
}
}
}
и расширения для этого апи
extension SomeApi: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
do {
let data: Data = try Data(contentsOf: location)
DispatchQueue.main.async {
self.requestHandler(data)
}
} catch {
print("Can`t get data form loacation")
}
}
}
extension SomeApi: URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
let d : String = String(data: data, encoding: .windowsCP1251)!
let rd = d.replacingOccurrences(of: "\n", with: "\\n")
let dd = JSON.init(parseJSON: rd)
if(dd["errorStatus"].boolValue) {
self.app.hideBusy(self.view, handler: {
DispatchQueue.main.async {
self.requestErroHandler(dd["result"]["Msg"].stringValue.data(using: .utf8)!)
}
})
} else {
let ss = dataTask.response as! HTTPURLResponse
let cookie : Any? = ss.allHeaderFields["Set-Cookie"]
if cookie != nil {
app.cookie = cookie as? String
}
do {
let ddd: Data = try dd["result"].rawData()
self.app.hideBusy(self.view, handler: {
// DispatchQueue.main.async {
print("self.requestHandler(ddd)")
self.requestHandler(ddd)
print("end self.requestHandler(ddd)")
// }
})
} catch {
self.app.hideBusy(self.view, handler: {
DispatchQueue.main.async {
self.requestErroHandler("Не данных".data(using: .utf8)!)
}
})
}
}
}
}
Получается работает так:
1 из контроллера я вызываю appDelegate.getApiService(self, sourceGetSuccess, sourceGetFail)
.getRequests((uStorage?.getCurrentPa().nls)!) например
2 в appDelegate записывается текущий viewcoltroller и создается SomeApi экземпляр
3 вызывается метод getRequests с параметрами и в методе вызывается showBusy, который отображает прелоадер, создается таск для запроса и когда запрос выполняется в итоге вызывается hideBusy в котором я пытаюсь скрыть прелоадер и по завершению скрытия прелоадера вызывается хендлер который я в самом контроллере описываю (в данном примере это sourceGetSuccess)
Проблема в том, что такая схема используется на всех контроллерах приложения и все везде работает кроме RequestsListViewController
В итоге прелоадер висит и не закрывается
https://yadi.sk/i/CZktHy_qb8PyAA
Подскажите где искать источник проблемы.
Добавил на гитлаб:
https://gitlab.com/malkolm163/samges