我的应用程序需要从应用程序的几个不同位置下载我的网站上的文件,因此编写函数以完成下载一次,将其放入其自己的类并从每个ViewController调用该函数似乎是有意义的。到目前为止,很好,一切正常。正在下载,正确地下载了文件print
。从多个视图控制器调用文件下载功能;如何将结果返回给那些VC的?
问题出现在下载函数发送一个“成功”或“失败”消息返回给调用它的ViewController时,以便VC可以做出相应的反应 - 更新显示,关闭下载对话框, 随你。如何做到这一点是我卡住的地方。
我有什么:
每个ViewControllerTwo和ViewControllerThree(这是相同的,现在,除了要求从我的服务器不同的文件除外)的调用下载功能这样的:
Downloader.load(url: urlForFileA!, to: localDestinationFileA, callingViewControllerNumber: 2)
的代码下载器功能(目前同步,但最终会变成异步)看起来像这样(在其自己的Downloader
类中):
class func load(url: URL, to localUrl: URL, callingViewControllerNumber: Int) {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Got a file, might be a 404 page...
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Success downloading: \(statusCode)")
if statusCode == 404 {
// ERROR -- FILE NOT FOUND ON SERVER
returnToCaller(sourceIdent: callingViewControllerNumber, successStatus: .fileNotFound, errorMessage: "File not Found, 404 error")
}
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: localUrl)
// SUCCESS!
returnToCaller(sourceIdent: callingViewControllerNumber, successStatus: .success, errorMessage: "")
} catch (let writeError) {
returnToCaller(sourceIdent: callingViewControllerNumber, successStatus: .movingError, errorMessage: "\(writeError)")
}
} else {
returnToCaller(sourceIdent: callingViewControllerNumber, successStatus: .downloadFailed, errorMessage: "Grave Unexplained Failure")
}
}
task.resume()
}
这部分工作。
的returnToCaller
功能是不可否认的难看的(好吧,非常非常丑陋的)的方式来送东西回调用视图控制器:
class func returnToCaller(sourceIdent : Int, successStatus : downloadSuccessStatusEnum, errorMessage : String) {
switch sourceIdent {
case 2:
ViewControllerTwo().returnFromDownload(successStatus: successStatus, errorMessage: errorMessage)
case 3:
ViewControllerThree().returnFromDownload(successStatus: successStatus, errorMessage: errorMessage)
default:
fatalError("Unknown sourceIdent of \(sourceIdent) passed to func returnToCaller")
}
}
的问题是,当returnFromDownload
功能在原来的ViewController被调用,它不知道VC中加载的任何东西 - 我去改变标签的背景颜色,并得到运行时错误,标签为nil
。这个标签存在,但是这个对ViewController代码的调用与正在运行的,实例化的VC本身隔离。 (可能是那里的错误词汇 - 道歉。)代码运行并且可以print
,但在与视图本身中的任何内容进行交互时出错。
我对此的处理越多,我就越不自信,我在这里的正确轨道上,而我对Swift的有限经验还不足以看到需要发生什么,以便下载功能可以做到所有的工作“在这里”,然后向调用的VC返回成功/失败消息,以便VC可以使用它。
This question似乎在问类似的东西;那里的一个答案并没有解决我如何在提交的VC中获取代码的根本问题,这个问题再次发生在VC之外发生的结果(经理批准他的情况下,我的下载) 。
不要求我的代码被重写(除非它是一个快速修复),但需要指向正确的方向。非常感谢!
如果我正确地阅读这篇文章,您希望 - 当天回来 - 被称为“松散耦合”代码。在Swift之前的日子里,另一个名字可能是KVC编码。基本上,你想尝试下载*异步*,并将结果发回给调用它的VC。至少有两种方法可以想到。 (1)可能最正确的方法是将观察者添加到默认NSNotificationCenter(http://stackoverflow.com/questions/24049020/nsnotificationcenter-addobserver-in-swift)。 (2)另一种方式 - 不太优雅,但它可能完成工作 - 是使用UIButton的sendAction方法。 – dfd