Skip to content

Commit

Permalink
AttachmentManager Optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
nathantannar4 committed Feb 2, 2018
1 parent f061e3e commit 23e65c2
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 62 deletions.
120 changes: 73 additions & 47 deletions InputBarAccessoryView/Managers/AttachmentManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,21 @@

import UIKit

open class AttachmentManager: NSObject, InputManager, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
open class AttachmentManager: NSObject, InputManager {

public enum Attachment {
case image(UIImage)
case url(URL)
case data(Data)
case other(AnyObject)
}

// MARK: - Properties [Public]

/// A protocol that can recieve notifications from the `AttachmentManager`
open weak var delegate: AttachmentManagerDelegate?

/// A protocol to passes data to the `AttachmentManager`
open weak var dataSource: AttachmentManagerDataSource?

open lazy var attachmentView: AttachmentsView = { [weak self] in
Expand All @@ -40,24 +51,14 @@ open class AttachmentManager: NSObject, InputManager, UICollectionViewDataSource
return attachmentView
}()

open var attachments = [AnyObject]() {
didSet {
reloadData()
}
}
/// The attachments that the managers holds
private(set) public var attachments = [Attachment]() { didSet { reloadData() } }

/// A flag you can use to determine if you want the manager to be always visible
open var isPersistent = false {
didSet {
attachmentView.reloadData()
}
}
open var isPersistent = false { didSet { attachmentView.reloadData() } }

open var showAddAttachmentCell = true {
didSet {
attachmentView.reloadData()
}
}
/// A flag to determine if the AddAttachmentCell is visible
open var showAddAttachmentCell = true { didSet { attachmentView.reloadData() } }

// MARK: - Initialization

Expand All @@ -73,20 +74,35 @@ open class AttachmentManager: NSObject, InputManager, UICollectionViewDataSource
delegate?.attachmentManager(self, shouldBecomeVisible: attachments.count > 0 || isPersistent)
}

/// Invalidates the `AttachmentManagers` session by removing all attachments
open func invalidate() {
attachments.removeAll()
attachments = []
}

/// Appends the object to the attachments
///
/// - Parameter object: The object to append
open func handleInput(of object: AnyObject) {
insertAttachment(object, at: attachments.count)
let attachment: Attachment
if let image = object as? UIImage {
attachment = .image(image)
} else if let url = object as? URL {
attachment = .url(url)
} else if let data = object as? Data {
attachment = .data(data)
} else {
attachment = .other(object)
}

insertAttachment(attachment, at: attachments.count)
}

// MARK: - Attachment Management
// MARK: - API [Public]

/// Performs an animated insertion of an attachment at an index
///
/// - Parameter index: The index to insert the attachment at
open func insertAttachment(_ attachment: AnyObject, at index: Int) {
open func insertAttachment(_ attachment: Attachment, at index: Int) {

attachmentView.performBatchUpdates({
self.attachments.insert(attachment, at: index)
Expand Down Expand Up @@ -114,63 +130,73 @@ open class AttachmentManager: NSObject, InputManager, UICollectionViewDataSource
})
}

}

extension AttachmentManager: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

// MARK: - UICollectionViewDelegate

open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
final public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == attachments.count {
delegate?.attachmentManager(self, didSelectAddAttachmentAt: indexPath.row)
delegate?.attachmentManager(self, shouldBecomeVisible: attachments.count > 0 || isPersistent)
}
}

// MARK: - UICollectionViewDataSource

open func numberOfItems(inSection section: Int) -> Int {
final public func numberOfItems(inSection section: Int) -> Int {
return 1
}

open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
final public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return attachments.count + (showAddAttachmentCell ? 1 : 0)
}

open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
final public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

if indexPath.row == attachments.count {
if indexPath.row == attachments.count && showAddAttachmentCell {
return addAttachmentCell(in: collectionView, at: indexPath)
}
return dataSource?.attachmentManager(self, cellFor: attachments[indexPath.row], at: indexPath.row) ?? defaultCell(in: collectionView, for: attachments[indexPath.row], at: indexPath)

let attachment = attachments[indexPath.row]

if let cell = dataSource?.attachmentManager(self, cellFor: attachment, at: indexPath.row) {
return cell
} else {

// Only images are supported by default
switch attachment {
case .image(let image):
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageAttachmentCell.reuseIdentifier, for: indexPath) as? ImageAttachmentCell else {
fatalError()
}
cell.attachment = attachment
cell.indexPath = indexPath
cell.manager = self
cell.imageView.image = image
return cell
default:
return collectionView.dequeueReusableCell(withReuseIdentifier: AttachmentCell.reuseIdentifier, for: indexPath) as! AttachmentCell
}

}
}

// MARK: - UICollectionViewDelegateFlowLayout

open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
final public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

var height = collectionView.intrinsicContentSize.height
var height = attachmentView.intrinsicContentHeight
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
height -= (layout.sectionInset.bottom + layout.sectionInset.top + collectionView.contentInset.top + collectionView.contentInset.bottom)
}
return CGSize(width: height, height: height)
}

// MARK: - Default Cells

open func defaultCell(in collectionView: UICollectionView, for attachment: AnyObject, at indexPath: IndexPath) -> AttachmentCell {

if let image = attachments[indexPath.row] as? UIImage {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageAttachmentCell.reuseIdentifier, for: indexPath) as? ImageAttachmentCell else {
fatalError()
}
cell.indexPath = indexPath
cell.manager = self
cell.imageView.image = image
return cell
}
return collectionView.dequeueReusableCell(withReuseIdentifier: "AttachmentCell", for: indexPath) as! AttachmentCell
}

open func addAttachmentCell(in collectionView: UICollectionView, at indexPath: IndexPath) -> AttachmentCell {
private func addAttachmentCell(in collectionView: UICollectionView, at indexPath: IndexPath) -> AttachmentCell {

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AttachmentCell", for: indexPath) as? AttachmentCell else {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AttachmentCell.reuseIdentifier, for: indexPath) as? AttachmentCell else {
fatalError()
}
cell.deleteButton.isHidden = true
Expand Down
6 changes: 1 addition & 5 deletions InputBarAccessoryView/Managers/AutocompleteManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,7 @@ open class AutocompleteManager: NSObject, InputManager {
private(set) public weak var inputTextView: InputTextView?

/// An ongoing session reference that holds the prefix, range and text to complete with
private(set) public var currentSession: AutocompleteSession? {
didSet {
layoutIfNeeded()
}
}
private(set) public var currentSession: AutocompleteSession? { didSet { layoutIfNeeded() } }

/// The `AutocompleteTableView` that renders available autocompletes for the `currentSession`
open lazy var tableView: AutocompleteTableView = { [weak self] in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ public protocol AttachmentManagerDataSource: class {
/// - attachment: The object
/// - index: The index in the AttachmentView
/// - Returns: An AttachmentCell
func attachmentManager(_ manager: AttachmentManager, cellFor attachment: AnyObject, at index: Int) -> AttachmentCell
func attachmentManager(_ manager: AttachmentManager, cellFor attachment: AttachmentManager.Attachment, at index: Int) -> AttachmentCell
}
12 changes: 6 additions & 6 deletions InputBarAccessoryView/Protocols/AttachmentManagerDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,22 @@ public protocol AttachmentManagerDelegate: class {
/// - manager: The AttachmentManager
/// - attachment: The attachment that was inserted
/// - index: The index of the attachment in the AttachmentManager's attachments array
func attachmentManager(_ manager: AttachmentManager, didInsert attachment: AnyObject, at index: Int)
func attachmentManager(_ manager: AttachmentManager, didInsert attachment: AttachmentManager.Attachment, at index: Int)

/// Notifys when an attachment has been removed from the AttachmentManager
///
/// - Parameters:
/// - manager: The AttachmentManager
/// - attachment: The attachment that was removed
/// - index: The index of the attachment in the AttachmentManager's attachments array
func attachmentManager(_ manager: AttachmentManager, didRemove attachment: AnyObject, at index: Int)
func attachmentManager(_ manager: AttachmentManager, didRemove attachment: AttachmentManager.Attachment, at index: Int)

/// Notifys when the AttachmentManager was reloaded
///
/// - Parameters:
/// - manager: The AttachmentManager
/// - attachments: The AttachmentManager's attachments array
func attachmentManager(_ manager: AttachmentManager, didReloadTo attachments: [AnyObject])
func attachmentManager(_ manager: AttachmentManager, didReloadTo attachments: [AttachmentManager.Attachment])

/// Notifys when the AddAttachmentCell was selected
///
Expand All @@ -71,11 +71,11 @@ public protocol AttachmentManagerDelegate: class {

public extension AttachmentManagerDelegate {

func attachmentManager(_ manager: AttachmentManager, didInsert attachment: AnyObject, at index: Int) {}
func attachmentManager(_ manager: AttachmentManager, didInsert attachment: AttachmentManager.Attachment, at index: Int) {}

func attachmentManager(_ manager: AttachmentManager, didRemove attachment: AnyObject, at index: Int) {}
func attachmentManager(_ manager: AttachmentManager, didRemove attachment: AttachmentManager.Attachment, at index: Int) {}

func attachmentManager(_ manager: AttachmentManager, didReloadTo attachments: [AnyObject]) {}
func attachmentManager(_ manager: AttachmentManager, didReloadTo attachments: [AttachmentManager.Attachment]) {}

func attachmentManager(_ manager: AttachmentManager, didSelectAddAttachmentAt index: Int) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ open class AttachmentsView: UICollectionView {
alwaysBounceHorizontal = true
showsHorizontalScrollIndicator = true
setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .vertical)
register(AttachmentCell.self, forCellWithReuseIdentifier: "AttachmentCell")
register(AttachmentCell.self, forCellWithReuseIdentifier: AttachmentCell.reuseIdentifier)
register(ImageAttachmentCell.self, forCellWithReuseIdentifier: ImageAttachmentCell.reuseIdentifier)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ open class AttachmentCell: UICollectionViewCell {

// MARK: - Properties

class var reuseIdentifier: String {
return "AttachmentCell"
}

open let containerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -57,7 +61,7 @@ open class AttachmentCell: UICollectionViewCell {
return button
}()

open var attachment: AnyObject?
open var attachment: AttachmentManager.Attachment?

open var indexPath: IndexPath?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ open class ImageAttachmentCell: AttachmentCell {

// MARK: - Properties

static var reuseIdentifier: String {
override class var reuseIdentifier: String {
return "ImageAttachmentCell"
}

Expand Down

0 comments on commit 23e65c2

Please sign in to comment.