Downloading UIImage via AlamofireImage? [duplicate] - ios

This question already has answers here:
How can I get the Data from NSURLSession.sharedSession().dataTaskWithRequest
(2 answers)
Closed 5 years ago.
I have a URL and want to download the image via a return function, however I cant get it to cooperate properly, here is my func:
func getTabImage(url: URL) -> UIImage {
Alamofire.request(url)
.responseImage { response in
if let image = response.result.value {
return image
} else {
print("Failed to get image")
}
}
}
I pass in the URL, and want a UIImage returned from the alamofire response.
But i get
Unexpected non-void return value in void function
for the return statement.
How can i achieve this correctly?

You can use the below function for downloading the image:
func getImage(_ url:String,handler: #escaping (UIImage?)->Void) {
print(url)
Alamofire.request(url, method: .get).responseImage { response in
if let data = response.result.value {
handler(data)
} else {
handler(nil)
}
}
}
Uses
getImage("http://") { (image) in
if image != nil {
print(image)
}
}
Or
If you want to set the image on UIImageView use extension of AlamofireImage.
if let imageURL = URL(string: "http://"), let placeholder = UIImage(named: "default") {
imageView.af_setImage(withURL: imageURL, placeholderImage: placeholder) //set image automatically when download compelete.
}

Related

LPLinkView Hide Info View

I am working on project with different files (video, photo, links) so we are going to use LPLinkView to present it directly from url like following image
So please if there is anyway to hide the footer view that include metadata (title, text, url) and only keep the preview?
If not can't you suggest me any library that do what we want?
Looking to here from your side
Thanks
You can't manage any internal properties of a LPLinkView, but you can use LPLinkMetadata instead and extract the images from its imageProvider.
So, you can create your own function to get the image from the imageProvider
import LinkPresentation
import UIKit
func getImageFromMetadata(url: URL, completion: #escaping (UIImage)-> Void) {
LPMetadataProvider().startFetchingMetadata(for: url) { (linkMetadata, error) in
guard let linkMetadata = linkMetadata, let imageProvider = linkMetadata.imageProvider else { return }
imageProvider.loadObject(ofClass: UIImage.self) { (image, error) in
guard error == nil else {
print("provider error")
return
}
if let image = image as? UIImage {
// now you can do whatever you want with the image.
// for we now are going to send it to the completion handler
DispatchQueue.main.async {
completion(image)
}
} else {
print("image not found")
}
}
}
}
Now you can use the function to load the image to your UIImageView
guard let url = URL(string: "https://www.youtube.com/watch?v=-YyeaaDOWho") else { return }
getImageFromMetadata(url: url) { image in
imageView.image = image
}

How i can see the image inside UIImageView?

I have an array filled with parsed json data including image url's. But when i try to see that images inside uiimageview, it doesn't the show. What should i do
I printed the url. This is my url inside array.
This is my array
var feedResult = [Result]()
It shows the name inside collectionview but i couldn't see the images. I used named like everybody does. But what is missing?
let info = feedResult[indexPath.row]
cell.appLabel.text = info.artistName
cell.customCollectionImage.image = UIImage(named: info.artWorkUrl)
You have to download the image Data using the url you got, only then you will use the downloaded data, like so:
imageView.image = UIImage(data: downloadedData)
Here is a quick subclass of UIImageView that does the downloading:
class URLImageView: UIImageView {
func download(url urlString: String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { (downloadedData, _, error) in
guard error == nil && downloadedData != nil else { return }
DispatchQueue.main.async{
self.image = UIImage(data: downloadedData!)
}
}
task.resume()
}
}
Update-1 Use the download function using UIImageView extension, without subclassing, like so:
extension UIImageView {
func download(url urlString: String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { (downloadedData, _, error) in
guard error == nil && downloadedData != nil else { return }
DispatchQueue.main.async{
self.image = UIImage(data: downloadedData!)
}
}
task.resume()
}
}
Usage:
cell.customCollectionImage.download(url: info.artWorkUrl)
By using UIImage(named: info.artWorkUrl) you are not accessing the image in your array but the images in your Assets.xcassets (assets that you add manually in your project).
You need to download the image from the artWorkUrl and then directly use the downloaded image like this:
cell.customCollectionImage.image = UIImage(data: yourImageData)
Where yourImageData is what you have downloaded from the server with the artWorkUrl.

Function doesnt wait download Picture with Alamofire in Swift

I try to download picture with Alamofire and this image must be append to custom class. But I didnt do that. Image is downloaded with async and i didnt fix this issue. Where is my mistake ?
Image always return nil
// MARK: CUSTOM FUNCTION
import UIKit
import Alamofire
import AlamofireImage
class DownloadPhotoWAlamofire {
func download(imageUid:String , completion : #escaping (UIImage) -> () ) {
let url = "\(Config.fileService)file?uid=\(String(describing: imageUid))"
print("URL \(url)")
Alamofire.request(url, method: .get ).responseImage { response in
print("Image Response \(response)")
let image = response.result.value
completion(image!)
}
}
}
// MARK : IN VIEWCONTROL
guard let objectElement = o as? [String:Any] else {return}
let managerName = objectElement["managerName"] as? String
let managerAvatarUid = objectElement["managerProfilePictureFileUid"] as? String
let assistantsOfDiariesUid = objectElement["assistantsOfDiariesUid"] as? String
var image:UIImage? = nil
if managerAvatarUid != nil {
DownloadPhotoWAlamofire().download(imageUid: managerAvatarUid!, completion: { (imageD) in
image = imageD
})
}
let e = AssistantInviteElement(managerName: managerName!, managerAvatarUid: managerAvatarUid, assistantsOfDiariesUid: assistantsOfDiariesUid!,avatarImage:image)
self.managerList.append(e)
Change it to :
if managerAvatarUid != nil {
DownloadPhotoWAlamofire().download(imageUid: managerAvatarUid!, completion: { (imageD) in
let image = imageD
let e = AssistantInviteElement(managerName: managerName!, managerAvatarUid: managerAvatarUid, assistantsOfDiariesUid: assistantsOfDiariesUid!,avatarImage:image)
self.managerList.append(e)
})
}
As downloading is asynchronous call and you this line is executing before image is downloaded :
let e = AssistantInviteElement(managerName: managerName!, managerAvatarUid: managerAvatarUid, assistantsOfDiariesUid: assistantsOfDiariesUid!,avatarImage:image)
at that time image is nil. So call it only when you have image downloaded and it should work.
Also don't unwrap optional with "!", do a if let/ guard let. So change Almofire code to :
Alamofire.request(url, method: .get ).responseImage { response in
print("Image Response \(response)")
if let image = response.result.value {
print("image downloaded: \(image)")
completion(image)
} else {
print("Image is nil")
}
}
You set the image directly after starting the asynchronous download, when it of course is still nil. The point of using a callback as you do in your code is that you only can use a requested resource once the callback gets called; so you should move the code that's using the image into the callback block.

Add an image as an accessory in your UITableView in Swift 3

In my project, I show a UITableView, which currently has text describing a show's name and genre loading from a remote JSON file.
That all works. What I want next is to use the URL from the JSON file and load a thumbnail next to each show.
Using a tutorial, I have added a function to download the remote image with a print to test if it's successful.
if let shows_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let shows_obj = shows_list[i] as? NSDictionary
{
let show_name = shows_obj["show"] as? String
let show_genre = shows_obj["genre"] as? String
let show_image = shows_obj["thumbnail"] as? String
TableData.append(show_name! + " | " + show_genre!)
let testPictureURL = URL(string: show_image!)!
let session = URLSession(configuration: .default)
// Here's the download task where I'm grabbing the image
let downloadPicTask = session.dataTask(with: testPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
if let res = response as? HTTPURLResponse {
print("Downloaded picture with response code \(res.statusCode)")
if let imageData = data {
// Now I know I have data, so I think I can use UIImage to convert it into an image
let image = UIImage(data: imageData)
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
There are three items in the JSON array, and I get three printed statements that the picture was download: but the image does not appear.
My theory: since this is a table, maybe I have to add this as an accessory, but there isn't an image accessory subclass.
I am new to Swift -- do you have any ideas about how I should append this uploaded image to the table.
This is probably being caused by the asynchronous behavior of URLSession so when the requested image returns the view is already loaded.
To solve that, you can use a callback, for instance:
func myFunction(completion: (returnedImage -> UIIMage) -> Void){
//...
let downloadPicTask = session.dataTask(with: testPictureURL) { (data, response, error) in
//...
let image = UIImage(data: imageData)
completion(returnedImage: image)
//...
}
downloadPicTask.resume()
}
}
By using a callback, let's say that you have a method called myFunction(completion:), so now when you call the method you can handle whatever comes back from completion:
myFunction { (image) in
DispatchQueue.main.async { cell.imageView.image = image }
}

how to bind local image to the image view using ReactiveKit?

For fetching image from server I have done this
// fetch image from server
func fetchImage(url: NSURL) -> Operation<UIImage, NSError> {
return Operation { observer in
// use almofire to deal with server request
let request = Alamofire.request(.GET, url).response { request, response, data, error in
// if error occurs then abort the operation
if let error = error {
observer.failure(error)
} else {
// if doesnt occurs error then convert imageData back to image
if(data != nil)
{
observer.next(UIImage(data : data!)!)
observer.success()
}
}
}
// if response is nil then execute this block
return BlockDisposable {
request.cancel()
}
}
}
& then bind it to the image view
if (url != nil)
{
let image : ObservableBuffer<UIImage>? = self.fetchImage(url!).shareNext()
if ((image) != nil)
{
image!.bindTo(customCellObj.mContentCellImageView)
}
}
Here I am fetching image from url using almofire. Is there any way by which I can bind local DB image with an image view directly using reactive kit?
Here is how you connect an imageView to your stream:
Stream.just(NSURL(string: "https://exoticcars.enterprise.com/etc/designs/exotics/clientlibs/dist/img/homepage/Homepage-Hero-Car.png")!)
.flatMapLatest(fetchImage)
.flatMapError { _ in return Stream.just(UIImage()) }
.observeNext { [weak self] image in self?.imageView.image = image }
.disposeIn(bag)
However, at the risk of sounding way too obvious... That's what ReactiveUIKit is for.
Stream.just(NSURL(string: "https://exoticcars.enterprise.com/etc/designs/exotics/clientlibs/dist/img/homepage/Homepage-Hero-Car.png")!)
.flatMapLatest(fetchImage)
.flatMapError { _ in return Stream.just(UIImage()) }
.bindTo(imageView.rImage)
.disposeIn(bag)
Also there is an Alamofire extension to ReactiveKit (AlamofireReactive) that you might find useful.

Resources