从 swift 中单独的 class 访问 label.text
Access label.text from separate class in swift
我有一个 viewController,带有一个按钮,允许用户从 url 下载文件。
为了保持我的代码干净,我创建了一个下载 class,我从我的视图中调用它。它运行良好,但现在我想为用户提供一些有关下载的 UI 提示。
假设我有一个标签,我想在下载结束后将其文本更改为 "Downloaded"。应该怎么做?
这是我的代码:
文件视图控制器
@IBOutlet weak var downloadLbl: UILabel!
func downloadFile(sender:UIButton!)
{
fileDownloader().download_zip(datastring, destination: path, name: naming, fileis: self.fileId)
}
(这只是重要的部分)
然后我将下载功能放在一个单独的 class 文件中,然后启动 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"
returns 错误:致命错误:在展开可选值时意外发现 nil。
有人可以帮忙吗?
结论
在 classed 之间创建通信时,两个提议的解决方案都有效,但我选择了通知解决方案,因为在我的情况下,我必须更新 UI 以及后台线程进程并使用协议没有按预期工作。已进行通信,但更新 UI 并非一直有效,即使在使用 dispatch_async 方法将更改推回主线程后也是如此。
使用通知系统很有帮助,因为它更易于实施、管理和用于 UI 修改。
FileViewController().downloadLbl.text = "downloaded"
是指"create new FileViewController, and set downloadLbl text".
您需要将文本设置为现有的 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)
}
编码愉快:)
在此代码中:
FileViewController().downloadLbl.text = "downloaded"
您正在创建一个新的 FileViewController
,而不是引用现有的。这个新的还没有标签,因为它的视图还没有建立。你引用 downloadLbl
,这是一个 UILabel!
。它是 nil
,所以您的应用程序崩溃了。
I have my download function inside a separate class file
这是一个很好的做法,但是让这个单独的 class 修改 UI 是一个不好的做法。相反,您应该编写一个 Swift protocol 来定义这些 class 是如何交互的。
一个简单的例子:
protocol MyAwesomeDownloadResponder : class {
func downloadFinished()
}
然后你可以在你的视图控制器中实现这个方法:
class FileViewController : UIViewController, MyAwesomeDownloadResponder {
@IBOutlet weak var downloadLbl: UILabel!
func downloadFinished() {
downloadLbl.text = "Downloaded"
}
}
在您的下载 class 中,存储对 responder
的引用,然后在下载完成时调用响应程序:
class Downloader {
weak var responder : MyAwesomeDownloadResponder?
init(responder : MyAwesomeDownloadResponder) {
self.responder = responder
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
responder?.downloadFinished()
}
}
如果您需要在这些 class 之间传递任何信息,请在 protocol
.
中定义它
我有一个 viewController,带有一个按钮,允许用户从 url 下载文件。 为了保持我的代码干净,我创建了一个下载 class,我从我的视图中调用它。它运行良好,但现在我想为用户提供一些有关下载的 UI 提示。
假设我有一个标签,我想在下载结束后将其文本更改为 "Downloaded"。应该怎么做?
这是我的代码:
文件视图控制器
@IBOutlet weak var downloadLbl: UILabel!
func downloadFile(sender:UIButton!)
{
fileDownloader().download_zip(datastring, destination: path, name: naming, fileis: self.fileId)
}
(这只是重要的部分)
然后我将下载功能放在一个单独的 class 文件中,然后启动 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"
returns 错误:致命错误:在展开可选值时意外发现 nil。
有人可以帮忙吗?
结论
在 classed 之间创建通信时,两个提议的解决方案都有效,但我选择了通知解决方案,因为在我的情况下,我必须更新 UI 以及后台线程进程并使用协议没有按预期工作。已进行通信,但更新 UI 并非一直有效,即使在使用 dispatch_async 方法将更改推回主线程后也是如此。
使用通知系统很有帮助,因为它更易于实施、管理和用于 UI 修改。
FileViewController().downloadLbl.text = "downloaded"
是指"create new FileViewController, and set downloadLbl text".
您需要将文本设置为现有的 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)
}
编码愉快:)
在此代码中:
FileViewController().downloadLbl.text = "downloaded"
您正在创建一个新的 FileViewController
,而不是引用现有的。这个新的还没有标签,因为它的视图还没有建立。你引用 downloadLbl
,这是一个 UILabel!
。它是 nil
,所以您的应用程序崩溃了。
I have my download function inside a separate class file
这是一个很好的做法,但是让这个单独的 class 修改 UI 是一个不好的做法。相反,您应该编写一个 Swift protocol 来定义这些 class 是如何交互的。
一个简单的例子:
protocol MyAwesomeDownloadResponder : class {
func downloadFinished()
}
然后你可以在你的视图控制器中实现这个方法:
class FileViewController : UIViewController, MyAwesomeDownloadResponder {
@IBOutlet weak var downloadLbl: UILabel!
func downloadFinished() {
downloadLbl.text = "Downloaded"
}
}
在您的下载 class 中,存储对 responder
的引用,然后在下载完成时调用响应程序:
class Downloader {
weak var responder : MyAwesomeDownloadResponder?
init(responder : MyAwesomeDownloadResponder) {
self.responder = responder
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
responder?.downloadFinished()
}
}
如果您需要在这些 class 之间传递任何信息,请在 protocol
.