2015-06-29 2 views
0

Я работаю над медицинским приложением, которое объясняет некоторые медицинские термины и его детали. Мне приходится обрабатывать несколько операций по загрузке изображений и некоторых аудиофайлов. У меня есть два класса для обработки сетевых операций и операций кеша для загрузки изображений и загрузки аудио соответственно. Я использовал AFNetworking для обработки всех операций, и я использую Swift. Сценарий запускается при запуске приложения, я вызываю func класса изображения для загрузки всех изображений и на соответствующем диспетчере просмотра для просмотра подробностей термина, у меня есть возможность воспроизвести аудиофайл, если он доступен. Однако, если я нажимаю кнопку воспроизведения, звук загружается только после загрузки всех изображений (например, 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', который (а), вероятно, делает его больше; и (б), возможно, теряет метаданные в этом процессе. Вы можете получить оригинальную 'NSData', посмотрев на свойство' responseData' операции. Или используйте стандартный 'AFHTTPResponseSerializer', а затем конвертируйте его в' UIImage' самостоятельно. В любом случае сохраните исходные данные ответа, а не повторно извлеките его из изображения. – Rob

ответ

1

Если вы создаете кучу изображений загрузки операций, а затем хотите создать один видео скачать операцию, вы не хотите, накопившихся будучи загрузки изображений, Есть несколько соображений, чтобы иметь в виду:

  • Используя NSURLConnection, вы ограничены тем, сколько запросов будет выполняться одновременно (5, я считаю).

  • Вы вручную вызываете start на операции. Таким образом, вы не пользуетесь ни тем, ни другим (а) возможностью ограничить количество параллельных операций; ни (b) приоритет, зависимости и качество обслуживания отдельных операций.

Основная идея состоит в том, чтобы использовать операционные очереди и свойства работы, чтобы диктовать поведение, связанное с тем, когда выполняются операции.

Я бы поэтому предложил, чтобы вы больше не вызывали start и скорее добавляли операции в очереди вашего создания. Вы можете либо создать очередь загрузки изображений (с maxConcurrentOperationCount чего-то типа 3), так и отдельную очередь загрузки видео. Таким образом, ваш NSURLConnection не будет запускать более трех запросов загрузки изображений одновременно и, следовательно, вы сможете одновременно запускать загрузку видео, не дожидаясь загрузки изображений.

Другой подход состоит в том, чтобы иметь одну общую очередь загрузки, возможно, использовать maxConcurrentOperationCount 4 или 5, а когда вы создаете загрузку изображений и видео, придайте видео операции более высокий приоритет/качество обслуживания.

Смежные вопросы