Dowload image from Firebase - swift

Please help me. Explain how to set the image in the cell. In my Database I have: title, description and imageURL (url from Firebase Storage). Can you write me a code and explain.
class TrainingProgram
{
var description = ""
var title = ""
var imageURL = ""
init(description: String, title: String, imageURL: String) {
self.description = description
self.title = title
self.imageURL = imageURL
}
function to get data from firebase.
func fetchPrograms() {
Database.database().reference().child("programs").observe(.childAdded) { (snapshot) in
if let dict = snapshot.value as? [String: AnyObject] {
let newTitle = dict["title"] as! String
let newDescription = dict["description"] as! String
let newImageURL = dict["imageURL"] as! String
let trainingCell = TrainingProgram(description: newDescription, title: newTitle, imageURL: newImageURL)
self.trainingPrograms.append(trainingCell)
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
}
And this is how I set title and description to my cells.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
//cell.featuredImageView.setImage(from: indexPath.item)
cell.titleLabel.text = trainingPrograms[indexPath.item].title
cell.descriptionLabel.text = trainingPrograms[indexPath.item].description
What I need to write in the function for receiving data to get images and how to set images in cells

Install SDWebImage pod from this link https://github.com/SDWebImage
And in Your CollectioView cellForRow method
var images_list = [String]()
var imagesArray = [URL]()
images_list.append(itemModel[indexPath.row]. imageURL)
let storage = Storage.storage().reference()
for x in images_list{
print(x)
let storageRef = storage.child("images/\(x).jpg")
storageRef.downloadURL { (url, error) in
if let error = error{
print(error.localizedDescription)
}
else{
imagesArray.append(url!)
}
if let x = images_list.last{
cell.itemImage.sd_setImage(with: URL(string: x), placeholderImage: UIImage(named: "default"))
}
}
}
Full code
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TrainingProgramCollectionViewCell", for: indexPath) as! TrainingProgramCollectionViewCell
//cell.featuredImageView.setImage(from: indexPath.item)
cell.titleLabel.text = trainingPrograms[indexPath.item].title
cell.descriptionLabel.text = trainingPrograms[indexPath.item].description
var images_list = [String]()
var imagesArray = [URL]()
for x in images_list{
print(x)
let storageRef = storage.child("images/\(x).jpg")
storageRef.downloadURL { (url, error) in
if let error = error{
print(error.localizedDescription)
}
else{
imagesArray.append(url!)
}
if let x = images_list.last{
cell.itemImage.sd_setImage(with: URL(string: x), placeholderImage: UIImage(named: "default"))
}
}
}
}
Try this for single image downloadJust take your imageUrl from firebase
let x: String = "yourImageUrl"
let storageRef = storage.child("images/\(x).jpg")
storageRef.downloadURL { (url, error) in
if let error = error{
print(error.localizedDescription)
}
else{
imagesArray.append(url!)
}
if let x = images_list.last{
cell.itemImage.sd_setImage(with: URL(string: x), placeholderImage: UIImage(named: "default"))
}
}

Related

image not displaying on cell swift

I'm trying to pick an image and convert it to a string to save into the model var picture = "". I can select the image but it's not displaying any suggestions on my error will help.
UPDATE: I figured it out with these changes and still used a string for the model.
var imagePath = ""
var profilePic: UIImage?
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? URL, let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
ALAssetsLibrary().asset(for: referenceUrl, resultBlock: { asset in
let fileName = asset?.defaultRepresentation().filename()
let userModel = User()
userModel.picture = fileName!
let filePath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/\(String(describing: fileName))"
self.imagePath = filePath
let imageData : NSData = UIImagePNGRepresentation(pickedImage)! as NSData
imageData.write(toFile: filePath, atomically: true)
UserDefaults.standard.set(imageData, forKey: "profileImage")
UserDefaults.standard.synchronize()
self.profilePic = pickedImage
self.tableView.reloadData()
}, failureBlock: nil)
}
dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case Setting.preferences.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: PreferencesTableViewCell.identifier,
for: indexPath) as? PreferencesTableViewCell else { return UITableViewCell() }
cell.addressTextfield.delegate = self
cell.cityTextField.delegate = self
cell.stateTextField.delegate = self
cell.zipcodeTextField.delegate = self
return cell
case Setting.personal.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: PersonalTableViewCell.identifier,
for: indexPath) as? PersonalTableViewCell else { return UITableViewCell() }
cell.firstNameTextField.delegate = self
cell.lastNameTextField.delegate = self
cell.phoneNumberTextField.delegate = self
cell.emailTextField.delegate = self
cell.buttonTouchedClosure = { [weak self] in
self?.pickImage()
}
return cell
case Setting.notifications.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: NotificationsTableViewCell.identifier,
for: indexPath) as? NotificationsTableViewCell else { return UITableViewCell() }
return cell
case Setting.social.rawValue:
guard let cell = tableView.dequeueReusableCell(withIdentifier: SocialTableViewCell.identifier,
for: indexPath) as? SocialTableViewCell else { return UITableViewCell() }
cell.logoutButton.addTarget(self, action: #selector(UserProfileTableViewController.logout), for: .touchUpInside)
return cell
default: return UITableViewCell()
}
}

Images not showing in collectionView Swift

In console there is printing of empty imagesArray but I am downloading it in downloadImages function. And in simulator the images won't load
import UIKit
import PinterestLayout
import ProgressHUD
class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var postsArray = [Post]()
var imagesArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
if let layout = collectionView.collectionViewLayout as? PinterestLayout {
layout.delegate = self
}
collectionView.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
loadItems()
downloadPhoto()
}
func loadItems() {
ref.child("Posts").observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String,Any>
if let title = snapshotValue["title"], let price = snapshotValue["price"], let downloadUrl = snapshotValue["downloadUrl"], let category = snapshotValue["category"], let senderUid = snapshotValue["senderUid"] {
let post = Post()
post.title = title as! String
post.price = price as! String
post.downloadUrl = downloadUrl as! String
post.category = category as! String
post.senderUid = senderUid as! String
self.postsArray.append(post)
self.collectionView.reloadData()
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tabBarController?.tabBar.shadowImage = UIImage()
tabBarController?.tabBar.backgroundImage = UIImage()
}
func downloadPhoto(){
DispatchQueue.global().async {
self.imagesArray.removeAll() // this is the image array
for i in 0..<self.postsArray.count {
guard let url = URL(string: self.postsArray[i].downloadUrl) else {
continue
}
let group = DispatchGroup()
print(url)
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? url.lastPathComponent)
if let imgData = data, let image = UIImage(data: imgData) {
DispatchQueue.main.async() {
self.imagesArray.append(image)
self.collectionView.reloadData()
}
} else if let error = error {
print(error)
}
group.leave()
}).resume()
group.wait()
}
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imagesArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell
cell.imgView.downloadImage(from: self.postsArray[indexPath.row].downloadUrl)
return cell
}
}
extension MainViewController: PinterestLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
let image = imagesArray[indexPath.item]
let height = image.size.height
return height
}
}
extension UIImageView {
func downloadImage(from url: String){
let urlRequest = URLRequest(url: URL(string: url)!)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data,response,error) in
if error != nil {
print(error ?? error!)
return
}
if let data = data {
DispatchQueue.main.async {
self.image = UIImage(data: data)
}
}
}
task.resume()
}
}
UPDATED CODE:
import UIKit
import PinterestLayout
import ProgressHUD
import Kingfisher
class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
var postsArray = [Post]()
var imagesArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
if let layout = collectionView.collectionViewLayout as? PinterestLayout {
layout.delegate = self
}
collectionView.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
loadItems()
collectionView.reloadData()
}
func loadItems() {
ref.child("Posts").observe(.childAdded) { (snapshot) in
let snapshotValue = snapshot.value as! Dictionary<String,Any>
if let title = snapshotValue["title"], let price = snapshotValue["price"], let downloadUrl = snapshotValue["downloadUrl"], let category = snapshotValue["category"], let senderUid = snapshotValue["senderUid"] {
let post = Post()
post.title = title as! String
post.price = price as! String
post.downloadUrl = downloadUrl as! String
post.category = category as! String
post.senderUid = senderUid as! String
self.postsArray.append(post)
self.downloadPhoto()
print(self.imagesArray.count)
self.collectionView.reloadData()
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tabBarController?.tabBar.shadowImage = UIImage()
tabBarController?.tabBar.backgroundImage = UIImage()
}
func downloadPhoto(){
DispatchQueue.global().async {
self.imagesArray.removeAll() // this is the image array
for i in 0..<self.postsArray.count {
guard let url = URL(string: self.postsArray[i].downloadUrl) else {
continue
}
let group = DispatchGroup()
print(url)
print("-------GROUP ENTER-------")
group.enter()
URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
print(response?.suggestedFilename ?? url.lastPathComponent)
if let imgData = data, let image = UIImage(data: imgData) {
DispatchQueue.main.async() {
self.imagesArray.append(image)
let post = Post()
post.image = image
self.collectionView.reloadData()
}
} else if let error = error {
print(error)
}
group.leave()
}).resume()
group.wait()
}
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return postsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell
let resource = ImageResource(downloadURL: URL(string: postsArray[indexPath.row].downloadUrl)!, cacheKey: postsArray[indexPath.row].downloadUrl)
cell.imgView.kf.setImage(with: resource)
return cell
}
}
extension MainViewController: PinterestLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
let image = imagesArray[indexPath.row]
let height = image.size.height / 6
return height
}
}
//AND POST CLASS
import UIKit
class Post {
var title : String = ""
var category : String = ""
var downloadUrl : String = ""
var price : String = ""
var senderUid : String = ""
var image = UIImage()
}
You need to call
downloadPhoto()
inside
loadItems()
as both are asynchronous , here
self.postsArray.append(post)
downloadPhoto()
Note: I recommend having a cache to check before downloading the image or better use SDWebImage
As Sh_Khan said, you need to call downloadPhoto after loadItems has completed, otherwise there wont be any posts to loop over.
Also, a few points to consider here...
You are not reloading any cells once the image download has completed (downloadPhoto)
You are not caching images, so you will end up downloading images often. Once you scroll your collectionView and cells get reused you will download the same images, again.
You are not using DispatchGroup effectively here (in downloadPhoto anyway), you appear to be downloading one image at a time (or trying to), not taking advantage of parallel downloads. If you intend to do this, use a serial queue. But this will slow down loading images considerably.
I prefer to use KingFisher for downloading and caching images, the library already manages most of this for you and leaves you to focus on your app.
If you dont want to use a library, something like this should help...
var imageCache = [String: UIImage]()
func downloadImage(from url: String){
if let image = imageCache[url] as? UIImage {
self.image = image
return
}
let urlRequest = URLRequest(url: URL(string: url)!)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data,response,error) in
if error != nil {
print(error ?? error!)
return
}
if let data = data {
DispatchQueue.main.async {
let image = UIImage(data: data)
imageCache[url] = image
self.image = image
}
}
}
task.resume()
}
Kingfisher example:
imageView.kf.setImage(with: url, completionHandler: {
(image, error, cacheType, imageUrl) in
// image: Image? `nil` means failed
// error: NSError? non-`nil` means failed
// cacheType: CacheType
// .none - Just downloaded
// .memory - Got from memory cache
// .disk - Got from disk cache
// imageUrl: URL of the image
})
so have a postsArray and images array
var postsArray = [Post]()
var images = [String: UIImage]() // dictionary, maps url to image
Then when you receive a Post:
let post = Post()
post.title = title as! String
post.price = price as! String
post.downloadUrl = downloadUrl as! String
post.category = category as! String
post.senderUid = senderUid as! String
self.postsArray.append(post)
imageView.kf.setImage(with: url, completionHandler: { (image, error, cacheType, imageUrl) in
// check image is not nil etc
images[url] = image
collectionView.reloadData()
}
CellForRowAt:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell
cell.imgView.image = images[postsArray[indexPath.row].downloadUrl]
return cell
}

Returning UIImage Async using Task

I have a UICollectionView of cells each including an image.
I want to load the cell's images.
My code that instantiate the image :
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
let prodInCell = searchActive ? filtered[indexPath.row] : products[indexPath.row]
// Set fields
cell.ProductImageView.image = prodInCell.GetProductImage()
cell.ProductName.text = prodInCell.Name()
cell.ProductPrice.text = String(prodInCell.Price())
cell.productUniqueID = prodInCell.UniqueID()
return cell
}
My Product's GetProductImage function:
public func GetProductImage() -> UIImage
{
let prodID = self.UniqueID()
let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
var prodImg = #imageLiteral(resourceName: "DefaultProductImage")
let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: // Up to 10 MB pictures
{
(data, error) in
if let data = data
{
if let img = UIImage(data: data)
{
prodImg = img
}
}
})
imgTask.observe(.progress, handler: {(snapshot) in
print (snapshot.progress ?? "NO MORE PROGRESS")
})
imgTask.resume()
return prodImg
}
I want a UIImage to be retrieved from Firebase Storage, or return a DefaultProductImage if none exists. Current implementation stucks my UI and seems to not really load anything from Firebase.
How do I Make this work ? I would also like for it to not take so much time - so perhaps using a couple of tasks to each load an image would be a good solution.
Edit :
This is my code now :
accept
You can use a completion block to return the UIImage asynchronously.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
let prodInCell = searchActive ? filtered[indexPath.row] : products[indexPath.row]
// Set fields
cell.ProductImageView.image = #imageLiteral(resourceName: "DefaultProductImage")
prodInCell.GetProductImage() { image in
cell.ProductImageView.image = image
}
cell.ProductName.text = prodInCell.Name()
cell.ProductPrice.text = String(prodInCell.Price())
cell.productUniqueID = prodInCell.UniqueID()
return cell
}
public func GetProductImage(completion: ((UIImage?) -> Void)) {
let prodID = self.UniqueID()
let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: { (data, error) in
if let data = data, let img = UIImage(data: data) {
completion(img)
} else {
completion(nil)
}
})
imgTask.observe(.progress, handler: {(snapshot) in
print (snapshot.progress ?? "NO MORE PROGRESS")
})
imgTask.resume()
}
And now I get
Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)
In function
- (void)invokeFetchCallbacksOnCallbackQueueWithData:(GTM_NULLABLE NSData *)data
error:(GTM_NULLABLE NSError *)error {
// Callbacks will be released in the method stopFetchReleasingCallbacks:
GTMSessionFetcherCompletionHandler handler;
#synchronized(self) {
GTMSessionMonitorSynchronized(self);
handler = _completionHandler;
if (handler) {
[self invokeOnCallbackQueueUnlessStopped:^{
handler(data, error);
// Post a notification, primarily to allow code to collect responses for
// testing.
//
// The observing code is not likely on the fetcher's callback
// queue, so this posts explicitly to the main queue.
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
if (data) {
userInfo[kGTMSessionFetcherCompletionDataKey] = data;
}
if (error) {
userInfo[kGTMSessionFetcherCompletionErrorKey] = error;
}
[self postNotificationOnMainThreadWithName:kGTMSessionFetcherCompletionInvokedNotification
userInfo:userInfo
requireAsync:NO];
}];
}
} // #synchronized(self)
In line handler(data,error);
With error error NSError * domain: #"com.google.HTTPStatus" - code: 404
You can use a completion block to return the UIImage asynchronously.
E.g. you could update your code to the following:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
let prodInCell = searchActive ? filtered[indexPath.row] : products[indexPath.row]
// Set fields
cell.ProductImageView.image = #imageLiteral(resourceName: "DefaultProductImage")
prodInCell.GetProductImage() { image in
cell.ProductImageView.image = image
}
cell.ProductName.text = prodInCell.Name()
cell.ProductPrice.text = String(prodInCell.Price())
cell.productUniqueID = prodInCell.UniqueID()
return cell
}
And:
public func GetProductImage(completion: ((UIImage?) -> Void)) {
let prodID = self.UniqueID()
let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: { (data, error) in
if let data = data, let img = UIImage(data: data) {
completion(img)
} else {
completion(nil)
}
})
imgTask.observe(.progress, handler: {(snapshot) in
print (snapshot.progress ?? "NO MORE PROGRESS")
})
imgTask.resume()
}

Swift Images place in wrong cell and keep chaging in UICollectionview

I have searched but I was not successful to find the answer to my question, I am downloading images from internet and put them into collection view but when I scroll the places are changing even without scrolling they places on the wrong cell here is my code :
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
var Label = cell.viewWithTag(2) as! UILabel
Label.text = namesArray[indexPath.row]
var image = cell.viewWithTag(1) as! UIImageView
let URLString = imgLink[indexPath.row]
let imgUrl = URL(string: URLString)
image.downloadedFrom(url: imgUrl!, contentMode: UIViewContentMode.scaleAspectFit)
UIimg.insert(image.image!, at: indexPath.row)
return cell
}
public extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { () -> Void in
self.image = image
}
}.resume()
}
func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloadedFrom(url: url, contentMode: mode)
}
}
UPDATE:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
var image1 = cell.viewWithTag(1) as! UIImageView
let URLString = imgLink[indexPath.row]
let imgUrl = URL(string: URLString)
var Label = cell.viewWithTag(2) as! UILabel
Label.text = namesArray[indexPath.row]
getImage(urlString: URLString) { (success:Bool, data:NSData?, errorDescription:String?) in
if success {
DispatchQueue.main.async() {
let image = UIImage(data: data! as Data)
image1.image = image
}
}
}
return cell
}
func getImage(urlString:String, completionHandler:#escaping (_ success:Bool, _ data:NSData?, _ errorDescription:String?) -> Void) -> Void {
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url! as URL)
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data, error == nil else {
completionHandler(false,nil, error?.localizedDescription)
return
}
completionHandler(true, data as NSData?, nil)
}
task.resume()
}
This function is an asynchronous function which will take some time to complete
image.downloadedFrom(url: imgUrl!, contentMode: UIViewContentMode.scaleAspectFit)
So this line..
UIimg.insert(image.image!, at: indexPath.row)
Will run before the above function call has finished downloading the image. This will be causing your issue.
Your downloadedFrom function should use a completion handler to run some code after the image has downloaded for it to work properly.
I usually use a function like the one below for fetching images
func getImage(urlString:String, completionHandler:(success:Bool, data:NSData?, errorDescription:String?) -> Void) -> Void {
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(URL: url!)
let task = session.dataTaskWithRequest(request) { (data, response, error) in
guard let data = data where error == nil else {
completionHandler(success: false,data: nil, errorDescription: error?.localizedDescription)
return
}
completionHandler(success: true, data: data, errorDescription: nil)
}
task.resume()
}
Which can be used in a tableCell/collectionCell like this:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let photo = fetchedResultsController.objectAtIndexPath(indexPath) as! Photo
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! AlbumCell
cell.backgroundColor = UIColor.grayColor()
cell.imageView.image = UIImage(named: "placeholder")
if let image = photo.image {
cell.imageView.image = image
} else {
VTClient.sharedInstance().getImage(photo.url) { (success:Bool, data:NSData?, errorDescription:String?) in
if success {
dispatch_async(dispatch_get_main_queue()) {
let image = UIImage(data: data!)
cell.imageView.image = image
FlickrClient.Caches.imageCache.storeImage(image, withIdentifier: photo.id)
}
}
}
}
return cell
}
}
See my project here https://github.com/martinjkelly/virtual-tourist/blob/master/Virtual Tourist for more information on how this is used

SDWebImage doesn't work

What am I doing wrong? Everything runs but I don't get the Images, help! Thanks!
import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
struct postStruct {
let title : String!
let downloadURL : String!
}
class ZeroHomeViewController: UITableViewController {
var posts = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Posts")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let title = value["Title"] as? String else { continue }
guard let downloadURL = value["Download URL"] as? String else { continue }
let post = postStruct(title: title, downloadURL: downloadURL)
self.posts.append(post)
}
self.posts = self.posts.reversed(); self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let imageView = cell?.viewWithTag(200) as! UIImageView
imageView.sd_setImage(with: URL(string: "downloadUrl"), placeholderImage: UIImage(named: "placeholder.png"))
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
return cell!
}
}
Secondly
Replace this line
imageView.sd_setImage(with: URL(string: "downloadUrl"), placeholderImage: UIImage(named: "placeholder.png"))
With this
imageView.sd_setImage(with: URL(string: "www.domain.com/url"), placeholderImage: UIImage(named: "placeholder.png"))
Make sure your edit the url to the image you want