Задать вопрос
@Malkolm163

Как закрыть UIAlertController?

Есть 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
  • Вопрос задан
  • 140 просмотров
Подписаться 1 Средний 6 комментариев
Решения вопроса 1
Loriens
@Loriens
iOS Developer
Перемести appDelegate.getApiService(...).getRequests(...) во viewDidAppear. Present view controller'a не должен вызываться во viewDidLoad.

Нашёл здесь - ответ на StackOverflow
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы