我的應用程序需要從應用程序的幾個不同位置下載我的網站上的文件,因此編寫函數以完成下載一次,將其放入其自己的類並從每個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