我正在开发一个医疗应用程序,解释一些医学术语及其细节。我必须处理下载图像和一些音频文件的几个操作。我有两个类来分别处理图像下载和音频下载的网络操作和缓存操作。我使用AFNetworking来处理所有操作,我正在使用Swift。该场景是在应用程序启动时,我调用图像类的func来下载所有图像,并在相应的viewcontroller上查看术语详细信息,我可以选择播放音频文件(如果可用)。但是,如果我点击播放按钮,则仅在下载了从应用程序代表处理的所有图像(例如: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 :(得分:1)
如果您要创建一系列图像下载操作,然后想创建一个视频下载操作,您不希望积压作为图像下载,请记住以下几点:
使用NSURLConnection
,您会受到实际同时执行的请求的限制(5,我相信)。
您正在手动调用start
进行操作。因此,您既没有利用(a)限制正在运行的并发操作数量的能力; (b)个别业务的优先级,依赖性和服务质量。
基本思想是使用操作队列和操作属性来指示与操作运行时相关的行为。
因此,我建议您不要再调用start
,而是将操作添加到您创建的队列中。您可以创建一个图像下载队列({3})的maxConcurrentOperationCount
和单独的视频下载队列。因此,NSURLConnection
一次不会运行超过3个图像下载请求,因此您可以同时运行视频下载,而不是等待图像下载。
另一种方法是拥有一个通用下载队列,可能使用4或5的maxConcurrentOperationCount
,当您创建图像和视频下载时,为视频操作提供更高的优先级/ QoS。