My goal was to do a home page with layout like Pinterest.
After some research I found this projects; PinterestAnimator and PinterestSwift. These really helped me about collection view layout, especially CHTCollectionViewWaterfallLayout. However there is still one problem called self-sizing.
So I searched more and found this fantastic extension on Alamofire in order to download images, thanks to Ray Wenderlich.
extension Alamofire.Request {
class func imageResponseSerializer() -> Serializer {
return { request, response, data in
if let data = data {
let image = UIImage(data: data)
return (image, nil)
}
return (nil, nil)
}
}
func responseImage(completionHandler: (NSURLRequest, NSHTTPURLResponse?, UIImage?, NSError?) -> Void) -> Self {
return response(serializer: Request.imageResponseSerializer(), completionHandler: {
(request, response, image, error) in
completionHandler(request, response, image as? UIImage, error)
})
}
}
Image size is accessible once it's downloaded but we know its width will be (view.size-3*inset)/columnNumber. Therefore we can filter image to that size in order to achieve faster loading time. Here is the code:
let item = items[indexPath.row]
// Prepare for re-use
cell.request?.cancel()
cell.imageView.image = nil // Caching can be implemented here
let imageScale = UIScreen.mainScreen().scale
let imagePixel = Int(cellWidth * imageScale)
let filterURLString = "http://cdn.filter.to/\(imagePixel)x\(imagePixel)/"
// We should delete "http://" of imageURLString in order to use filtering
if
let imageURLString = item.imageURLString,
let rangeOfURLString = imageURLString.rangeOfString("//", options: .allZeros, range: nil, locale: nil),
let imageURL = NSURL(string: filterURLString+imageURLString.substringFromIndex(advance(rangeOfURLString.startIndex,2)))
{
cell.request = Alamofire.request(.GET, imageURL, parameters: nil, encoding: .URL).responseImage({
(_, _, image, error) -> Void in
if let image = image where error == nil {
// Resize cell
cell.imageView.image = image
cell.title = item.title
cell.subtitle = item.subtitle
let imageViewHeight = self.cellWidth * image.ratio
let extraHeight = cell.titleLabel.frame.height + cell.subtitleLabel.frame.height
item.estimatedCellSize = CGSize(width: self.cellWidth, height: imageViewHeight + extraHeight)
// Perform updates
collectionView.performBatchUpdates(nil, completion: nil)
}
})
}
You can find the project here.