Почему мой URLDownloadTask не вызывает didFinishDownloadtingTo?

Большая часть моего опыта программирования связана с Shell и Python. Я новичок в Swift, например, «3 дня назад». Я просто не могу понять, почему didFinishDownloadtingTo не вызывается, когда моя задача загрузки завершается. Вот мой файл AppDelegate.swift:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, URLSessionDelegate, URLSessionDownloadDelegate {

@IBOutlet weak var window: NSWindow!
@IBOutlet var progressind: NSProgressIndicator!
@IBOutlet var outputtext: NSTextField!



func applicationDidFinishLaunching(_ aNotification: Notification) {

    // Insert code here to initialize your application
    let requestURL: URL = URL(string: "https://www.apple.com")!
    let urlRequest: URLRequest = URLRequest(url: requestURL as URL)
    let session = URLSession.shared
    let downloads = session.downloadTask(with: urlRequest)
    print("starting download...")
    downloads.resume()

}

func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
}

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL){
    print("download finished!")
}


}

Я использую Swift 3, и я просто не могу найти достаточно документации, чтобы понять это самостоятельно.

Я немного сошел с ума, объявляя классы, пытаясь понять, почему это работает неправильно, поэтому я уверен, что там также есть некоторые ошибки.

Похоже, что файл успешно загружен. Я пробовал с несколькими URL-адресами. Разделы «Диск» и «Сеть» в меню отладки кажутся совместимыми с загрузкой файла такого размера по каждому URL-адресу, который я тестировал.


person Matt    schedule 23.08.2016    source источник
comment
чего ты пытаешься добиться? Просто цель тестирования? Если вы хотите что-то скачать, я предлагаю вам взглянуть на Alamofire. Используйте менеджер зависимостей, например Cocoapods.   -  person Andre Cytryn    schedule 23.08.2016
comment
Я просто пытаюсь получить файл со статической веб-страницы. Это появится один раз, когда приложение будет сказано и сделано, поэтому загрузка и обучение использованию всей сетевой библиотеки для загрузки одного файла для первоначальной настройки приложения кажется мне слишком сложным в данный момент.   -  person Matt    schedule 23.08.2016


Ответы (2)


Дело в том, что когда вы используете NSURLSession(URLSession в Swift 3), вам нужно выбрать, вы хотите использовать делегат или обработчик завершения, в случае использования обоих вызывается только обработчик завершения. В вашем случае delegate не установлен, поэтому вы не можете видеть вызов методов делегата. Вместо этого вы должны указать delegate, используя другой инициализатор NSURLSession, как в следующем коде:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, URLSessionDelegate, URLSessionDownloadDelegate {

   func applicationDidFinishLaunching(_ aNotification: Notification) {
      let requestURL: URL = URL(string: "https://www.apple.com")!
      let urlRequest: URLRequest = URLRequest(url: requestURL as URL)

      let config = URLSessionConfiguration.default
      let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

      let downloads = session.downloadTask(with: urlRequest)

      print("starting download...")
      downloads.resume()
   }

   func applicationWillTerminate(_ aNotification: Notification) {
      // Insert code here to tear down your application
   }

   func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL){
       print("download finished!")
   }   
}

И тогда вы должны увидеть, что метод делегата вызывается правильно.

Я надеюсь, что это поможет вам

person Victor Sigler    schedule 23.08.2016
comment
Это сработало отлично! Это подводит меня ко второму вопросу. Я до сих пор не уверен, как делегаты связываются друг с другом или работают вместе, или как это называется. В этом случае сам мой файл AppDelegate.swift? Если да, то замена себя на DownloadDelegate скажет моей программе искать в DownloadDelegate.swift метод didFinishDownloadingTo? - person Matt; 23.08.2016
comment
@ user6684500 Нет, это не тот способ, которым обрабатывается шаблон делегата, делегат очень легко понять, если вы внимательно посмотрите, вы делегируете функцию другим объектам. Делегирующий объект хранит ссылку на другой объект - делегат и на соответствующее время отправляет ему сообщение, вы можете узнать больше об этом здесь. И, пожалуйста, примите ответ, если решите свой вопрос :) - person Victor Sigler; 23.08.2016

Ключ заключается в слове «делегат». Это как ночная собака в сказке о Шерлоке Холмсе. Ночью собака ничего не делала. Слово «делегат» никогда не появляется в вашем коде!

Но это необходимо. didFinishDownloadingTo – это метод делегата. Вы можете получить этот метод только в том случае, если вы являетесь делегатом сеанса NSURLSession. Вам нужно установить self как его delegate. Среда выполнения не читает ваши мысли волшебным образом и не знает, что вы намереваетесь использовать этот объект в качестве делегата; вы должны рассказать об этом.

person matt    schedule 23.08.2016
comment
Да, действительно, @matt, но дело в том, что он использует URLSession.shared, а поскольку delegate в URLSession доступен только для чтения, по крайней мере, это невозможно сделать таким образом. - person Victor Sigler; 23.08.2016
comment
@VictorSigler Совершенно верно. Я просто пытаюсь прояснить концепцию. Вопрос был в том, что я просто не могу понять, почему didFinishDownloadtingTo не вызывается. И ответ в том, что я сказал: это потому, что вы не делегат. Я не сказал, что ваш ответ неверен (хотя на самом деле ваш разговор об обработчике завершения совершенно не соответствует действительности). Преимущество вашего ответа заключается в том, что он сообщает ОП, что делать. Но мой ответ имеет то преимущество, что отвечает на вопрос, который на самом деле задал ОП. Мне кажется, мир достаточно велик для обоих. - person matt; 23.08.2016
comment
@matt Я включил didFinishDownloadingTo в свой appDelegate, и при настройке сеанса я устанавливаю делегата на себя, но я все еще не понимаю этот метод. Любые другие идеи, почему иначе метод делегата не будет вызываться? Полная информация здесь: stackoverflow.com/questions/41488989/ - person user2363025; 05.01.2017