我定义了一个带有下载任务的 NSURLSession。我想下载一个文件,然后在我的绘图样式工具包中使用文件中的值。 session 和绘图样式工具包确实在同步队列上运行,不幸的是,任务在 NSOperationQueue 上运行,该队列在创建 View 后才运行。因此, View 不包含正确的文件信息。是否有编码解决方案或者它是一个逻辑问题,是否有人对改进逻辑有建议。我是新手,欢迎提出任何建议。
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
}
最佳答案
好吧,有几件事......好吧......以我的拙见我会说选择不当:)
下面是我将如何解决这个问题。
你的基本思路是:
"Have a custom view, that displays stuff according to some information downloaded from the net"
首先,我们应该看看我们需要什么:
- 您需要一个自定义 View
- 您需要某种形式的异步下载
- 你需要一些协调的 Controller
- 你需要决定整个事情应该如何表现:
- 是否仅在下载信息时创建 View ?
- View 是否在一开始就已经存在,同时显示的是什么?
- 什么触发下载?一些 Controller ?该 View 确实不应该。
现在我们不想将任何异步下载内容混合到 View 中。 View 应该只是愚蠢的并显示它给出的内容。 (我不得不承认我不知道你的 View 实际会显示什么,所以在某些情况下这可能被认为是有效的,但很可能不是)
因此我建议您创建一个单独的类来处理下载和一个单独的类作为您的 View 。
您可以创建一个 您可以这样做使用 GCD 的 Controller 内部的异步内容,以及完成处理程序(在任何一种情况下)告诉 View 重新显示自身。NSOperation
子类来执行所有异步操作并由您的 Controller 入队/启动(例如参见 Ray Wenderlich's NSOperation Tutorial)或者
View 可以在内容未下载时显示一个占位符,并且通过从外部调用一个函数( Controller 将调用它)可以在新内容到达时重新呈现自身。有一件事是肯定的:DrawRect 需要尽可能快!
因此您可能希望在其中有一个 if 语句,并且仅当内容被获取时( View 可以有一个 Bool
或 Enum
来指示此状态) ,您调用 View 的专门绘制方法,否则只需绘制占位符。
并且不要在那里的任何地方使用 dispatch_sync……事实上,根本不要在任何地方使用它。在大多数情况下,您确实希望异步(像往常一样,有异常(exception))。在 drawRect
中的这种特殊情况下,您真的不能像这样使用任何 GCD 函数,因为 drawRect 是在主线程 afaik 上调用的,您不能在主线程之外进行任何绘图。
我希望这能让你开始。否则我可能会在本周晚些时候抽出时间来编写一些代码。
编辑:您可以只使用您拥有的 NSURLDownloadTask,但在 Controller 中。一个单独的 NSOperation 子类在这里可能不是最好的选择,也没有必要。
关于ios - NSURLSession 任务文件下载发生在程序需要使用该文件之后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29307113/