AdaptiveCode/AdaptiveCode/ProfileViewController.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
A view controller that shows a user's profile. |
*/ |
import UIKit |
class ProfileViewController: UIViewController { |
// MARK: Properties |
fileprivate var imageView: UIImageView? |
fileprivate var nameLabel: UILabel? |
fileprivate var conversationsLabel: UILabel? |
fileprivate var photosLabel: UILabel? |
// Holds the current constraints used to position the subviews. |
fileprivate var constraints = [NSLayoutConstraint]() |
let user: User |
var nameText: String { |
return user.name |
} |
var conversationsText: String { |
let conversationCount = user.conversations.count |
let localizedStringFormat = NSLocalizedString("%d conversations", comment: "X conversations") |
return String.localizedStringWithFormat(localizedStringFormat, conversationCount) |
} |
var photosText: String { |
let photoCount = user.conversations.reduce(0) { count, conversation in |
return count + conversation.photos.count |
} |
let localizedStringFormat = NSLocalizedString("%d photos", comment: "X photos") |
return String.localizedStringWithFormat(localizedStringFormat, photoCount) |
} |
// MARK: Initialization |
init(user: User) { |
self.user = user |
super.init(nibName: nil, bundle: nil) |
title = NSLocalizedString("Profile", comment: "Profile") |
} |
required init(coder aDecoder: NSCoder) { |
fatalError("init(coder:) has not been implemented") |
} |
// MARK: View Controller |
override func loadView() { |
let view = UIView() |
view.backgroundColor = UIColor.white |
// Create an image view |
let imageView = UIImageView() |
imageView.contentMode = .scaleAspectFit |
imageView.translatesAutoresizingMaskIntoConstraints = false |
self.imageView = imageView |
view.addSubview(imageView) |
// Create a label for the profile name |
let nameLabel = UILabel() |
nameLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline) |
nameLabel.translatesAutoresizingMaskIntoConstraints = false |
self.nameLabel = nameLabel |
view.addSubview(nameLabel) |
// Create a label for the number of conversations |
let conversationsLabel = UILabel() |
conversationsLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body) |
conversationsLabel.translatesAutoresizingMaskIntoConstraints = false |
self.conversationsLabel = conversationsLabel |
view.addSubview(conversationsLabel) |
// Create a label for the number of photos |
let photosLabel = UILabel() |
photosLabel.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body) |
photosLabel.translatesAutoresizingMaskIntoConstraints = false |
self.photosLabel = photosLabel |
view.addSubview(photosLabel) |
self.view = view |
// Update all of the visible information |
updateUser() |
updateConstraintsForTraitCollection(traitCollection) |
} |
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { |
super.willTransition(to: newCollection, with: coordinator) |
// When the trait collection changes, change our views' constraints and animate the change |
coordinator.animate(alongsideTransition: { _ in |
self.updateConstraintsForTraitCollection(newCollection) |
self.view.setNeedsLayout() |
}, completion: nil) |
} |
// Applies the proper constraints to the subviews for the size class of the given trait collection. |
func updateConstraintsForTraitCollection(_ collection: UITraitCollection) { |
let views: [String: AnyObject] = [ |
"topLayoutGuide": topLayoutGuide, |
"imageView": imageView!, |
"nameLabel": nameLabel!, |
"conversationsLabel": conversationsLabel!, |
"photosLabel": photosLabel! |
] |
// Make our new set of constraints for the current traits |
var newConstraints = [NSLayoutConstraint]() |
if collection.verticalSizeClass == .compact { |
// When we're vertically compact, show the image and labels side-by-side |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|[imageView]-[nameLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "[imageView]-[conversationsLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "[imageView]-[photosLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[topLayoutGuide][imageView]|", options: [], metrics: nil, views: views) |
newConstraints += [ |
NSLayoutConstraint(item: imageView!, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 0.5, constant: 0) |
] |
} |
else { |
// When we're vertically compact, show the image and labels top-and-bottom |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|[imageView]|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|-[nameLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|-[conversationsLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|-[photosLabel]-|", options: [], metrics: nil, views: views) |
newConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]-20-[imageView]|", options: [], metrics: nil, views: views) |
} |
// Change to our new constraints |
NSLayoutConstraint.deactivate(constraints) |
constraints = newConstraints |
NSLayoutConstraint.activate(newConstraints) |
} |
// MARK: Convenience |
// Updates the user interface with the data from the current user object. |
func updateUser() { |
nameLabel?.text = nameText |
conversationsLabel?.text = conversationsText |
photosLabel?.text = photosText |
imageView?.image = user.lastPhoto?.image |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13