AdaptiveCode/AdaptiveCode/ListTableViewController.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 list of conversations that can be viewed. |
*/ |
import UIKit |
class ListTableViewController: UITableViewController { |
// MARK: Properties |
let user: User |
static let cellIdentifier = "ConversationCell" |
// MARK: Initialization |
init(user: User) { |
self.user = user |
super.init(style: .plain) |
title = NSLocalizedString("Conversations", comment: "Conversations") |
navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("About", comment: "About"), style: .plain, target: self, action: #selector(ListTableViewController.showAboutViewController(_:))) |
navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("Profile", comment: "Profile"), style: .plain, target: self, action: #selector(ListTableViewController.showProfileViewController(_:))) |
clearsSelectionOnViewWillAppear = false |
} |
required init(coder aDecoder: NSCoder) { |
fatalError("init(coder:) has not been implemented") |
} |
deinit { |
NotificationCenter.default.removeObserver(self) |
} |
// MARK: View Controller |
override func viewDidLoad() { |
super.viewDidLoad() |
tableView.register(UITableViewCell.self, forCellReuseIdentifier: ListTableViewController.cellIdentifier) |
NotificationCenter.default.addObserver(self, selector: #selector(ListTableViewController.showDetailTargetDidChange(_:)), name: NSNotification.Name.UIViewControllerShowDetailTargetDidChange, object: nil) |
} |
override func viewWillAppear(_ animated: Bool) { |
super.viewWillAppear(animated) |
// Deselect any index paths that push when tapped |
for indexPath in tableView.indexPathsForSelectedRows ?? [] { |
let pushes: Bool |
if shouldShowConversationViewForIndexPath(indexPath) { |
pushes = willShowingViewControllerPushWithSender(self) |
} |
else { |
pushes = willShowingDetailViewControllerPushWithSender(self) |
} |
if pushes { |
// If we're pushing for this indexPath, deselect it when we appear. |
tableView.deselectRow(at: indexPath, animated: animated) |
} |
} |
if let visiblePhoto = currentVisibleDetailPhotoWithSender(self) { |
for indexPath in tableView.indexPathsForVisibleRows ?? [] { |
let photo = photoForIndexPath(indexPath) |
if photo == visiblePhoto { |
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none) |
} |
} |
} |
} |
func showDetailTargetDidChange(_ notification: Notification) { |
/* |
Whenever the target for showDetailViewController: changes, update all |
of our cells (to ensure they have the right accessory type). |
*/ |
for cell in tableView.visibleCells { |
if let indexPath = tableView.indexPath(for: cell) { |
tableView(tableView, willDisplay: cell, forRowAt: indexPath) |
} |
} |
} |
override func containsPhoto(_ photo: Photo) -> Bool { |
return true |
} |
// MARK: About |
func showAboutViewController(_ sender: UIBarButtonItem) { |
if presentedViewController != nil { |
// Dismiss Profile if visible |
dismiss(animated: true, completion: nil) |
} |
let aboutViewController = AboutViewController() |
aboutViewController.navigationItem.title = NSLocalizedString("About", comment: "About") |
aboutViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ListTableViewController.closeAboutViewController(_:))) |
let navController = UINavigationController(rootViewController: aboutViewController) |
navController.modalPresentationStyle = .fullScreen |
present(navController, animated: true, completion: nil) |
} |
func closeAboutViewController(_ sender: UIBarButtonItem) { |
dismiss(animated: true, completion: nil) |
} |
// MARK: Profile |
func showProfileViewController(_ sender: UIBarButtonItem) { |
let profileController = ProfileViewController(user: user) |
profileController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ListTableViewController.closeProfileViewController(_:))) |
let profileNavController = UINavigationController(rootViewController: profileController) |
profileNavController.modalPresentationStyle = .popover |
profileNavController.popoverPresentationController?.barButtonItem = sender |
// Set self as the presentation controller's delegate so that we can adapt its appearance |
profileNavController.popoverPresentationController?.delegate = self |
present(profileNavController, animated: true, completion:nil) |
} |
func closeProfileViewController(_ sender: UIBarButtonItem) { |
dismiss(animated: true, completion: nil) |
} |
// MARK: Table View |
func conversationForIndexPath(_ indexPath: IndexPath) -> Conversation { |
return user.conversations[indexPath.row] |
} |
func photoForIndexPath(_ indexPath: IndexPath) -> Photo? { |
if shouldShowConversationViewForIndexPath(indexPath) { |
return nil |
} |
else { |
let conversation = conversationForIndexPath(indexPath) |
return conversation.photos.last |
} |
} |
// Returns whether the conversation at indexPath contains more than one photo. |
func shouldShowConversationViewForIndexPath(_ indexPath: IndexPath) -> Bool { |
let conversation = conversationForIndexPath(indexPath) |
return conversation.photos.count > 1 |
} |
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
return user.conversations.count |
} |
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
return tableView.dequeueReusableCell(withIdentifier: ListTableViewController.cellIdentifier, for: indexPath) |
} |
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { |
// Whether to show the disclosure indicator for this cell. |
let pushes: Bool |
if shouldShowConversationViewForIndexPath(indexPath) { |
// If the conversation corresponding to this row has multiple photos. |
pushes = willShowingViewControllerPushWithSender(self) |
} |
else { |
// If the conversation corresponding to this row has a single photo. |
pushes = willShowingDetailViewControllerPushWithSender(self) |
} |
/* |
Only show a disclosure indicator if selecting this cell will trigger |
a push in the master view controller (the navigation controller above |
ourself). |
*/ |
cell.accessoryType = pushes ? .disclosureIndicator : .none |
let conversation = conversationForIndexPath(indexPath) |
cell.textLabel?.text = conversation.name |
} |
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
let conversation = conversationForIndexPath(indexPath) |
if shouldShowConversationViewForIndexPath(indexPath) { |
let controller = ConversationViewController(conversation: conversation) |
controller.title = conversation.name |
// If this row has a conversation, we just want to show it. |
show(controller, sender: self) |
} |
else { |
if let photo = conversation.photos.last { |
let controller = PhotoViewController(photo: photo) |
controller.title = conversation.name |
// If this row has a single photo, then show it as the detail (if possible). |
showDetailViewController(controller, sender: self) |
} |
} |
} |
} |
extension ListTableViewController: UIPopoverPresentationControllerDelegate { |
func presentationController(_ presentationController: UIPresentationController, willPresentWithAdaptiveStyle style: UIModalPresentationStyle, transitionCoordinator: UIViewControllerTransitionCoordinator?) { |
guard let presentedNavigationController = presentationController.presentedViewController as? UINavigationController else { return } |
// We want to hide the navigation bar if we're presenting in our original style (Popover) |
let hidesNavigationBar = style == .none |
presentedNavigationController.setNavigationBarHidden(hidesNavigationBar, animated: false) |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13