在不同视图中使用操作时出现延迟

时间:2015-06-29 01:54:54

标签: ios multithreading swift afnetworking

我正在开发一个医疗应用程序,解释一些医学术语及其细节。我必须处理下载图像和一些音频文件的几个操作。我有两个类来分别处理图像下载和音频下载的网络操作和缓存操作。我使用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 ()

1 个答案:

答案 0 :(得分:1)

如果您要创建一系列图像下载操作,然后想创建一个视频下载操作,您不希望积压作为图像下载,请记住以下几点:

  • 使用NSURLConnection,您会受到实际同时执行的请求的限制(5,我相信)。

  • 您正在手动调用start进行操作。因此,您既没有利用(a)限制正在运行的并发操作数量的能力; (b)个别业务的优先级,依赖性和服务质量。

基本思想是使用操作队列和操作属性来指示与操作运行时相关的行为。

因此,我建议您不要再调用start,而是将操作添加到您创建的队列中。您可以创建一个图像下载队列({3})的maxConcurrentOperationCount和单独的视频下载队列。因此,NSURLConnection一次不会运行超过3个图像下载请求,因此您可以同时运行视频下载,而不是等待图像下载。

另一种方法是拥有一个通用下载队列,可能使用4或5的maxConcurrentOperationCount,当您创建图像和视频下载时,为视频操作提供更高的优先级/ QoS。