Как узнать размер файла перед загрузкой с URL? - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь показать размер файла перед загрузкой в ​​моем AlertView после нажатия на ячейку:

var fileSize = 0

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let url = URL(string: "http://ex.com/\(indexPath.row).mp3")!
    getDownloadSize(url: url, completion: { (size, error) in
        if error != nil {
            print("An error occurred when retrieving the download size: \(error!.localizedDescription)")
        } else {
            print("The download size is \(size).")
        self.fileSize = Int(size)
        }
    })

    // Create the alert controller
    let alertController = UIAlertController(title: nil, message: "Size - \(self.fileSize) MB", preferredStyle: UIAlertControllerStyle.actionSheet)

    etc

}

func getDownloadSize(url: URL, completion: @escaping (Int64, Error?) -> Void) {
        let timeoutInterval = 5.0
        var request = URLRequest(url: url,
                                 cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
                                 timeoutInterval: timeoutInterval)
        request.httpMethod = "HEAD"
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            let contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
            completion(contentLength, error)
        }.resume()
    }

Но когда я нажимаю на ячейку в первый раз, я получаю Размер - 0 МБ. И если я в следующий раз нажму на любую ячейку, я получу размер от предыдущего URL (предыдущей ячейки). Как это исправить?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2020

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

0 голосов
/ 27 апреля 2020

Задача данных URL является асинхронной. Ваш код не ждет, пока не завершится, прежде чем отобразить диалоговое окно.

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

Блок, который вы передаете на getDownloadSize(), будет запущен, как только будет получен результат, но код ниже этого вызова выполняется сразу после вызова getDownloadSize(), он не будет ждать, пока блок не будет выполнен.

И было бы неплохо изменить это, так как получение результата может занять от нескольких секунд до нескольких минут. Если выполнение кода будет блокироваться до тех пор, пока не будет получен результат, все ваше приложение также будет блокироваться на это время (ваш пользовательский интерфейс полностью зависнет, взаимодействие с пользователем будет невозможно).

...