Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

af_setImage doesn't work well with iOS 13 #370

Closed
fabios9702 opened this issue Aug 12, 2019 · 28 comments
Closed

af_setImage doesn't work well with iOS 13 #370

fabios9702 opened this issue Aug 12, 2019 · 28 comments

Comments

@fabios9702
Copy link

fabios9702 commented Aug 12, 2019

What did you do?

I'm having problems with Alamofire image with iOS 13, some images are loaded and placed, but other not. Is this a known problem with iOS 13? How can I fix it?

Alamofire Environment

**Alamofire version: 4.8.2
**Alamofire Image version: 3.5.2
**Xcode version: 11
**Swift version: 4
**Platform(s) running AlamofireImage: iOS 13
macOS version running Xcode:

Demo Project

ℹ Please link to or upload a project we can download that reproduces the issue.

@Tequilag
Copy link

Same problem
**Alamofire version: 4.8.2
**AlamofireImage version: 3.5.0
**Xcode version: 11
**Swift version: 5
**Platform(s) running AlamofireImage: iOS 13

@albertolina
Copy link

Same problem. iOS 13 is releasing in a couple of weeks and our app is totally unusable due to this issue. We either need to stop using AlamofireImage or someone needs to give us more info.

Thank you very much

**Alamofire version: 4.8.2
**Alamofire Image version: 3.5.2
**Xcode version: 11
**Swift version: 4
**Platform(s) running AlamofireImage: iOS 13

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

All of our tests and demo project are working fine on iOS 13, so please provide additional information and, most helpfully, a demo project that reproduces the issue in the simulator.

This includes:

  • Any errors seen.
  • Kinds of images which sometimes don't load.
  • Any customizations you've made to the default ImageDownloader instance.
  • Code samples showing how you use af_setImage.

You should also be retesting on the new betas as you go, as this year's beta process has been particularly buggy.

@fabios9702
Copy link
Author

Are you testing with iOS 13 SDK? Because the App developed for iOS 13 in Xcode 11 doesn't work well with Alamofire, instead, the same app that is already on the store for iOS 11 or superior, works fine.
We've have not customised the ImageDownloader istance;

sample of code using af_setImage:
imageToPlace.af_setImage(withURL: URL(string: artworkImage)!)

The images are all .jpg or .png, furthermore there are no errors or warnings. There isn't a rule that make the images not loading, for example, sometimes it doesn't load the heavy images and sometimes it doesn't load the lights images.
We've have also checked the urls that are passed to af_setImage and they are valid

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Yes, the testing was performed with Xcode 11 beta 6 on the iOS 13 simulator.

If you could perform some investigation on your side to narrow down why images might not be showing up, we could think investigate a fix. It could be a few things:

  • It's not actually downloading the image.
  • The image is downloaded, but is never rendered.
  • It's rendered but never appears in the image view.

Answering those questions would help narrow down a fix.

@fabios9702
Copy link
Author

I've tried and I found that this part of code in the af_setImage function is never called

 // Generate a unique download id to check whether the active request has changed while downloading
        let downloadID = UUID().uuidString

        // Download the image, then run the image transition or completion handler
        let requestReceipt = imageDownloader.download(
            urlRequest,
            receiptID: downloadID,
            filter: filter,
            progress: progress,
            progressQueue: progressQueue,
            completion: { [weak self] response in
                guard
                    let strongSelf = self,
                    strongSelf.isURLRequestURLEqualToActiveRequestURL(response.request) &&
                    strongSelf.af_activeRequestReceipt?.receiptID == downloadID
                else {
                    completion?(response)
                    return
                }

                if let image = response.result.value {
                    strongSelf.run(imageTransition, with: image)
                }

                strongSelf.af_activeRequestReceipt = nil

                completion?(response)
            }
        )

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Where does it return before then? From the initial guard, or the cache check?

@fabios9702
Copy link
Author

sometimes, after let downloadID = UUID().uuidString, it goes directly to af_activeRequestReceipt = requestReceipt, sometimes it stops at let downloadID = UUID().uuidString without returning anything

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

That doesn't make much sense. Are you building with optimization?

@fabios9702
Copy link
Author

fabios9702 commented Aug 22, 2019

yes, it's set on Optimize for speed [-O]

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Please turn that off and test again, as it prevent breakpoints from working correctly.

@fabios9702
Copy link
Author

I turnet all the optimizations to No Optimization, but it doesn't work anyway

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Right, but you should now be able to trace the path more accurately.

@fabios9702
Copy link
Author

ok, now it enter in the code and the response.result.value is nil, so it doesn't run strongSelf.run(imageTransition, with: image)

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Right. You should be able to check the response in that closure and make sure it has the appropriate response code, data, etc.

@fabios9702
Copy link
Author

if I do a po response when I put the breakpoint the result is

error: Couldn't materialize: can't get size of type
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

Yes, you must turn off optimizations for debugging to work correctly.

@fabios9702
Copy link
Author

it's off

@jshier
Copy link
Contributor

jshier commented Aug 22, 2019

There are other settings that can interfere with debugging. At this point this doesn't look like an AlamofireImage bug. Please continue debugging until you discover the cause, and if it is a bug, please comment and I can reopen the issue.

@jshier jshier closed this as completed Aug 22, 2019
@ckakei
Copy link

ckakei commented Sep 20, 2019

In my case, I add support to the "application/octet-stream" into the acceptableImageContentTypes fix my problem

DataRequest.addAcceptableImageContentTypes(["application/octet-stream"])

In iOS 13 Release note have the following statement:

To enhance security, URLSession no longer sniffs the MIME type when the server sends Content-Type: application/octet-stream. (7820658)

https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes

@tomeron11
Copy link

tomeron11 commented Sep 22, 2019

Hi
also have the same problem. the af_setImage cause my app to crash.
in xcode 10 it worked fine. version from the store works great on ios13.
in xcode11 (official) it crashes. (phone and simulator).
the debugger points on
public static func af_threadSafeImage(with data: Data, scale: CGFloat) -> UIImage? {
lock.lock()
let image = UIImage(data: data, scale: scale)
lock.unlock()
return image
}

and in the console i see
seek:285: *** IIOScanner::seek reached EOF
getVal16:139: *** IIOScanner::getVal16 reached EOF

i tried the octet-stream from previous comment. didn't help

@carlosh
Copy link

carlosh commented Nov 5, 2019

In my case, I add support to the "application/octet-stream" into the acceptableImageContentTypes fix my problem

DataRequest.addAcceptableImageContentTypes(["application/octet-stream"])

In iOS 13 Release note have the following statement:

To enhance security, URLSession no longer sniffs the MIME type when the server sends Content-Type: application/octet-stream. (7820658)

https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes

I found myself having this issue when I recently upgraded to Xcode 11. I can confirm the above was the actual issue, and adding the image content type fixed it for me. Not sure if ImageDownloader should have a default configuration for this, or the developer should always need to add this image content type. Either way, I feel it should be explained in the readme file. Thanks.

@objectivecosta
Copy link
Contributor

@jshier Hey, I believe @carlosh is right... can you reopen the issue?

@cnoon
Copy link
Member

cnoon commented Feb 22, 2020

We've added the application/octet-stream content type in f48f8cf. It will be released shortly as part of AFI 4.0.0.

Cheers. 🍻

@ReflectCode
Copy link

This is just for record and may help other developers in future.
The AWS S3 server we were connecting to download images was sending content type "image/*" and AF was throwing error.
We could get around this problem by using 'ImageResponseSerializer' :

 var imgSer = ImageResponseSerializer.self
        imgSer.addAcceptableImageContentTypes(Set(arrayLiteral: "image/*"))
        mView!.af.setImage( withURL: url, 
                placeholderImage: mPlaceholderImage, 
                **serializer: imgSer.init()**, 
                filter: self, 
                progress: nil,  imageTransition: imgTransition!, runImageTransitionIfCached: true, completion: { dr in  .....

AlamofireImage (3.6.0), Alamofire (4.9.1)

@shreyadc
Copy link

I faced this issue(even in iOS 15, AlamofireImage 4.2.0). I was using af.setImage to download and set images. The images were perfectly downloading from every url, other than the images in aws s3 bucket. The s3 bucket images weren't downloading and displaying properly.
After much debugging, I see that following are the acceptable content types in AFI.
acceptableContentTypes: ["application/octet-stream", "image/bmp", "image/gif", "image/heic", "image/heif", "image/ico", "image/jp2", "image/jpeg", "image/jpg", "image/png", "image/tiff", "image/webp", "image/x-bmp", "image/x-icon", "image/x-ms-bmp", "image/x-win-bitmap", "image/x-xbitmap"]

But the images in s3 have response content type "binary/octet-stream", so although the images are downloading perfectly and can be further retrieved from response data, they're getting AlamofireImage.AFIError.alamofireError(Alamofire.AFError.responseValidationFailed(reason: Alamofire.AFError.ResponseValidationFailureReason.unacceptableContentType(..)) and so they are unable to set in the imageview.

AFAIK AFI should include "binary/octet-stream" in the acceptable content-type as well!

@keegho
Copy link

keegho commented Jan 24, 2022

@shreyadc

Yes had same issue and I solved it this way

import AlamofireImage    

ImageResponseSerializer.addAcceptableImageContentTypes(["binary/octet-stream"])

@jshier
Copy link
Contributor

jshier commented Jan 24, 2022

AlamofireImage 4.2.0 should have both application/octet-stream and image/jpg in the default Accept header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests