从swift中的单独类访问label.text

我有一个带有按钮的viewController,允许用户从URL下载文件。 为了保持我的代码干净,我创建了一个从我的视图中调用的下载类。 它工作正常,但现在我想为用户提供有关下载的一些UI提示。

假设我有一个标签,我想在下载结束后将其文本更改为“已下载”。 应该怎么做?

这是我的代码:

FileViewController

@IBOutlet weak var downloadLbl: UILabel! func downloadFile(sender:UIButton!) { fileDownloader().download_zip(datastring, destination: path, name: naming, fileis: self.fileId) } 

(这只是重要的部分)

然后我将我的下载function放在一个单独的类文件中,然后启动一个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"返回错误:致命错误:在展开Optional值时意外发现nil。

有人可以帮忙吗?

结论

这两个提议的解决方案在创建通信之间的通信时都起作用,但是我去了通知解决方案,因为在我的情况下我必须更新UI以及后台线程进展并且使用协议不能按预期工作。 进行了通信,但是即使在使用dispatch_async方法推回主线程上的更改之后,更新UI仍然无法正常工作。

使用通知系统有帮助,因为它更容易实现,管理和用于UI修改。

 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) } 

更多详细信息: https : //developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/

快乐编码:)

在这段代码中:

 FileViewController().downloadLbl.text = "downloaded" 

您正在创建一个新的FileViewController ,而不是引用现有的FileViewController 。 这个新标签还没有标签,因为它的视图尚未构建。 你参考downloadLbl ,这是一个UILabel! 。 这是nil ,所以你的应用程序崩溃了。

我有一个单独的类文件中的下载function

这是一个很好的做法,但是让这个单独的类修改UI是一个不好的做法。 相反,你应该编写一个定义这些类如何交互的Swift协议 。

一个简单的例子:

 protocol MyAwesomeDownloadResponder : class { func downloadFinished() } 

然后,您可以在视图控制器中实现此方法:

 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定义它。