在程序需要使用该文件后,会发生NSURLSession任务文件下载

时间:2015-03-27 17:53:08

标签: ios swift grand-central-dispatch nsurlsession

我已经使用下载任务定义了NSURLSession。我想下载一个文件,然后在我的绘图样式工具包中使用文件中的值。会话和绘图样式工具包确实在同步队列上运行,遗憾的是,任务在NSOperationQueue上运行,该NSOperationQueue在创建视图之后才会运行。因此,视图不包含正确的文件信息。有编码解决方案还是逻辑问题,是否有人提出改进逻辑的建议。我是新手,所以欢迎任何建议。

class SomeView: UIView, NSURLSessionDelegate, NSURLSessionTaskDelegate

{
var session: NSURLSession!

required init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder)

    // Create the session configuration
    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    configuration.timeoutIntervalForRequest = 15.0

    // Create the session
    session = NSURLSession(configuration: configuration,
        delegate: self,
        delegateQueue: nil)
}



override func drawRect(rect: CGRect)
{
    let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)


        dispatch_sync(queue,
            {
                // Define the data source at www.powerball.com/powerball/winnums-text.txt
                let url = NSURL(string: "http://www.powerball.com/powerball/winnums-text.txt")

                // Create the download task for the session

                let task = self.session.downloadTaskWithURL(url!, completionHandler:
                    {[weak self] (url: NSURL!,
                        response: NSURLResponse!,
                        error: NSError!) in

                        if error == nil
                        {
                            let fileManager = NSFileManager()


                            //Get the path for the caches folder
                            var error: NSError?
                            var cachePath = fileManager.URLForDirectory(
                                NSSearchPathDirectory.CachesDirectory,
                                inDomain: NSSearchPathDomainMask.UserDomainMask,
                                appropriateForURL: url,
                                create: true,
                                error: &error)!


                            // Assign consistent file name
                            var fileName = "winnums-text"

                            // Apend the file name to the cache path
                            var filePath = cachePath.URLByAppendingPathComponent(fileName)

                            // Move the file to the file path
                            fileManager.moveItemAtURL(url, toURL: filePath, error: nil)

                            println(filePath)
                        }
                        else
                        {
                            println("Connection failed")  //add user notification later
                        }

                        //Clean up sessions
                        self!.session.finishTasksAndInvalidate()
                })  //Task
                task.resume()
            })  // Dispatch queue

        dispatch_sync(queue,
            {
                    // Only override drawRect: if you perform custom drawing.
                    SomeappStyleKit.drawMain(frame: self.bounds)

            })  // Dispatch queue

}

}

1 个答案:

答案 0 :(得分:2)

好的,有几件事......好吧......我谦虚地认为我选择了错误的选择:)

以下是我将如何解决这个问题。

你的基本想法是:

"Have a custom view, that displays stuff according to some information downloaded from the net"

首先,我们应该看看我们需要什么:

  • 您需要自定义视图
  • 您需要某种形式的异步下载
  • 您需要一些协调控制器
  • 你需要决定整个事情应该如何表现:
    • 仅在下载信息时创建视图吗?
    • 视图在开头是否已经存在,同时显示的是什么?
    • 什么触发下载?有些控制器?这个观点真的不应该。

现在我们 NOT 想要将任何异步下载内容混合到视图中。视图应该只是愚蠢并显示它给出的内容。 (我不得不承认我不知道你的观点会实际显示什么,因此可能会出现这种情况,这可能被认为是有效的,但很可能并非如此)

因此,我建议您创建一个单独的类来处理下载,并创建一个单独的类视图。

您可以创建一个NSOperation子类来执行所有异步操作并由控制器排队/启动(例如,请参阅Ray Wenderlich's NSOperation Tutorial)或您可以执行使用GCD在控制器内部进行异步处理,并在完成处理程序中(在任何一种情况下)告诉视图重新显示自己。

视图可以在未下载内容时显示占位符,并且通过从外部调用函数(控制器将调用此函数)可以在新内容到达时重新呈现。有一件事是肯定的:DrawRect需要尽可能快!

所以你可能希望在那里有一个if语句,并且只有在提取内容时(视图可以有一个BoolEnum来指示这种状态),你可以调用一个专门的绘图您的视图方法,否则只需绘制占位符。

不要在那里的任何地方使用dispatch_sync ......事实上,不要在任何地方使用它。在大多数情况下,您确实想要异步(像往常一样,例外情况适用)。在drawRect内的这种特殊情况下,你真的不能使用这样的任何GCD函数,因为在主线程afaik上调用drawRect,你不能在主线程之外进行任何绘制。

我希望这能让你开始。否则我可能会在本周晚些时候找到时间来提出一些代码。

编辑:您可以使用NSURLDownloadTask,但是在控制器中。单独的NSOperation子类可能不是这里的最佳选择,也是不必要的。