Xcode - iOS - AWS S3 - 下载的图像不会出现在首次下载中

时间:2015-07-07 06:28:39

标签: ios iphone amazon-web-services amazon-s3 server

以下是我用于从AWS S3服务器下载图像并将其指定为图像视图中显示的图像的代码:

    let s3BucketName = "bucketName"
    let fileName = Globals.currAuthorName.filter { $0 != Character(" ") } + ".jpg"

    let downloadFilePath = NSTemporaryDirectory().stringByAppendingPathComponent(fileName)
    let downloadingFileURL = NSURL.fileURLWithPath(downloadFilePath)

    // Create a credential provider for AWS requests
    let credentialsProvider = AWSCognitoCredentialsProvider(
        regionType: AWSRegionType.USEast1,
        identityPoolId: "us-east-1:********-****-****-****-************")

    // Create a service configuration for AWS requests
    let defaultServiceConfiguration = AWSServiceConfiguration(
        region: AWSRegionType.USEast1,
        credentialsProvider: credentialsProvider)

    // Create a new download request to S3, and set its properties
    AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration

    let downloadRequest = AWSS3TransferManagerDownloadRequest()
    downloadRequest.bucket = s3BucketName
    downloadRequest.key  = "folderName/" + fileName
    downloadRequest.downloadingFileURL = downloadingFileURL

    let transferManager = AWSS3TransferManager.defaultS3TransferManager()
    transferManager.download(downloadRequest)

    // Set the UIImageView to show the file that was downloaded
    let image = UIImage(contentsOfFile: downloadFilePath)
    authorImage.contentMode = UIViewContentMode.ScaleAspectFit
    authorImage.image = image

问题是,当我运行iOS模拟器并导航到相应的页面时,我第一次访问页面时从不加载图像。但是,当我离开页面然后返回页面时,它总是被加载,并且每次我访问页面时都会加载。当我停止运行应用程序然后再次启动它并再次访问该页面时,图像仍然加载。我第一次访问某个iOS模拟器的页面时才会加载图像(即它在iPhone 6模拟器,iPhone 5模拟器等中发生一次)

我尝试通过添加这段代码来解决问题:

while (image == nil) {
  transferManager.download(downloadRequest)
  let image = UIImage(contentsOfFile: downloadFilePath)
}

但这只是在我第一次访问该页面时导致无限循环。控制台最终也输出了这个错误:

  

2015-07-06 23:26:28.529 CCBF [19839:92323] 19839:CFNetwork内部错误(0xc01a:/SourceCache/CFNetwork_Sim/CFNetwork-711.3.18/Foundation/NSURLRequest.mm:798)   2015-07-06 23:26:28.564 AuthorProject [19839:92323] AWSiOSSDKv2 [错误] AWSURLSessionManager.m行:240 | __41- [AWSURLSessionManager taskWithDelegate:] _ block_invoke222 | AWSURLSessionTaskType无效。

修改

我尝试实现以下continuewithblock:

var image : UIImage!

let task = transferManager.download(downloadRequest)
task.continueWithBlock({
    if task.error != nil {
        println(task.error)
    } else {
        dispatch_async(dispatch_get_main_queue(), {
            image = UIImage(contentsOfFile: downloadFilePath)
            self.authorImage.contentMode = UIViewContentMode.ScaleAspectFit
            self.authorImage.image = image
        })
    }
    return nil
}())

但是,当我运行它并尝试加载图像时,我收到一个运行时错误,指向我的#34; continueWithExecutor"方法。具体来说,代码行:

result = block(self);

消息为:

  

EXC_BAD_ACCESS(代码:1,地址= 0x10)

EDIT2:

我似乎找到了一个有效的解决方案:

var image : UIImage!

    let taskTODO = transferManager.download(downloadRequest)
    taskTODO.continueWithBlock{ (task: AWSTask!) -> AnyObject! in
        if task.error != nil {
            println(task.error)
        } else {
            dispatch_async(dispatch_get_main_queue(), {
                image = UIImage(contentsOfFile: downloadFilePath)
                self.authorImage.contentMode = UIViewContentMode.ScaleAspectFit
                self.authorImage.image = image
            })
        }

        return nil
    }

这看起来是正确的方法吗?

1 个答案:

答案 0 :(得分:1)

transferManager.download(downloadRequest)是异步的,这意味着下载图像大约需要20毫秒。但是,第一次进入屏幕时,您尝试立即分配图像(尚未下载)。在随后的屏幕加载中 - 图像已经下载并缓存 - 因此它可以立即显示,。你需要的是一个完成块,它指示图像何时完成下载并准备好显示,在那个块中你应该分配图像。见下面的例子:

let readRequest1 : AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest()
    readRequest1.bucket = "shrikar-picbucket"
    readRequest1.key =  "bingo"
    readRequest1.downloadingFileURL = downloadingFileURL1

    let task = transferManager.download(readRequest1)
    task.continueWithBlock { (task) ->; AnyObject! in
        println(task.error)
        if task.error != nil {
        } else {
            dispatch_async(dispatch_get_main_queue()
                , { () ->; Void in
                    self.selectedImage.image = UIImage(contentsOfFile: downloadingFilePath1)
                    self.selectedImage.setNeedsDisplay()
                    self.selectedImage.reloadInputViews()

            })
            println("Fetched image")
        }
        return nil
    }