我已经使用下载任务定义了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
}
}
答案 0 :(得分:2)
好的,有几件事......好吧......我谦虚地认为我选择了错误的选择:)
以下是我将如何解决这个问题。
你的基本想法是:
"Have a custom view, that displays stuff according to some information downloaded from the net"
首先,我们应该看看我们需要什么:
现在我们 NOT 想要将任何异步下载内容混合到视图中。视图应该只是愚蠢并显示它给出的内容。 (我不得不承认我不知道你的观点会实际显示什么,因此可能会出现这种情况,这可能被认为是有效的,但很可能并非如此)
因此,我建议您创建一个单独的类来处理下载,并创建一个单独的类视图。
您可以创建一个您可以执行使用GCD在控制器内部进行异步处理,并在完成处理程序中(在任何一种情况下)告诉视图重新显示自己。NSOperation
子类来执行所有异步操作并由控制器排队/启动(例如,请参阅Ray Wenderlich's NSOperation Tutorial)或
视图可以在未下载内容时显示占位符,并且通过从外部调用函数(控制器将调用此函数)可以在新内容到达时重新呈现。有一件事是肯定的:DrawRect需要尽可能快!
所以你可能希望在那里有一个if语句,并且只有在提取内容时(视图可以有一个Bool
或Enum
来指示这种状态),你可以调用一个专门的绘图您的视图方法,否则只需绘制占位符。
不要在那里的任何地方使用dispatch_sync ......事实上,不要在任何地方使用它。在大多数情况下,您确实想要异步(像往常一样,例外情况适用)。在drawRect
内的这种特殊情况下,你真的不能使用这样的任何GCD函数,因为在主线程afaik上调用drawRect,你不能在主线程之外进行任何绘制。
我希望这能让你开始。否则我可能会在本周晚些时候找到时间来提出一些代码。
编辑:您可以使用NSURLDownloadTask,但是在控制器中。单独的NSOperation子类可能不是这里的最佳选择,也是不必要的。