Lets Build YouTube Home Feed
YouTubeToday we'll start off this brand new series on how to build out the YouTube application for iOS. I'll give you guys a quick demo of the application and some of the features/functionality that we'll be writing in Swift. Sit back, relax, and enjoy this first lesson where we'll focus on building out the Home Feed portion of the app!
<div class='filename'>HomeController.swift</div>
!codebreak
!syntax-highlight
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Home"
collectionView?.backgroundColor = UIColor.whiteColor()
collectionView?.registerClass(VideoCell.self, forCellWithReuseIdentifier: "cellId")
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellId", forIndexPath: indexPath)
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(view.frame.width, 200)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
}
!codebreak
<div class='filename'>VideoCell.swift</div>
!codebreak
!syntax-highlight
class VideoCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let thumbnailImageView: UIImageView = {
let imageView = UIImageView()
imageView.backgroundColor = UIColor.blueColor()
imageView.image = UIImage(named: "taylor_swift_blank_space")
return imageView
}()
let userProfileImageView: UIImageView = {
let imageView = UIImageView()
imageView.backgroundColor = UIColor.greenColor()
return imageView
}()
let separatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.blackColor()
return view
}()
let titleLabel: UILabel = {
let label = UILabel()
label.backgroundColor = UIColor.purpleColor()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let subtitleTextView: UITextView = {
let textView = UITextView()
textView.backgroundColor = UIColor.redColor()
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
func setupViews() {
addSubview(thumbnailImageView)
addSubview(separatorView)
addSubview(userProfileImageView)
addSubview(titleLabel)
addSubview(subtitleTextView)
addConstraintsWithFormat("H:|-16-[v0]-16-|", views: thumbnailImageView)
addConstraintsWithFormat("H:|-16-[v0(44)]", views: userProfileImageView)
//vertical constraints
addConstraintsWithFormat("V:|-16-[v0]-8-[v1(44)]-16-[v2(1)]|", views: thumbnailImageView, userProfileImageView, separatorView)
addConstraintsWithFormat("H:|[v0]|", views: separatorView)
//top constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .Top, relatedBy: .Equal, toItem: thumbnailImageView, attribute: .Bottom, multiplier: 1, constant: 8))
//left constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .Left, relatedBy: .Equal, toItem: userProfileImageView, attribute: .Right, multiplier: 1, constant: 8))
//right constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .Right, relatedBy: .Equal, toItem: thumbnailImageView, attribute: .Right, multiplier: 1, constant: 0))
//height constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 0, constant: 20))
//top constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .Top, relatedBy: .Equal, toItem: titleLabel, attribute: .Bottom, multiplier: 1, constant: 8))
//left constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .Left, relatedBy: .Equal, toItem: userProfileImageView, attribute: .Right, multiplier: 1, constant: 8))
//right constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .Right, relatedBy: .Equal, toItem: thumbnailImageView, attribute: .Right, multiplier: 1, constant: 0))
//height constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 0, constant: 20))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
!codebreak
<div class='filename'>UIView extension</div>
!codebreak
!syntax-highlight
extension UIView {
func addConstraintsWithFormat(format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerate() {
let key = "v\(index)"
view.translatesAutoresizingMaskIntoConstraints = false
viewsDictionary[key] = view
}
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
}
!codebreak
<div class='filename'>AppDelegate.swift</div>
!codebreak
!syntax-highlight
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
return true
}