我有一个带有按钮的viewController,允许用户从网址下载文件。 为了保持我的代码清洁,我创建了一个从我的视图中调用的下载类。它工作正常,但现在我想为用户提供有关下载的一些UI提示。
假设我有一个标签,我想将其文本更改为" Downloaded"一旦下载结束。应该怎么做?
这是我的代码:
FileViewController
@IBOutlet weak var downloadLbl: UILabel!
func downloadFile(sender:UIButton!)
{
fileDownloader().download_zip(datastring, destination: path, name: naming, fileis: self.fileId)
}
(这只是重要部分)
然后我将我的下载功能放在一个单独的类文件中,然后启动一个DownloadTaskSession并使用以下委托来观察下载完成
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println("session \(session) has finished the download task \(downloadTask) of URL \(location).")
FileViewController().downloadLbl.text = "downloaded"
}
最后一行:FileViewController().downloadLbl.text = "downloaded"
返回错误:致命错误:在解包可选值时意外发现nil。
有人可以帮忙吗?
结论
这两个提议的解决方案都可以在创建通信解决方案之间进行通信时使用,但是我选择了通知解决方案,因为在我的情况下,我必须更新UI以及后台线程进度,并且使用协议并没有按预期工作。进行了沟通,但即使在使用dispatch_async方法推回主线程上的更改后,更新UI仍然无法正常工作。
使用通知系统有帮助,因为它更容易实现,管理和用于UI修改。
答案 0 :(得分:8)
在此代码中:
FileViewController().downloadLbl.text = "downloaded"
您正在创建新的FileViewController
,而不是引用现有的downloadLbl
。这个新标签还没有标签,因为它的视图还没有建成。您引用UILabel!
,即nil
。它是protocol MyAwesomeDownloadResponder : class {
func downloadFinished()
}
,因此你的应用程序崩溃了。
我的下载功能位于单独的类文件
中
这是一个很好的做法,但是让这个单独的类修改UI是一种不好的做法。相反,您应该编写一个Swift protocol来定义这些类如何交互。
一个简单的例子:
class FileViewController : UIViewController, MyAwesomeDownloadResponder {
@IBOutlet weak var downloadLbl: UILabel!
func downloadFinished() {
downloadLbl.text = "Downloaded"
}
}
然后,您可以在视图控制器中实现此方法:
responder
在下载类中,存储对class Downloader {
weak var responder : MyAwesomeDownloadResponder?
init(responder : MyAwesomeDownloadResponder) {
self.responder = responder
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
responder?.downloadFinished()
}
}
的引用,然后在下载完成时调用响应者:
protocol
如果您需要在这些类之间传递任何信息,请在{{1}}。
中进行定义答案 1 :(得分:3)
FileViewController().downloadLbl.text = "downloaded"
是指"创建新的FileViewController,并设置downloadLbl文本"。
您需要将文本设置为现有的FileViewController 要将来自URLSession完成块的消息告知FileViewController,您可以使用委托或通知模式。
例如,通知模式:
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println("session \(session) has finished the download task \(downloadTask) of URL \(location).")
// notify download complete!
let defaultCenter = NSNotificationCenter.defaultCenter()
defaultCenter.postNotificationName("CompleteDownloadNotification",
object: nil,
userInfo: nil)
}
----------------
@IBOutlet weak var downloadLbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// ready for receiving notification
let defaultCenter = NSNotificationCenter.defaultCenter()
defaultCenter.addObserver(self,
selector: "handleCompleteDownload",
name: "CompleteDownloadNotification",
object: nil)
}
func handleCompleteDownload() {
// if notification received, change label value
downloadLbl.text = "downaloded"
}
func downloadFile(sender:UIButton!) {
fileDownloader().download_zip(datastring, destination: path, name: naming, fileis: self.fileId)
}
快乐编码:)