2015-06-29 54 views
0

我正在研究解釋一些醫療術語及其細節的醫療應用程序。我必須處理幾個操作以下載圖像和一些音頻文件。我有兩個類分別處理圖像下載和音頻下載的網絡操作和緩存操作。我已經使用AFNetworking來處理所有的操作,我正在使用Swift。該場景是在應用程序啓動時,我打電話給圖像類的函數來下載所有圖像,並在各自的視圖控制器上查看術語詳細信息,我可以選擇播放音頻文件(如果可用)。但是,如果我點擊播放按鈕,只有在下載了從應用程序代理處理的所有圖像(例如:20張圖像)後纔會下載音頻。在不同視圖中使用操作時的延遲

import UIKit 

let ImageFileDirectory : String = "Image-cache" 

typealias ImageDownloadCallBackSuccess = (String , UIImage) -> Void 

class ImageManager: NSObject {  

override init() { 
    super.init() 
} 



func downloadImageFile (imageData : Dictionary<String,AnyObject>, callback: ImageDownloadCallBackSuccess) -> Void { 

    let imageUrl : NSString = (imageData as NSDictionary).objectForKey("url") as! NSString 

    let imageId : Int = (imageData as NSDictionary).objectForKey("id") as! Int 

    let imageIDString : String = String(imageId) 

    let filemanager = NSFileManager.defaultManager() 

    if !filemanager.fileExistsAtPath(filePath(imageIDString)) { 


     var opManager : AFHTTPRequestOperationManager = AFHTTPRequestOperationManager() 
     opManager.responseSerializer = AFImageResponseSerializer() 
     opManager.requestSerializer.timeoutInterval = 180.0 

     let newOperation = opManager.HTTPRequestOperationWithRequest(NSURLRequest(URL: NSURL(string: imageUrl)!), success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) -> Void in 
      println("File Saved to ImageCacheDirectory") 

      let imageData : NSData = UIImageJPEGRepresentation(responseObject as! UIImage, 1.0) 
      imageData.writeToFile(self.filePath(imageIDString), atomically: true) 

      callback(imageIDString, responseObject as! UIImage) 

      }, failure: { (operation: AFHTTPRequestOperation!,error: NSError!) -> Void in 
       println("Couldn't save the file to ImageCacheDirectory") 

     }) 
     newOperation.start() 

    } 
    else { 

     println("file exist for path") 
    } 
} 

class func filePathForImage (imageID: String) -> (String!) { 

    let documentsPath : String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0] as! String 

    let fileExtensionString = String(format:"/%@/", ImageFileDirectory) 
    let folderPath = documentsPath.stringByAppendingPathComponent("\(fileExtensionString)") 
    let filemanager = NSFileManager.defaultManager() 

    var err: NSErrorPointer = nil 

    if !filemanager.fileExistsAtPath(folderPath) { 

     filemanager.createDirectoryAtPath(folderPath, withIntermediateDirectories: true, attributes: nil, error: err) 
    } 

    var filePath = "\(folderPath)" 
    filePath += "/" 
    filePath += "\(imageID)" 
    filePath += "." 
    filePath += "jpg" 

    return filePath 
} 


func imageRootDirectory() -> String { 

    let documentsPath : String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0] as! String 

    let imageDirectory = String(format:"/%@/", ImageFileDirectory) 

    return documentsPath.stringByAppendingPathComponent("\(imageDirectory)") 
} 
func filePath (imageID :String) -> String { 

    let folderPath = imageRootDirectory() 

    var filePath = "\(folderPath)" 
    filePath += "/" 
    filePath += "\(imageID)" 
    filePath += "." 
    filePath += "jpg" 

    return filePath 

} 

func downloadAllImage() { 

    for imageObject in DataManager.sharedInstance.allImages { 

     downloadImageFile(imageObject, callback: { (imageString, imageData) -> Void in 
     }) 
    } 
} 
} 



typealias AudioDownloadHandler = (Double) -> Void 

let AudioFileDirectory : String = "Audio-cache" 

import UIKit 
import AVFoundation 

class AudioManager: NSObject ,AVAudioPlayerDelegate { 

var audioID : Int? 
var audioUrl : String? 

var audioPlayer : AVAudioPlayer! // will be Optional, must supply initializer 

override init() { 

    super.init() 

} 

init (audioId : Int , audioUrl: String) { 
    self.audioUrl = audioUrl 
    self.audioID = audioId 
    super.init() 

} 

func cacheAudioFile(callback:AudioDownloadHandler) -> Void { 

    let request: NSURLRequest = NSURLRequest(URL: NSURL(string: self.audioUrl!)!) 
    let audioDownloadOperation: AFHTTPRequestOperation = AFHTTPRequestOperation(request: request) 
    audioDownloadOperation.outputStream = NSOutputStream(toFileAtPath: filePathForAudio()!, append: false) 

    audioDownloadOperation.setDownloadProgressBlock({(bytesRead, totalBytesRead, totalBytesExpectedToRead) -> Void in 

     var total: CGFloat = CGFloat(totalBytesRead)/CGFloat(totalBytesExpectedToRead) 
     callback(Double(total)) 
    }) 
    audioDownloadOperation.start() 

} 

func filePathForAudio() -> (String!) { 

    let documentsPath : String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)[0] as! String 

    let fileExtensionString = String(format:"/%@/", AudioFileDirectory) 
    let folderPath = documentsPath.stringByAppendingPathComponent("\(fileExtensionString)") 
    let filemanager = NSFileManager.defaultManager() 

    var err: NSErrorPointer = nil 

    if !filemanager.fileExistsAtPath(folderPath) { 

     filemanager.createDirectoryAtPath(folderPath, withIntermediateDirectories: true, attributes: nil, error: err) 
    } 

    var filePath = "\(folderPath)" 
    filePath += "/" 
    filePath += "\(self.audioID!)" 
    filePath += "." 
    filePath += "\(self.audioUrl!.pathExtension)" 
    return filePath 
} 

func playAudioFile() { 

    var filePathUrl : NSURL = NSURL.fileURLWithPath(filePathForAudio())! 
    var error: NSError! 
    self.audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil) 
    self.audioPlayer.delegate = self 

    if let player : AVAudioPlayer = self.audioPlayer as AVAudioPlayer?{ 
     self.audioPlayer.prepareToPlay() 
     player.play() 

    } 
} 

func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) { 
    NSNotificationCenter.defaultCenter().postNotificationName("AudioFinishedPlaying", object: nil) 
} 
} 

      let imageManager = ImageManager() 
      imageManager.downloadAllImage() 
+0

那麼你的問題是什麼? –

+0

@DuncanC使用我的代碼進行操作管理有任何問題。 – Nassif

+0

無關,但我不會建議使用'AFImageResponseSerializer',然後使用'UIImageJPEGRepresentation'重新創建'NSData',以便(a)可能使其變大;和(b)在這個過程中可能丟失元數據。您可以通過查看操作的'responseData'屬性來獲得原始的'NSData'。或者使用標準的'AFHTTPResponseSerializer',然後將它自己轉換爲'UIImage'。無論哪種方式,請保存原始響應數據,而不是從圖像中重新提取。 – Rob

回答

1

如果要創建一堆圖像下載操作,然後要創建一個你不想積壓是圖像下載一個視頻下載操作,有幾個注意事項要牢記:

  • 使用NSURLConnection,你受到多少請求將被實際同時執行(我相信)的限制。

  • 您正在手動呼叫start進行操作。因此,你既沒有利用(a)約束有多少併發操作正在運行的能力; (b)各項業務的優先順序,依賴性和服務質量。

其基本思想是使用操作隊列和操作屬性來規定與操作運行時相關的行爲。

因此,我建議您不要再打start,而是將操作添加到創建的隊列中。您可以創建一個圖像下載隊列(帶有類似3的maxConcurrentOperationCount)和一個單獨的視頻下載隊列。因此,您的NSURLConnection因此一次不會運行超過3個圖像下載請求,因此您有能力同時運行視頻下載,而不是等待圖像下載。

另一種方法是擁有一個通用下載隊列,或許使用maxConcurrentOperationCount,4或5,並且當您創建圖像和視頻下載時,爲視頻操作提供更高的優先級/ QoS。