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