Как использовать функцию обратного вызова в viewdidload ()? - PullRequest
0 голосов
/ 01 мая 2019

мне дали класс (Client) с функцией (requestSitesData), которая может получать данные с сервера, и в нем есть @escaping:

func requestSitesData(response: @escaping (_ data: Data?, _ error: Error?) -> Void) {
        DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + randomTimeDelay()) {
            guard self.isRequestSuccessful() else {
                response(nil, ClientError.requestFailed)

                return
            }
            guard let fileURL = Bundle.main.url(forResource: self.responseFilename, withExtension: "json") else {
                response(nil, ClientError.noFile)
                return 
            }
            do {
                let data = try Data(contentsOf: fileURL)
                let _ = try JSONSerialization.jsonObject(with: data)
                response(data, nil)
            } catch let error {
                response(nil, error)
            }
        }
    }

поэтому я думаю, что функция ответа здесь является функцией обратного вызова. В моем проекте у меня есть глобальная переменная для хранения данных с сервера, и я хочу отобразить ее на моем viewcontroller. Но кажется, что независимо от того, куда я поместил функцию call_back в классе viewcontroller, функция обратного вызова вызывается после всех функций (как и должно быть), поэтому я не могу получить данные в viewdidload ().

func call_back(data: Data?, error: Error?) -> Void {
        print("call_back called")
        if let file_data = data {
            if let sites_map = try? JSONSerialization.jsonObject(with: file_data, options: .mutableLeaves) as! [String: [Dictionary<String, Any>]] {
                if let sites = sites_map["sites"] {
                    for site in sites {
                        if let name = site["name"] as? String,
                        let slogan = site["slogan"] as? String,
                        let url = site["url"] as? String,
                        let description = site["description"] as? String,
                        let color = site["color"] as? String {
                            let single_site: Site = Site(name: name, slogan: slogan, url: url, description: description, color: color)
                            sites_res.append(single_site)
                        }
                    }
                }
            }
        }
    }

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let c = Client()
        c.requestSitesData { (response_data, response_error) in
            self.call_back(data: response_data, error: response_error)
            print("ddd")
        }

    }

Я не знаю, как получить данные в viewdidload (), потому что неправильный способ вызова этой функции call_back? Кто-нибудь может помочь?

Ответы [ 2 ]

0 голосов
/ 01 мая 2019

Изменить функцию, как показано ниже:

func call_back(data: Data?, error: Error?) -> [String: [Dictionary<String, Any>]]? {
            print("call_back called")
            if let file_data = data {
                if let sites_map = try? JSONSerialization.jsonObject(with: file_data, options: .mutableLeaves) as? [String: [Dictionary<String, Any>]] {
                    return sites_map
                }
            }
            return nil
        }


override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let c = Client()
        c.requestSitesData { (response_data, response_error) in
            if let sites_map = self.call_back(data: response_data, error: response_error){
        if let sites = sites_map["sites"] {
            for site in sites {
                if let name = site["name"] as? String,
                    let slogan = site["slogan"] as? String,
                    let url = site["url"] as? String,
                    let description = site["description"] as? String,
                    let color = site["color"] as? String {
                    let single_site: Site = Site(name: name, slogan: slogan, url: url, description: description, color: color)
                    sites_res.append(single_site)
                }
            }
        }
    }
  }
}
0 голосов
/ 01 мая 2019

Вам потребуется перезагрузить, обновить данные представления внутри обратного вызова, экранирующие замыкания устаревают от функции, в которой она была вызвана, поэтому обратный вызов внутри нее произойдет только после того, как функция завершит выполнение, и вернет ожидаемое значение в обратный вызов.

Проблема в том, что вы не знаете, сколько времени потребуется, чтобы вернуть эти данные, вы либо создаете функцию для обновления, чтобы перезагрузить представление и заставляете ее вызывать функцию обратного вызова, либо вы можете получить данные до того, какоткройте представленный ViewController и передайте ему данные.

EDIT 1

Попробуйте выполнить действия, показанные ниже, чтобы он обновлял ваши данные в View Controllerили просто данные в представлении, но измените их в соответствии с вашими потребностями.

func call_back(data: Data?, error: Error?) -> Void {
    print("call_back called")
    if let file_data = data {
        if let sites_map = try? JSONSerialization.jsonObject(with: file_data, options: .mutableLeaves) as! [String: [Dictionary<String, Any>]] {
            if let sites = sites_map["sites"] {
                for site in sites {
                    if let name = site["name"] as? String,
                    let slogan = site["slogan"] as? String,
                    let url = site["url"] as? String,
                    let description = site["description"] as? String,
                    let color = site["color"] as? String {
                        let single_site: Site = Site(name: name, slogan: slogan, url: url, description: description, color: color)
                        sites_res.append(single_site)
                    }
                }
            }
        }
    }
}
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let c = Client()
    c.requestSitesData { (response_data, response_error) in
        self.call_back(data: response_data, error: response_error)
        updateData()
    }

}

func updateData(){
//either update your data here or just update the data in the subviews.
    mylabel.text = data.text
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...