Load Images with SDWebImage using Cocoapod
AppStore JSON APIs
Our rows inside of our cells look decent right now, but they're still missing the correct images for the application icons. Let's now fix that by using SDWebImage to very easily load and cache images in our app. Using libraries like this greatly reduces the amount of custom image loading code you have to manually maintain.

Comments (12)
tatters
4 years ago
Best episode so far! Thanks
Tube
4 years ago
Often, you seem to do the Search tab first. Any special reason?
Brian Voong
4 years ago
tsangaris
4 years ago
Hey Brian, Is there a difference between .layer.masksToBounds = true VS clipsToBounds = true? I know that there are a lot of explanations out there (https://stackoverflow.com/questions/39466001/maskstobounds-vs-clipstobounds) but have you ever had to choose which one to use? Or you just use the clipsToBounds for every case?
Brian Voong
4 years ago
RobinHe0212
4 years ago
Ho Brian, When we set the cell properties ,can we put those in the didSet function in the cell class instead in the cellForItemAt function?
RobinHe0212
4 years ago
I just saw. Solve my question.Thanks.
Brian Voong
4 years ago
ZiadHamdieh
4 years ago
Hey Brian, question about your refactored code from the VC to the View. You are calling one of the functions in the SDWebImage library but you don't need to import SDWebImage in SearchResultCell.swift. I thought that you couldn't use a library in a swift file without importing it first. Do you mind clearing this up for me?
Brian Voong
4 years ago
nombienombie
4 years ago
Hey Brian, I wanted to reduce the amount of condition logic so instead of checking if the returned image count was greater than 1 or 2, I used a for loop let ss = [cell.ssOne, cell.ssTwo, cell.ssThree] for (index, element) in data.screenshotUrls.enumerated() { guard index < ss.count else { break } ss[index].sd_setImage(with: URL(string: element)) } Is this approach OK? I added a guard statement to ensure if the API returned 4 images I would not get a crash from only having 3 screen shots in my ss array.
Hadouryu
4 years ago
Hello Brian, First of all nice video and I enjoy it pretty much so far. I have one question tho since i encountered a bug. I will describe it now. I have done this a bit differently to practice even more, instead of loading 3 screen shots, I made a whole collection view to load all the screenshots that are fetched from the api. Everything works find but there is a really weird bug. When you scroll down using the api in this video, only on 23rd row (PolaUS app) the images on screenshot are changing and are displayed with wrong content in them when the collection view is dequeuing them. Every other app from the api is just fine. Does something special happen on 23rd row or what am I missing here?
Brian Voong
4 years ago
Hadouryu
4 years ago
Thanks for the reply, I will check that and try to fix it. Keep up the good work, you are awesome. All the best , Armin
Patrick Cockrill
4 years ago
Hey Brian, I'm working on a scrolling Reusable headerView, and there is a collectionView nested inside the header to have the ability to load the total amount of images for the post (horizontal scrolling). The data is initially passed in from the HomeViewController which uses the didSelectHandler we wrote in the video, which is then passed into the appId on the DetailViewController. However, since I need to load the images in via the ItemHeader because of the nested collectionView cell (to my knowledge), the data is nil when I try and sd_setImage that way. Is there a way to get the data from DetailViewController into the Header Cells? I tried to call an object of ItemHeader in the didSelectHandler on the HomeView but that didn't work. class ItemHeader: UICollectionReusableView, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { let cellId = "cellId" var app: Result? func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 4 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! PhotoCell cell.imageView.sd_setImage(with: URL(string: app?.artworkUrl100 ?? "")) // This RESULTS in NIL return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 0 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: frame.width, height: frame.height) } let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.backgroundColor = UIColor.lightGray cv.isPagingEnabled = true cv.layer.masksToBounds = true cv.isScrollEnabled = true return cv }() ... } class PhotoCell: UICollectionViewCell { override init(frame: CGRect) { super.init(frame: frame) layoutViews() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } let imageView: UIImageView = { let view = UIImageView() view.contentMode = .scaleAspectFill return view }() private func layoutViews() { addSubview(imageView) imageView.fillSuperview() } }
Brian Voong
4 years ago
Patrick Cockrill
4 years ago
Yeah, That loads in the image through the detailViewController which is only the one image the app has right? In this case it's setting the imageViews.image for each cell which happens directly in the header... I thought. I was thinking maybe a didSet {...} but idk.
Brian Voong
4 years ago
Patrick Cockrill
4 years ago
One more thing, I remember in the Instagram course that we resized the selectedImage by doing a CGSize() because it became blurry. When I tap on a cell (an App) the header is that Image, and it gets fuzzy/blurry because of the resizing/expanding of the size it was initially. Is there a way to solve this issue, it sounds relatively trivial but I've seen vImage for instance but I don't think that'd be necessary.
Eugeneberezin
3 years ago
Swift package manager is super cool! Love it. So much faster and easier to install dependencies!
Brian Voong
3 years ago
dclawson
3 years ago
Probably obvious to most, but here are the basic steps: Within XCode (with your project open, obviously) 1. File > Swift Packages... > Add Package Dependency... 2. Drop down window: "Choose Package Repository:" 3. Put the URL into the textfield: "https://github.com/SDWebImage/SDWebImage" 4. Hit next 5. Choose which packages you want. When I did this, it had options for SDWebImage and also a version that included MapKit. I just selected the standard one. 6. Click Finish If mine compiled or did anything after that, it didn't take long, and I hit "Build" and could immediately import SDWebImage.
Lazaro Ambrosio
3 years ago
Thanks I did not know how to :)
frankusu
3 years ago
Hey Brian, I don't really understand why the computed property "var appResult : Result! { didSet{ } }" you need the bang 'Result!' and if you don't add the bang, the error "Property self.appResult not initialized at super.init call" pops up. How does '!' initialize values, it's a Decodable? Stackoverflow makes no sense. Thank you for your time! https://stackoverflow.com/questions/24021093/error-in-swift-class-property-not-initialized-at-super-init-call “Swift’s compiler performs four helpful safety-checks to make sure that two-phase initialization is completed without error:” Safety check 1 “A designated initializer must ensure that all of the “properties introduced by its class are initialized before it delegates up to a superclass initializer.”
c.smith
3 years ago
Hello Brian, I use the image Cache extension from your video back in 2016. <https://www.youtube.com/watch?v=GX4mcOOUrWQ> @24:31 is there a difference in using the cocoapod and native code?
sohail
3 years ago
JSON Integration iTunes Search API (8. Load Images with SDWebImage using Cocoapod) ---------------------------------------------------------------- let url = URL(string: appResult.artworkUrl100) cell.imageView.sd_setImage(with: url) ---------------------------------------------------------------- Console Area Fetching itunes apps from Service layer Failed to decode Json keyNotFound(CodingKeys(stringValue: "screenshortUrls", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"screenshortUrls\", intValue: nil) (\"screenshortUrls\").", underlyingError: nil)) Failed to fetch apps: keyNotFound(CodingKeys(stringValue: "screenshortUrls", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"screenshortUrls\", intValue: nil) (\"screenshortUrls\").", underlyingError: nil)) ----------------------------------------------------------------- actually i am basic level so, what i do next
Brian Voong
3 years ago
HELP & SUPPORT