I asynchronously call a downloader object function to try to download a file.
Within the downloader's function, it asynchronously initiates a connection for downloading.
Even so, I cannot interact with my UI elements.
For example, I cannot edit my text field while download is in progress.
I want to be able to interact with my UI elements while downloading.
Where did I miss? What should I do? I truly appreciate your help!
//relevant UI elements I am referring to
@IBOutlet var renderButton: UIButton!
@IBOutlet var urlField: UITextField!
func handleOpenURL(url: NSURL){
var downloader: aDownloader = aDownloader(url: url)
//I try to put download to background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {() -> Void in
//This function initiates a connection call in an attempt to download the file
downloader.executeConnection({
(dataURL:NSURL!,error:NSError!) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.imageView.image = UIImage(data:NSData(contentsOfURL: url)!)
})
//rest are nonsense
}, progress: { (percentage:Double) -> Void in
//nonsense
}
)
})
}
class aDownloader: NSObject, allOtherProtocols {
unowned var url: NSURL
//this block reports the progress as a % number
var progressBlock : ((Double)->Void)?
//this block will return either the destinationFileURL after download finishes,
//or return error of any sort
var dataBlock: ((NSURL!,NSError!)->Void)?
init(url: NSURL) {
self.url = url
}
func executeConnection(received:(NSURL!,NSError!)->Void, progress:(Double)->Void){
var request : NSURLRequest = NSURLRequest(URL: self.url,
cachePolicy: .ReloadIgnoringLocalCacheData,
timeoutInterval: 60.0)
//I attempt to async-ly download the file here
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { () -> Void in
var connectionManager : NSURLConnection? = NSURLConnection(request:request,
delegate: self,
startImmediately: false)
connectionManager?.scheduleInRunLoop(NSRunLoop.mainRunLoop(),
forMode: NSRunLoopCommonModes)
connectionManager?.start()
})
self.dataBlock = received
self.progressBlock = progress
}
//nonsense
}
Two things.
Most importantly, you are still configuring your configuration manager to run on the main loop:
connectionManager?.scheduleInRunLoop(NSRunLoop.mainRunLoop(),
forMode: NSRunLoopCommonModes)
You will probably find it easier to just use NSURLConnection's class method sendAsynchronousRequest:queue:completionHandler: instead of manually starting the request in a background thread.
Also, it is a bad idea to update UI elements from a background thread:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.imageView.image = UIImage(data:NSData(contentsOfURL: url)!)
})
Instead, you should load the image into a temporary variable in the background and then perform the actual assignment back on the main thread.