Apologies
You must be signed in to watch this lesson.
Preview Screenshots Cells
AppStore JSON APIs
It's time we finally moved onto to showing the preview screenshots of each app that we click into. This will be another exercise where we implement a horizontal collection controller to embed a horizontal sliding component. Enjoy.

Comments (9)
Dennisvm82
5 years ago
Everything works just fine, but Xcode still returns the following in my case. The relevant UICollectionViewFlowLayout instance is <AppStore.BaseSnappingLayout: 0x7fd3dfe63990>, and it is attached to <UICollectionView: 0x7fd441120200; frame = (0 0; 375 453.667); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x600001112730>; layer = <CALayer: 0x600001fee700>; contentOffset: {-16, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 16, 0, 16}> collection view layout: <AppStore.BaseSnappingLayout: 0x7fd3dfe63990>. Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger. The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
tsangaris
5 years ago
I had a slightly different approach when it came to putting the PreviewCell together: In the PreviewCell I create the separatorLine (basically a UIView with light gray color and a width equal to 1), the previewLabel and used the horizontalController.view. Then I added all of them into a vertical stack view like so: let stack = VerticalStackView(arrangedSubviews: [separatorLine, previewLabel, horizontalController.view], spacing: 16, distribution: .fill, alignment: .fill) addSubview(stack) stack.fillSuperview(padding: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) This way all 3 elements are aligned correctly by just setting the padding once in the fillSuperview() method. The spacing between the elements is easily manipulated when arranging the subviews in the vertical stack view. PS: What i really like about Brian is that he repeats the code in every step he makes. There isn't a better way to learn! Thanks again chief!
Maciek Górecki
5 years ago
The images are not low quality, but some apps have landscape images. They appear "bad quality", because we have vertical cells and the content mode is set to .scaleAspectFill.
Brian Voong
5 years ago
sdevreugd
4 years ago
He Brian, First off: Great turorials! Appreciate the hard work! I had a question regarding the ScreenShotCell imageView and the layout of the sizing of the ScreenShotCells. I basically found a way to render out the ScreenShot cells size and the PreviewCell size according to the various .scaleAspectFit sizes of the apps’ screenShot images. Considering that either the app preview only has horizontal or vertical images, I fetched the first image and used its’ size as the size for both the ScreenShotCell and the PreviewCell. Both in AppDetailController and PreviewScreenShotController I added the following: var app: Result? { didSet { self.collectionView.reloadData() self.screenShotURLs = self.app?.screenshotUrls ?? [] guard let firstUrlString = self.app?.screenshotUrls?.first else { return } if let url = URL(string: firstUrlString) { dummyScreenShot.sd_setImage(with: url) { (image, _, _, _) in self.imageSize = image?.size } } } } var imageSize: CGSize? { didSet { DispatchQueue.main.async { self.collectionView.reloadData() } } } let dummyScreenShot = UIImageView() let verticalImageWidth: CGFloat = 230 - And in sizeForItem, again both in AppDetailController and PreviewScreenShotController: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { guard let previewCellSize = self.imageSize else { return CGSize(width: view.frame.width, height: view.frame.height)} if previewCellSize.width > previewCellSize.height { let ratio = previewCellSize.width / previewCellSize.height return CGSize(width: view.frame.width, height: self.view.frame.width / ratio) } else { let ratio = previewCellSize.height / previewCellSize.width return CGSize(width: verticalImageWidth, height: (verticalImageWidth * ratio)) } } This seems all a bit naive to me and I was wondering if there is a more efficient way of doing this? For example in the case of adjusting the collectionView cell sizes according to the intrinsic content size of images with more varying sizes? Cheers
Brian Voong
4 years ago
sdevreugd
4 years ago
Agreed! Thanks for the quick response
dclawson
4 years ago
Maybe it's just me, but when we set the contentInset at around 13-14min in, I lost the top rounding for the purple cells. I set that top inset to 16, and it came back. Obviously, it takes up more space now.
druvinskiy
4 years ago
Do you have any suggestions for rendering out the AppDetailCell and the PreviewCell without using an if statement based on the indexPath.item? This seems like it would work for a few number of cells but doesn't seem really scalable if we wanted multiple kinds of cells. I'm thinking there has to be a better way to do this.
Brian Voong
4 years ago
tomisin
3 years ago
Hi Brain, Please I don't understand the solution you gave in terms of the application (usage)
sepmotameni
3 years ago
Hi Brian, I'm curious. Why do you use a UICollectionViewController rather than just a ViewController for the AppDetailController? I was thinking of just creating a single view controller for AppDetailController and adding multiple subviews to that view controller. Is the reason why you use a UICollectionViewController because all the content won't fit in 1 view controller since you cannot scroll down on a UIViewController? Best, Sep
Brian Voong
3 years ago
sepmotameni
3 years ago
Awesome! Thanks for the quick response! Have a good day.
aldo3
3 years ago
Hi Brian, I'm just curious. What was the main reason for not keeping with the previous pattern, of one cell with an embedded horizontal UICollectionViewController. I do think this separation(two cells) is bettering this case instead of jamming all the UI into one cell. Thanks -Al
alokach123
2 years ago
Hey Brian, Can you explain why the variable app in AppDetailCell needs to be an optional? Because when I don't make it optional, the everything besides the apps in the first section crashes. Thank you -Alok
HELP & SUPPORT