0

I have a UITablView contains number of cells that represent employees for each.

And I have UISearchBar to filter the list of employees, I'm storing employee data as employee object which has number of properties so I'm filtering the employees.

What I couldn't filter is the employee photo because I didn't save it as property in employee object , I call function for downloading the image inside cellForRowAtIndexPath and that's it I can't use the image again .

I need a way to save the image for later use .

This cellForRowAtIndexPath code :

    override   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! employeeCell

    if self.isSearching == true {

    let emp = searchedEmployees[(indexPath as NSIndexPath).row]
        cell.empName.text = emp.getFistName() + " " + emp.getLastName()

        cell.empPosition.text = emp.getPosition()

        cell.status.text=emp.getStatus()

        let myurlstring=emp.getPhotoURL()!
        let myurl = myurlstring.addingPercentEncoding( withAllowedCharacters: CharacterSet.urlQueryAllowed)


        cell.empPhoto.downloadImageFrom(link: myurl!, contentMode: UIViewContentMode.scaleAspectFit)
    }
    else{

    let emp = employees[(indexPath as NSIndexPath).row]
        cell.empName.text = emp.getFistName() + " " + emp.getLastName()

        cell.empPosition.text = emp.getPosition()

        cell.status.text=emp.getStatus()

        let myurlstring=emp.getPhotoURL()!
        let myurl = myurlstring.addingPercentEncoding( withAllowedCharacters: CharacterSet.urlQueryAllowed)


        cell.empPhoto.downloadImageFrom(link: myurl!, contentMode: UIViewContentMode.scaleAspectFit)
    }

    return cell

}

This is downloading image function :

extension UIImageView {
func downloadImageFrom(link:String, contentMode: UIViewContentMode){

    URLSession.shared.dataTask( with: URL(string:link)!, completionHandler: {
        (data, response, error) -> Void in
        DispatchQueue.main.async {
            self.contentMode = contentMode
            if let data = data {
                self.image = UIImage(data: data)
                self.image = self.image?.circle
                self.image = self.image?.rounded
            }
        }
    }).resume()
}

}

This is searchBar function :

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    if self.searchBar.text!.isEmpty {

        // set searching false
        self.isSearching = false

        // reload table view
        self.tableView.reloadData()

    }else{

        // set searghing true
        self.isSearching = true

        // empty searching array
        self.searchedEmployees.removeAll(keepingCapacity: false)

        // find matching item and add it to the searcing array
        for i in 0..<self.employees.count {

            let firstName : String = self.employees[i].getFistName()
            let lastName : String = self.employees[i].getLastName()
            let fullName : String = self.employees[i].getFistName()+" "+self.employees[i].getLastName()
            if firstName.lowercased().range(of: self.searchBar.text!.lowercased()) != nil || lastName.lowercased().range(of: self.searchBar.text!.lowercased()) != nil || fullName.lowercased().range(of: self.searchBar.text!.lowercased()) != nil{
                self.searchedEmployees.append(self.employees[i])
            }

        }

        self.tableView.reloadData()
    }

}

I think my way for getting the images is wrong because in my case I need to save the images for later use and I'm not also I couldn't find a way to async download image then after loading it save it in array or something.

Any help ?

Janmenjaya
  • 4,149
  • 1
  • 23
  • 43
Zizoo
  • 1,694
  • 5
  • 20
  • 42
  • You can save to Document directory after successful download and keep the path or last name of image path (Other path would be same for all i.e document directory). then use that property to fetch the image from document directory. Does that make sense ? – Janmenjaya Sep 22 '16 at 12:54

2 Answers2

2

Consider using SDWebImage library it downloads and caches your images so they are not downloaded every time your cellForRowAtIndexPath is called and will also solve your problem.

Just use

cell.empPhoto.sd_setImageWithURL(self.imageURL)

in your cellForRowAtIndexPath.

Hope this helps.

nishith Singh
  • 2,968
  • 1
  • 15
  • 25
  • Thank you , but sorry i'm new to this which file should I copy to my project ? – Zizoo Sep 22 '16 at 13:07
  • Download the zip from this link. Inside the zip you will find a folder named SDWebImage add the folder and all the files containing in it to your project then just add this import to your bridging header #import and you are good to go. – nishith Singh Sep 22 '16 at 13:11
  • If you need help in adding a bridging header to your project please refer this link http://stackoverflow.com/questions/31716413/xcode-not-automatically-creating-bridging-header – nishith Singh Sep 22 '16 at 13:13
  • I get error when the code reach this line cell.empPhoto.sd_setImage(with: url) – Zizoo Sep 22 '16 at 13:55
  • Check your url for nil and if it is a valid url or not – nishith Singh Sep 22 '16 at 14:07
  • terminating with uncaught exception of type NSException – Zizoo Sep 22 '16 at 14:10
  • try not adding addingPercentEncoding. – nishith Singh Sep 22 '16 at 14:13
  • I tried to add only url string without addingPercentEncoding , same error – Zizoo Sep 22 '16 at 14:13
  • Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImageView sd_setImageWithURL:]: unrecognized selector sent to instance 0x7fb3e86485c0' – Zizoo Sep 22 '16 at 14:18
  • Replace the previous import with this import in your bridging header #import "UIImageView+WebCache.h" – nishith Singh Sep 22 '16 at 14:28
  • I get this : bridging header '/.../.../...' does not exist – Zizoo Sep 22 '16 at 14:35
  • use this link to add a bridging header http://stackoverflow.com/questions/31716413/xcode-not-automatically-creating-bridging-header – nishith Singh Sep 22 '16 at 14:38
  • click File->New->File then select Cocoa class then click Next, then provide any name to the class and in language be sure to select Objective-C then click Next then click Create. Once this done xcode will ask to create a bridging header for you click yes and you will have a bridging file. Place the import there and everything should work fine – nishith Singh Sep 22 '16 at 14:42
  • I did all of this . still getting the same error when reach that line – Zizoo Sep 22 '16 at 15:21
  • Finally it works , really thank you and sorry for long discussion :) – Zizoo Sep 22 '16 at 16:20
  • No problem. Happy to help. – nishith Singh Sep 23 '16 at 07:11
0

For Swift, there is a library Kingfisher.

Methods are pretty smart:

import Kingfisher
...

let url = URL(string: "url_of_your_image")
imageView.kf.setImage(with: url)

You can install it via Pods, Carthage, by Swift Package Manager or manually:

https://github.com/onevcat/Kingfisher/wiki/Installation-Guide

I prefer Pods way:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target 'MyApp' do
  # your other pod
  # ...
  pod 'Kingfisher', '~> 3.0'
end

More docs are here:

http://cocoadocs.org/docsets/Kingfisher/3.1.0/

https://github.com/onevcat/Kingfisher

pedrouan
  • 12,762
  • 3
  • 58
  • 74