Load selectedIndexItem on new collectionViewCell (invalidate imageCache)
I have a lot of problems loading the CustomImageView: UIImageView in the detailed viewController based on the selectedIndexPath of the ViewCell collection. I successfully went through and loaded UILabels and UITextViews, but could not load CustomImageView: UIImageView from the same selectedIndexPath using the same process and code logic. I believe it has something to do with clearing or flushing the image cache, but not sure where or what code to execute to do this. Sorry for any extra code, just want to be thorough. Thanks for any help or guidance!
// object classes that store values ββfrom Firebase
class CurrentPlanner: SafeJsonObjectPlanner {
var name: String?
var profileImageUrl: String?
var planningPlace: String?
init(dictionary: [String: AnyObject]) {
self.name = dictionary["addedBy"] as? String
self.profileImageUrl = dictionary["profileImageUrl"] as? String
self.planningPlace = dictionary["planning"] as? String
}
}
// CustomImageView: a UIImageView extension that populates the first collectionViewController
let imageCache = NSCache<NSString, UIImage>()
class CustomImageView: UIImageView {
var imageUrlString: String?
func loadImageUsingUrlString(_ urlString: String) {
imageUrlString = urlString
let url = URL(string: urlString)
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as NSString) {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url!, completionHandler: { (data, respones, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async(execute: {
let imageToCache = UIImage(data: data!)
if self.imageUrlString == urlString {
self.image = imageToCache
}
imageCache.setObject(imageToCache!, forKey: urlString as NSString)
})
}).resume()
}
}
extension UIImageView {
func loadImageUsingCacheWithUrlString(_ urlString: String) {
self.image = nil
//check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as NSString) {
self.image = cachedImage
return
}
//otherwise fire off a new download
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
//download hit an error so lets return out
if let error = error {
print(error)
return
}
DispatchQueue.main.async(execute: {
if let downloadedImage = UIImage(data: data!) {
imageCache.setObject(downloadedImage, forKey: urlString as NSString)
self.image = downloadedImage
}
})
}).resume()
}
}
// schedule the cell class in the first collectionView
class BasePlanningCell: BaseCell2 {
var currentPlanners = [CurrentPlanner]()
var currentPlanner: CurrentPlanner? {
didSet {
setupProfileImage()
}
}
fileprivate func setupProfileImage() {
if let profileImageUrl = currentPlanner?.profileImageUrl {
userProfileImageView.loadImageUsingCacheWithUrlString(profileImageUrl)
}
}
// the selected cell class in the first collectView method - calling the delegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("cell tapped")
// cell delegate method called from collectionViewController
travelersFeedVC?.showPlanningViewDetailView(indexPath: indexPath)
}
// the first class CollectionViewController is the method executed when the cell is clicked
func showPlanningViewDetailView(indexPath: IndexPath) {
let plannersDetailVC = PlanningPlaceDetailsVC()
plannersDetailVC.profileImageUrl = plannedPlaces[indexPath.row].profileImageUrl!
print(plannersDetailVC.profileImageUrl!)
show(plannersDetailVC, sender: self)
}
// Second class DetailViewController
var nameString: String!
var locationString: String!
var profileImageUrl: String!
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.item {
case 0:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlanningDetailViewCells", for: indexPath) as! PlanningDetailViewCells
cell.myMethod(str: nameString)
cell.getLocationMethod(str: locationString)
cell.getProfileImageMethod(str: profileImageUrl)
return cell
case 1:
// ...
case 2:
// ...
default:
// ...
}
}
// 2nd DetailViewControllers Delegate class cells
func myMethod(str : String){
nameString = str
print("var : \(nameString)")
planningCellHeader?.titleLabel.text = nameString
}
func getLocationMethod(str : String){
locationString = str
print("var : \(String(describing: locationString))")
planningCellHeader?.locationTextView.text = locationString
}
func getProfileImageMethod(str : String){
profileImageUrl = str
print("var : \(String(describing: profileImageUrl))")
planningCellHeader?.userProfileImageView.imageUrlString = profileImageUrl
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.section {
case 0:
switch indexPath.item {
case 0:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "headerId", for: indexPath) as! PlanningCellHeader
cell.myMethod(str: nameString)
cell.getLocationMethod(str: locationString)
cell.getProfileImageMethod(str: profileImageUrl)
return cell
case 1:
// ...
default:
// ...
}
default:
// ...
}
}
// headerCell class that contains views
var nameString: String?
var locationString: String?
var profileImageUrl: String?
let titleLabel: UILabel = {
let label = UILabel()
// ...
return label
}()
let locationTextView: UITextView = {
let textView = UITextView()
// ...
return textView
}()
let userProfileImageView: CustomImageView = {
let imageView = CustomImageView()
// ...
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel.text = nameString
locationTextView.text = locationString
userProfileImageView.imageUrlString = profileImageUrl
setupViews()
}
func myMethod(str : String){
nameString = str
print("var : \(String(describing: nameString))")
titleLabel.text = nameString
}
func getLocationMethod(str : String){
locationString = str
print("var : \(String(describing: locationString))")
locationTextView.text = locationString
}
func getProfileImageMethod(str : String){
profileImageUrl = str
print("var : \(String(describing: profileImageUrl))")
// userProfileImageView.image = UIImage(named: "meAndDuncan")
userProfileImageView.imageUrlString = profileImageUrl
}
source to share
I figured it out myself. Maybe self explanatory, but I had to convert imageUrlString to Data (contentsOf: url!) In my getProfileImageMethod (str: String) as shown below:
func getProfileImageMethod(str : String){
profileImageUrl = str
print("var : \(String(describing: profileImageUrl))")
// added the code below and it worked!
var imageUrlString: String?
imageUrlString = profileImageUrl
let url = URL(string: imageUrlString!)
let data = try? Data(contentsOf: url!)
let image: UIImage = UIImage(data: data!)!
userProfileImageView.image = image
}
source to share