diff --git a/ContainerControllerSwift.podspec b/ContainerControllerSwift.podspec index c99f410..d9b5ef4 100644 --- a/ContainerControllerSwift.podspec +++ b/ContainerControllerSwift.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.name = 'ContainerControllerSwift' s.version = '0.1.0' - s.summary = 'A short description of ContainerControllerSwift.' + s.summary = 'This is a swipe-panel from application: https://www.apple.com/ios/maps/' # This description is used to generate tags and improve search results. # * Think: What does it do? Why did you write it? What is the focus? @@ -21,16 +21,16 @@ Pod::Spec.new do |s| TODO: Add long description of the pod here. DESC - s.homepage = 'https://github.com/rustamburger@gmail.com/ContainerControllerSwift' + s.homepage = 'https://github.com/mrustaa/ContainerController' # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'rustamburger@gmail.com' => 'rustamburger@gmail.com' } - s.source = { :git => 'https://github.com/rustamburger@gmail.com/ContainerControllerSwift.git', :tag => s.version.to_s } + s.source = { :git => 'https://github.com/mrustaa/ContainerController.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '13.0' - s.source_files = 'ContainerControllerSwift/Classes/**/*' + s.source_files = 'ContainerControllerSwift/*.{swift}' # s.resource_bundles = { # 'ContainerControllerSwift' => ['ContainerControllerSwift/Assets/*.png'] diff --git a/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCell.swift b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCell.swift new file mode 100644 index 0000000..30fa727 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCell.swift @@ -0,0 +1,124 @@ +// +// ColletionAdapterCell.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 01/05/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class CollectionAdapterCell: UICollectionViewCell { + + @IBInspectable var hideAnimation: Bool = false + var selectedView: UIView? + + public var cellData: CollectionAdapterCellData? + + open func fill(data: Any?) { + + } + + override init(frame: CGRect) { + super.init(frame: frame) + setupCommonProperties() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupCommonProperties() + } + + private func setupCommonProperties() { + + } + +// public func notifyDidTap() { +// guard let cellData = cellData else { return } +// let cellDataIdentifier = cellData.cellIdentifier +// +// let action = CollectionViewAdapterCellAction( +// cell: self, +// cellIdentifier: cellDataIdentifier, +// actionIdentifier: CollectionsActionCellsIdentifiers.cellDidTap.rawValue, +// data: cellData) +// +// delegate?.handle(action: action) +// } + + let selAlpha: CGFloat = 0.2 // 0.15 + + + override var isSelected: Bool { + set { + super.isSelected = newValue + + if hideAnimation { + + if newValue { + alpha = 0.5 + UIView.animate(withDuration: 0.45) { + self.alpha = 1 + } + } else { + self.alpha = 1 + } + + } else { + + if let selectedView = selectedView { + if newValue { + selectedView.alpha = selAlpha + UIView.animate(withDuration: 0.45) { + selectedView.alpha = 0.0 + } + } else { + selectedView.alpha = 0.0 + } + } else { + // super.setSelected(selected, animated: animated) + } + } + } + get { + return super.isSelected + } + } + + override var isHighlighted: Bool { + set { + super.isHighlighted = newValue + + if hideAnimation { + if newValue { + UIView.animate(withDuration: 0.1) { + self.alpha = 0.5 + } + } else { + UIView.animate(withDuration: 0.45) { + self.alpha = 1 + } + } + } else { + if let selectedView = selectedView { + if newValue { + UIView.animate(withDuration: 0.1) { + selectedView.alpha = self.selAlpha + } + } else { + UIView.animate(withDuration: 0.45) { + selectedView.alpha = 0.0 + } + } + } else { +// super.setHighlighted(highlighted, animated: animated) + } + } + + } + get { + return super.isHighlighted + } + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCellData.swift b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCellData.swift new file mode 100644 index 0000000..34ff829 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterCellData.swift @@ -0,0 +1,19 @@ +// +// ColletionAdapterCellData.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 01/05/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class CollectionAdapterCellData: NSObject { + + public var selectCallback: (() -> Void)? + + open func size() -> CGSize { + return CGSize.zero + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterItem.swift b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterItem.swift new file mode 100644 index 0000000..192d6b7 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterItem.swift @@ -0,0 +1,29 @@ +// +// ColletionAdapterItem.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 01/05/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class CollectionAdapterItem: NSObject { + + public let cellClass: AnyClass + public let cellData: CollectionAdapterCellData? + + public var cellReuseIdentifier: String { + return String(describing: cellClass) + } + + init(cellClass: AnyClass, cellData: CollectionAdapterCellData? = nil) { + self.cellClass = cellClass + self.cellData = cellData + } + + public func size() -> CGSize { + return cellData?.size() ?? CGSize.zero + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterTypes.swift b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterTypes.swift new file mode 100644 index 0000000..d8fcfc9 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterTypes.swift @@ -0,0 +1,14 @@ +// +// CollectionAdapterTypes.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 01/05/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +typealias CollectionAdapterCountCallback = () -> Int +typealias CollectionAdapterCellIndexCallback = (_ index: Int) -> UICollectionViewCell +typealias CollectionAdapterSizeIndexCallback = (_ index: Int) -> CGSize +typealias CollectionAdapterSelectIndexCallback = (_ index: Int) -> () diff --git a/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterView.swift b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterView.swift new file mode 100644 index 0000000..53b790d --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerCollection/CollectionAdapterView.swift @@ -0,0 +1,117 @@ +// +// CollectionAdapterView.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 01/05/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class CollectionAdapterView: UICollectionView { + + var countCallback: CollectionAdapterCountCallback? + var cellIndexCallback: CollectionAdapterCellIndexCallback? + var sizeIndexCallback: CollectionAdapterSizeIndexCallback? + var selectIndexCallback: CollectionAdapterSelectIndexCallback? + + var items: [CollectionAdapterItem] = [] + + required init?(coder: NSCoder) { + super.init(coder: coder) + update() + } + + override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { + super.init(frame: frame, collectionViewLayout: layout) + update() + } + + func update() { + delegate = self + dataSource = self + backgroundColor = .clear + } + + + public func set(items: [CollectionAdapterItem]) { + items.forEach { + registerNibIfNeeded(for: $0) + } + self.items = items + reloadData() + } + + public func registerNibIfNeeded(for item: CollectionAdapterItem) { + let nib = UINib(nibName: item.cellReuseIdentifier, bundle: nil) + register(nib, forCellWithReuseIdentifier: item.cellReuseIdentifier) + } + + public func clear() { + items = [] + reloadData() + } + + private func cellAt(_ indexPath: IndexPath) -> CollectionAdapterCell? { + let item = items[indexPath.row] + let cellIdentifier = item.cellReuseIdentifier + let cell = dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as? CollectionAdapterCell + cell?.cellData = item.cellData + return cell + } + +} + +extension CollectionAdapterView: UICollectionViewDelegate { + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if !items.isEmpty { + let item = items[indexPath.row] + item.cellData?.selectCallback?() + } + if let selectIndexCallback = selectIndexCallback { + selectIndexCallback(indexPath.row) + } + + } +} + +extension CollectionAdapterView: UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + if !items.isEmpty { + return items.count + } + if let countCallback = countCallback { + return countCallback() + } + return 0 + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if !items.isEmpty { + let item = items[indexPath.row] + let cell = cellAt(indexPath) + cell?.fill(data: item.cellData) + return cell ?? UICollectionViewCell() + } + if let cellIndexCallback = cellIndexCallback { + return cellIndexCallback(indexPath.row) + } + return UICollectionViewCell() + } +} + +extension CollectionAdapterView: UICollectionViewDelegateFlowLayout { + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + if !items.isEmpty { + let item = items[indexPath.row] + return item.size() + } + if let sizeIndexCallback = sizeIndexCallback { + return sizeIndexCallback(indexPath.row) + } + return CGSize.zero + } +} diff --git a/ContainerControllerSwift/Classes/ContainerController.swift b/ContainerControllerSwift/Classes/ContainerController.swift new file mode 100644 index 0000000..9a006b1 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerController.swift @@ -0,0 +1,1335 @@ +// +// ContainerView.swift +// PatternsSwift +// +// Created by mrustaa on 21/04/2020. +// Copyright © 2020 mrustaa. All rights reserved. +// + +import UIKit + +class ContainerController: NSObject { + + // MARK: Views + + public var view: ContainerView! + + public var shadowButton: UIButton! + + public var controller: UIViewController? + + public var scrollView: UIScrollView? + + public var headerView: UIView? + + public var footerView: UIView? + + // MARK: Layout + + public var layout: ContainerLayout = ContainerLayout() + + // MARK: Delegate + + public var delegate: ContainerControllerDelegate? + + // MARK: Current Move Type + + public var moveType: ContainerMoveType = .hide + + public var oldMoveType: ContainerMoveType = .hide + + // MARK: - Properties Scroll + + private var oldTransform: CGAffineTransform = .identity + + private var oldPosition: CGFloat = 0.0 + + private var panGesture: UIPanGestureRecognizer? + + private var panBeginSavePosition: CGFloat = 0.0 + + private var oldOrientation: ContainerDevice.Orientation = ContainerDevice.orientation + + private var isScrolling: Bool = false + + private var scrollBordersRunContainer: Bool = false + + private var scrollOnceBeginDragging: Bool = false + + private var scrollOnceEnded: Bool = false + + private var scrollBegin: Bool = false + + private var scrollStartPosition: CGFloat = 0.0 + + private var scrollTransform = CGAffineTransform.identity + + // MARK: - Properties Position + + public var topBarHeight: CGFloat { + var result: CGFloat = 0.0 + if let vc = controller?.navigationController, !vc.isNavigationBarHidden { + let statusBarHeight: CGFloat = ContainerDevice.statusBarHeight + let navBarHeight: CGFloat = vc.navigationBar.frame.height + result = statusBarHeight + navBarHeight + } + return result + } + + public var topTranslucent: Bool { + return controller?.navigationController?.navigationBar.isTranslucent ?? false + } + + private var isPortrait: Bool { + return ContainerDevice.isPortrait + } + + private var deviceHeight: CGFloat { + var height: CGFloat = 0.0 + if isPortrait { + height = ContainerDevice.screenMax + } else { + height = ContainerDevice.screenMin + } + height -= topBarHeight + return height + } + + private var deviceWidth: CGFloat { + var width: CGFloat = 0.0 + if isPortrait { + width = ContainerDevice.screenMin + } else { + width = ContainerDevice.screenMax + } + return width + } + + // MARK: - Positions Move + + private var positionTop: CGFloat { + var top = layout.positions.top + if !isPortrait { + if let landscape = layout.landscapePositions { + top = landscape.top + } + } + return top + } + + public var positionMiddle: CGFloat { + var middle = layout.positions.middle ?? layout.positions.bottom + if !isPortrait { + if let landscapeMid = layout.landscapePositions?.middle { + middle = landscapeMid + } + } + return deviceHeight - middle + } + + private var positionBottom: CGFloat { + var bottom = layout.positions.bottom + if !isPortrait { + if let landscape = layout.landscapePositions { + bottom = landscape.bottom + } + } + return deviceHeight - bottom + } + + private var insetsLeft: CGFloat { + var left: CGFloat = layout.insets.left + if !isPortrait { + if let inset = layout.landscapeInsets { + left = inset.left + } + } + return left + } + + private var insetsRight: CGFloat { + var right: CGFloat = layout.insets.right + if !isPortrait { + if let inset = layout.landscapeInsets { + right = inset.right + } + } + return right + } + + private var middleEnable: Bool { + if isPortrait { + return layout.positions.middle != nil + } else { + if let landscapePositions = layout.landscapePositions { + return landscapePositions.middle != nil + } else { + return layout.positions.middle != nil + } + } + } + + // MARK: - Init + + public init(addTo controller: UIViewController, layout: ContainerLayout) { + super.init() + + self.controller = controller + set(layout: layout) + + NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: UIDevice.orientationDidChangeNotification, object: nil) + + createShadowButton() + createContainerView() + + move(type: layout.startPosition, animation: false) + } + + // MARK: - Remove + + public func remove(completion: (() -> Void)? = nil) { + + NotificationCenter.default.removeObserver(self) + + move(type: .hide, completion: + + { [weak self] in + guard let _self = self else { return } + + _self.scrollView?.removeFromSuperview() + _self.headerView?.removeFromSuperview() + _self.footerView?.removeFromSuperview() + _self.shadowButton.removeFromSuperview() + _self.view.removeFromSuperview() + + completion?() + }) + } + + // MARK: - Rotated + + @objc func rotated() { + + let orint = UIDevice.current.orientation + if orint == .faceUp || orint == .faceDown { return } + if ContainerDevice.orientation == oldOrientation { return } + oldOrientation = ContainerDevice.orientation + + if isPortrait { + shadowButton.isHidden = !layout.backgroundShadowShow + } else { + if let landscapeShadowShow = layout.landscapeBackgroundShadowShow { + shadowButton.isHidden = !landscapeShadowShow + } else { + shadowButton.isHidden = !layout.backgroundShadowShow + } + } + + delegate?.containerControllerRotation(self) + + calculationView() + calculationScrollViewHeight(from: .rotation) + + move(type: moveType, from: .rotation) + } + + // MARK: - Update Layout + + func set(layout: ContainerLayout) { + self.layout = layout + calculationViews() + } + + // MARK: Set + + func set(movingEnabled: Bool) { + layout.movingEnabled = movingEnabled + scrollView?.isScrollEnabled = movingEnabled + panGesture?.isEnabled = movingEnabled + } + + func set(trackingPosition: Bool) { + layout.trackingPosition = trackingPosition + } + + func set(footerPadding: CGFloat) { + layout.footerPadding = footerPadding + calculationViews() + } + + // MARK: Scroll Insets + + func set(scrollIndicatorTop: CGFloat) { + layout.scrollIndicatorInsets = UIEdgeInsets(top: scrollIndicatorTop, left: 0, bottom: layout.scrollIndicatorInsets.bottom, right: 0) + calculationViews() + } + + func set(scrollIndicatorBottom: CGFloat) { + layout.scrollIndicatorInsets = UIEdgeInsets(top: layout.scrollIndicatorInsets.top, left: 0, bottom: scrollIndicatorBottom, right: 0) + calculationViews() + } + + func set(scrollInsetsTop: CGFloat) { + layout.scrollInsets = UIEdgeInsets(top: scrollInsetsTop, left: 0, bottom: layout.scrollInsets.bottom, right: 0) + calculationViews() + } + + func set(scrollInsetsBottom: CGFloat) { + layout.scrollInsets = UIEdgeInsets(top: layout.scrollInsets.top, left: 0, bottom: scrollInsetsBottom, right: 0) + calculationViews() + } + + // MARK: Portrait + + func set(top: CGFloat) { + layout.positions.top = top + } + + func set(middle: CGFloat?) { + layout.positions.middle = middle + } + + func set(bottom: CGFloat) { + layout.positions.bottom = bottom + } + + func set(right: CGFloat) { + layout.insets.right = right + if isPortrait { calculationViews() } + } + + func set(left: CGFloat) { + layout.insets.left = left + if isPortrait { calculationViews() } + } + + func set(backgroundShadowShow: Bool) { + layout.backgroundShadowShow = backgroundShadowShow + if isPortrait { move(type: moveType) } + } + + // MARK: Landscape + + func updateLandscapeLayout() { + if layout.landscapePositions == nil { + layout.landscapePositions = ContainerPosition.zero + } + if layout.landscapeInsets == nil { + layout.landscapeInsets = ContainerInsets.zero + } + } + + func setLandscape(top: CGFloat) { + updateLandscapeLayout() + layout.landscapePositions?.top = top + } + + func setLandscape(middle: CGFloat?) { + updateLandscapeLayout() + layout.landscapePositions?.middle = middle + } + + func setLandscape(bottom: CGFloat) { + updateLandscapeLayout() + layout.landscapePositions?.bottom = bottom + } + + func setLandscape(right: CGFloat) { + updateLandscapeLayout() + layout.landscapeInsets?.right = right + if !isPortrait { calculationViews() } + } + + func setLandscape(left: CGFloat) { + updateLandscapeLayout() + layout.landscapeInsets?.left = left + if !isPortrait { calculationViews() } + } + + func setLandscape(backgroundShadowShow: Bool) { + layout.landscapeBackgroundShadowShow = backgroundShadowShow + if !isPortrait { move(type: moveType) } + } + + + // MARK: - Create Shadow-Button + + private func createShadowButton() { + shadowButton = UIButton(frame: CGRect(x: 0, y: 0, width: ContainerDevice.screenMax, height: ContainerDevice.screenMax)) + shadowButton.isUserInteractionEnabled = false + shadowButton.backgroundColor = .black + shadowButton.alpha = 0.0 + shadowButton.addTarget(self, action: #selector(shadowButtonAction), for: .touchUpInside) + controller?.view.addSubview(shadowButton) + } + + @objc private func shadowButtonAction() { + delegate?.containerControllerShadowClick(self) + } + + // MARK: - Create Container-View + + private func createContainerView() { + let frame = CGRect(x: 0, y: 0, width: deviceWidth, height: deviceHeight * 2) + view = ContainerView(frame: frame) + view.backgroundColor = .white + controller?.view.addSubview(view) + + panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) + panGesture?.isEnabled = layout.movingEnabled + if let panGesture = panGesture { + view.addGestureRecognizer(panGesture) + } + } + + // MARK: - Add Header + + public func removeHeaderView() { + if let headerView = self.headerView { + headerView.removeFromSuperview() + } + headerView = nil + calculationViews() + } + + public func add(headerView: UIView) { + removeHeaderView() + self.headerView = headerView + view.contentView?.addSubview(headerView) + calculationViews() + } + + // MARK: - Add Footer + + public func removeFooterView() { + if let footerView = self.footerView { + footerView.removeFromSuperview() + } + footerView = nil + calculationViews() + } + + public func add(footerView: UIView) { + removeFooterView() + self.footerView = footerView + controller?.view.addSubview(footerView) + calculationViews() + } + + // MARK: - Add ScrollView + + public func removeScrollView() { + if let scroll = self.scrollView { + scroll.removeFromSuperview() + } + scrollView = nil + calculationViews() + } + + public func add(scrollView: UIScrollView) { + removeScrollView() + self.scrollView = scrollView + + scrollView.isScrollEnabled = layout.movingEnabled + scrollView.autoresizingMask = [.flexibleLeftMargin, + .flexibleWidth, + .flexibleRightMargin, + .flexibleTopMargin, + .flexibleHeight, + .flexibleBottomMargin] + + scrollView.isScrollEnabled = (moveType == .top) + + if scrollView.delegate == nil { + scrollView.delegate = self + } + + if let tableAdapterView = scrollView as? TableAdapterView { + tableAdapterView.delegate = self + tableAdapterView.dataSource = self + } + + if let collectionAdapterView = scrollView as? CollectionAdapterView { + collectionAdapterView.delegate = self + collectionAdapterView.dataSource = self + } + + view.contentView?.addSubview(scrollView) + calculationViews() + } + + // MARK: - Pan Gesture + + @objc private func handlePan(_ gesture: UIPanGestureRecognizer) { + + view.layer.removeAllAnimations() + scrollView?.layer.removeAllAnimations() + + switch gesture.state { + case .began: + + panBeginSavePosition = view.transform.ty + + case .changed: + + var transform = view.transform + transform.ty = (panBeginSavePosition + gesture.translation(in: view).y) + + if transform.ty < 0 { + + transform.ty = (positionTop / 2) + + } else if transform.ty < positionTop { + + transform.ty = ((positionTop / 2) + (transform.ty / 2)) + } + + let position = transform.ty + let type: ContainerMoveType = moveType + let from: ContainerFromType = .pan + let animation = false + + changeView(transform: transform) + shadowLevelAlpha(position: position, animation: false) + changeFooterView(position: position) + calculationScrollViewHeight(from: from) + changeMove(position: position, type: type, animation: animation) + + case .ended: + + let velocityY = gesture.velocity(in: view).y + + let type = calculatePositionTypeFrom(velocity: velocityY) + + move(type: type, animation: true, velocity: velocityY, from: .pan) + + default: break + } + } + + + // MARK: - Calculation Views Size + + public func calculationViews() { + calculationView() + calculationScrollViewHeight() + } + + private func calculationView() { + guard let view = view else { return } + + let x: CGFloat = insetsLeft + let width: CGFloat = (deviceWidth - insetsRight - insetsLeft) + + view.frame.origin.x = x + view.frame.size.width = width + view.frame.size.height = deviceHeight * 2 + + if let headerView = headerView { + headerView.frame.origin.x = 0.0 + headerView.frame.origin.y = 0.0 + headerView.frame.size.width = width + } + + if let footerView = footerView { + footerView.frame.origin.x = x + footerView.frame.size.width = width + changeFooterView() + } + } + + // MARK: - Calculation ScrollView Size + + private func calculationScrollViewHeight(position: CGFloat = -1.0, + animation: Bool = false, + from: ContainerFromType = .custom, + velocity: CGFloat = 0.0, + moveType: ContainerMoveType = .custom, + moveTypeOld: ContainerMoveType = .custom) { + + guard let scrollView = scrollView else { return } + scrollView.layer.removeAllAnimations() + + let headerHeight: CGFloat = headerView?.frame.height ?? 0.0 + + var footerInsets: CGFloat = 0.0 + if let footerView = footerView { + footerInsets = deviceHeight - footerView.frame.origin.y + } + + var scrollInsetsBottom: CGFloat = ContainerDevice.isIphoneXBottom + if scrollInsetsBottom < footerInsets { + scrollInsetsBottom = 0.0 + } + + let top: CGFloat = layout.scrollInsets.top + let bottom: CGFloat = layout.scrollInsets.bottom + scrollInsetsBottom + + let indicatorTop: CGFloat = layout.scrollIndicatorInsets.top + let indicatorBottom: CGFloat = layout.scrollIndicatorInsets.bottom + scrollInsetsBottom + + var containerViewPositionY: CGFloat = 0.0 + if position == -1.0 { + containerViewPositionY = view.transform.ty + } else { + containerViewPositionY = position + } + + let width: CGFloat = (deviceWidth - insetsRight - insetsLeft) + var height: CGFloat = (deviceHeight - (headerHeight + footerInsets + containerViewPositionY)) + + if height < 0 { + height = 0 + } + + if animation , + !isScrolling, + footerView == nil, + oldPosition < position, + ((moveType == .middle) && (0 < velocity)) || (moveType == .bottom) { + + height = scrollView.frame.height + } + + scrollView.frame = CGRect(x: 0, y: headerHeight, width: width, height: height) + scrollView.scrollIndicatorInsets = UIEdgeInsets(top: indicatorTop , left: 0, bottom: indicatorBottom, right: 0) + scrollView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: bottom, right: 0) + } + + // MARK: - Position-Type From Velocity + + private func calculatePositionTypeFrom(velocity: CGFloat) -> ContainerMoveType { + + var type: ContainerMoveType + + let position = view.transform.ty + + if middleEnable { + + if position < positionTop { /// <<< (70 Top) + + if 750 < velocity { + + if 2500 < velocity { + type = .bottom /// ↓↓↓ + } else { + type = .middle /// ↓ + } + + } else { + type = .top /// Default + } + + } else if position > positionBottom { /// (300 Bottom) >>> + + if velocity < -750 { + + if velocity < -2000 { + type = .top /// ↑↑↑ + } else { + type = .middle /// ↑ + } + + } else { + type = .bottom /// Default + } + + } else { + + let centerMiddleTop = (((positionMiddle - positionTop) / 2) + positionTop) + let centerBottomMiddle = (((positionBottom - positionMiddle) / 2) + positionMiddle) + + if position < centerMiddleTop { /// ↑↑↑ top ...70 + + if 150 < velocity { + + if 2500 < velocity { + type = .bottom /// ↓↓↓ + } else { + type = .middle /// ↓ + } + + } else { + type = .top /// Default + } + + } else if position < centerBottomMiddle { /// --- + + if velocity < 0 { + + if velocity < -150 { + type = .top /// ↑↑↑ + } else { + type = .middle /// ↑ + } + + } else { + + if 150 < velocity { + type = .bottom /// ↓↓↓ + } else { + type = .middle /// ↓ + } + } + + } else { /// ↓↓↓ + + if velocity < -150 { + + if velocity < -2000 { + type = .top /// ↑↑↑ + } else { + type = .middle /// ↑ + } + + } else { + type = .bottom /// Default + } + } + } + + + } else { + + if position < positionTop { /// <<< (70 Top) + + if 750 < velocity { + type = .bottom /// ↓↓↓ + } else { + type = .top /// Default + } + + } else if position > positionBottom { /// (300 Bottom) >>> + + if velocity < -750 { + type = .top /// ↑↑↑ + } else { + type = .bottom /// Default + } + + } else { /// (pos 150) - Center top...!...bottom + + /// (((300 - 70 = 230) / 2 = 115) + 70) = 185 + + let centerTopBottom = (((positionBottom - positionTop) / 2) + positionTop) + + if position < centerTopBottom { /// ↑↑↑ + + if 150 < velocity { + type = .bottom + } else { + type = .top /// Default + } + + } else { /// ↓↓↓ + + if velocity < -150 { + type = .top + } else { + type = .bottom /// Default + } + } + } + } + return type + } + + // MARK: - Move + + public func move(type: ContainerMoveType, + animation: Bool = true, + velocity: CGFloat = 0.0, + from: ContainerFromType = .custom, + completion: (() -> Void)? = nil) { + + let position = positionMoveFrom(type: type) + + move(position: position, + animation: animation, + type: type, + velocity: velocity, + from: from, + completion: completion) + } + + // MARK: - Move Position + + public func positionMoveFrom(type: ContainerMoveType) -> CGFloat { + + switch type { + case .top: return positionTop + case .middle: + if !middleEnable { return positionBottom } + else { return positionMiddle } + case .bottom: return positionBottom + case .hide: return deviceHeight + case .custom: return 0.0 + } + } + + // MARK: - Move Animtaion + + private var displayVelocity: CGFloat = 0.0 + + public func move(position: CGFloat, + animation: Bool, + type: ContainerMoveType, + velocity: CGFloat = 0.0, + from: ContainerFromType, + completion: (() -> Void)? = nil) { + + if layout.movingEnabled { + scrollView?.isScrollEnabled = (type == .top) + } else { + scrollView?.isScrollEnabled = false + } + + displayVelocity = velocity + + oldMoveType = moveType + let oldMove = moveType + moveType = type + + shadowLevelAlpha(position: position, animation: true) + + let transform = CGAffineTransform(translationX: 0, y: position) + + let animationComp = { [weak self] in + guard let _self = self else { return } + + _self.changeView(transform: transform) + if !_self.layout.trackingPosition { + _self.changeFooterView(position: position) + _self.calculationScrollViewHeight(position: position, animation: animation, from: from, velocity: velocity, moveType: type, moveTypeOld: oldMove) + } + _self.changeMove(position: position, type: type, animation: true) + } + + if animation { + + animationSpringFrom(force: velocity, type: type, animation: animationComp, completion: completion) + + } else { + + changeFooterView(position: position) + changeView(transform: transform) + calculationScrollViewHeight(position: position, animation: animation, from: from, velocity: velocity, moveType: type, moveTypeOld: oldMove) + changeMove(position: position, type: type, animation: false) + + completion?() + } + } + + // MARK: - Tracking Position + + @objc func animationDidUpdate(displayLink: CADisplayLink) { + guard layout.trackingPosition else { return } + guard let presentationLayer = self.view.layer.presentation() else { return } + + let position = presentationLayer.frame.origin.y + changeFooterView(position: position) + calculationScrollViewHeight(position: position, from: .tracking, velocity: displayVelocity, moveType: moveType, moveTypeOld: oldMoveType) + } + + private func changeView(transform: CGAffineTransform) { + oldPosition = view.frame.origin.y + oldTransform = view.transform + view.transform = transform + } + + private func changeMove(position: CGFloat, + type: ContainerMoveType, + animation: Bool) { + + delegate?.containerControllerMove(self, position: position, type: type, animation: animation) + } + + //MARK: - Shadow Alpha Level + + func shadowLevelAlpha(position: CGFloat, + animation: Bool) { + + if animation { + animationSpring(duration: 0.45) { [weak self] in + guard let _self = self else { return } + _self.shadowLevelAlpha(positionY: position) + } + } else { + shadowLevelAlpha(positionY: position) + } + } + + func animationSpring(duration: CGFloat = 0.45, animations: @escaping () -> Void) { + UIView.animate(withDuration: TimeInterval(duration), + delay: 0, + usingSpringWithDamping: 0.8, + initialSpringVelocity: 6.0, + options: [.allowUserInteraction], + animations: animations, + completion: nil) + + } + + func shadowLevelAlpha(positionY: CGFloat) { + + if isPortrait { + shadowButton.isHidden = !layout.backgroundShadowShow + } else { + if let landscapeShadowShow = layout.landscapeBackgroundShadowShow { + shadowButton.isHidden = !landscapeShadowShow + } else { + shadowButton.isHidden = !layout.backgroundShadowShow + } + } + + let alphaMax: CGFloat = 0.45 + + if positionY < positionTop { + + shadowButton.alpha = alphaMax + + } else if positionY < positionMiddle { + let m = positionMiddle - positionTop + let p = positionY - positionTop + let percent = (1.0 - (p / m)) + let result = percent * alphaMax + + shadowButton.alpha = result + } else { + shadowButton.alpha = 0.0 + } + + } + + //MARK: - Change FooterView Position + + func changeFooterView(position: CGFloat? = nil) { + guard let footer = footerView else { return } + + let pos = position ?? positionMoveFrom(type: moveType) + + let header = headerView?.frame.height ?? 0.0 + let rr = deviceHeight - header - footer.frame.height + let result = ((rr - pos) - layout.footerPadding) + + let footerViewPositionDefault = (deviceHeight - footer.frame.height) + + if result < 0 { + footer.frame.origin.y = (footerViewPositionDefault + (result * (-1))) + } else { + footer.frame.origin.y = footerViewPositionDefault + } + + } + + // MARK: - Animation Spring + Force + + func animationSpringFrom(force: CGFloat, + type: ContainerMoveType, + animation: @escaping (() -> Void), + completion: (() -> Void)? = nil) { + + var velocity: CGFloat = 0 + let transformY = view.transform.ty + + if type == .top { + + if force < 0 { + velocity = force * (-1) + } + + } else if type == .bottom { + + velocity = force + + } else if type == .middle { + + if force < 0 { + velocity = force * (-1) + } else { + velocity = force + } + } + + velocity = velocity / 10000 + velocity = velocity * 300 + + + if type == .top { + + if (transformY - positionTop) < 0 { + velocity = velocity * (-1) + } + + } else if type == .bottom { + + if 0 < (transformY - positionBottom) { + velocity = velocity * (-1) + } + } + + var positionY: CGFloat = 0 + + if type == .top { + positionY = (transformY - positionTop) + } else if type == .bottom { + positionY = (transformY - positionBottom) + } else if type == .middle { + positionY = (transformY - positionMiddle) + } else if type == .hide { + positionY = (transformY - deviceHeight) + } + + if positionY < 0 { + positionY = positionY * (-1) + } + + var damping: CGFloat = 0.75 + var duration: CGFloat = 0.65 + + let percent = (1.0 - (transformY / deviceHeight)) + + if 350 < positionY { /// 350... + + velocity = (velocity * percent) / 3.5 + + if 6.5...13.5 ~= velocity { + if velocity < 9.0 { + velocity = 6.5 + } else { + velocity = 13.5 + } + } + + damping = 0.8 + duration = 0.45 + + } else if 200 < positionY { /// 200...350 + + velocity = (velocity * percent) / 2.0 + + if 6.5...13.5 ~= velocity { + if velocity < 9.0 { + velocity = 6.5 + } else { + velocity = 13.5 + } + } + + damping = 0.8 + duration = 0.45 + + } else if 150 < positionY { /// 150...200 + + damping = 0.7 + duration = 0.55 + + velocity = (velocity * percent) / 2.5 + + if 4.7...8.6 ~= velocity { + if velocity < 6.5 { + velocity = 8.6 + } else { + velocity = 4.7 + } + } + + } else if 100 < positionY { /// 100...150 + + velocity = (velocity * percent) / 2.0 + + } else if 50 < positionY { /// 50...100 + + velocity = velocity / 1.5 + + } else if 25 < positionY { /// 25...50 + + // velocity = velocity * 1.5 + + } else if 10 < positionY { /// 10...25 + + velocity = velocity * 1.5 + + } else { /// ...10 + + velocity = velocity * 3.0 + + } + + if duration == 0.65, damping == 0.75 { + if 4.3...7.4 ~= velocity { + if velocity < 5.85 { + velocity = 7.4 + } else { + velocity = 4.3 + } + } + } + + var displayLink: CADisplayLink? + if layout.trackingPosition { + displayLink = CADisplayLink(target: self, selector: #selector(animationDidUpdate)) + displayLink?.preferredFramesPerSecond = 60 + displayLink?.add(to: .main, forMode: .default) + } + + UIView.animate( withDuration: TimeInterval(duration), + delay: 0.0, + usingSpringWithDamping: damping, + initialSpringVelocity: velocity, + options: [ .allowUserInteraction ], + animations: animation, + completion: { _ in + + if let displayLink = displayLink { + displayLink.invalidate() + } + completion?() + }) + + } +} + +// MARK: - Gesture Delegate + +extension ContainerController: UIGestureRecognizerDelegate { + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return false + } + +} + +// MARK: - Table Delegate + +extension ContainerController: UITableViewDelegate { + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if let tableAdapterView = scrollView as? TableAdapterView { + return tableAdapterView.tableView(tableView, heightForRowAt: indexPath) + } + return 0 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if let tableAdapterView = scrollView as? TableAdapterView { + return tableAdapterView.tableView(tableView, didSelectRowAt: indexPath) + } + } + +} + +// MARK: - Table DataSource + +extension ContainerController: UITableViewDataSource { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if let tableAdapterView = scrollView as? TableAdapterView { + return tableAdapterView.tableView(tableView, numberOfRowsInSection: section) + } + return 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if let tableAdapterView = scrollView as? TableAdapterView { + return tableAdapterView.tableView(tableView, cellForRowAt: indexPath) + } + return UITableViewCell() + } + +} + +// MARK: - Collection Delegate + +extension ContainerController: UICollectionViewDelegate { + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if let collectionAdapterView = scrollView as? CollectionAdapterView { + collectionAdapterView.collectionView(collectionView, didSelectItemAt: indexPath) + } + } + +} + +// MARK: - Collection DataSource + +extension ContainerController: UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + if let collectionAdapterView = scrollView as? CollectionAdapterView { + return collectionAdapterView.collectionView(collectionView, numberOfItemsInSection: section) + } + return 0 + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if let collectionAdapterView = scrollView as? CollectionAdapterView { + return collectionAdapterView.collectionView(collectionView, cellForItemAt: indexPath) + } + return UICollectionViewCell() + } +} + +// MARK: - Collection DelegateFlowLayout + +extension ContainerController: UICollectionViewDelegateFlowLayout { + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + if let collectionAdapterView = scrollView as? CollectionAdapterView { + return collectionAdapterView.collectionView(collectionView, layout: collectionViewLayout, sizeForItemAt: indexPath) + } + return CGSize.zero + } +} + +// MARK: - Scroll Delegate + +extension ContainerController: UIScrollViewDelegate { + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + + if let tableAdapterView = scrollView as? TableAdapterView { + tableAdapterView.scrollViewDidScroll(tableAdapterView) + } + + let gesture: UIPanGestureRecognizer = scrollView.panGestureRecognizer + + let inViewVelocityY: CGFloat = gesture.velocity(in: controller?.view).y + let inViewTranslationY: CGFloat = gesture.translation(in: controller?.view).y + + if gesture.state != .possible, scrollView.contentOffset.y <= 0 { + scrollView.showsVerticalScrollIndicator = false + scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: 0) + } else { + scrollView.showsVerticalScrollIndicator = true + } + + if scrollView.contentOffset.y == 0, 0 < inViewVelocityY { + scrollBordersRunContainer = true + } else { + scrollBordersRunContainer = false + } + + scrollTransform = view.transform + + let top: CGFloat = positionTop + + if gesture.state == .ended { + scrollOnceBeginDragging = false + } + + if scrollBordersRunContainer { + + view.layer.removeAllAnimations() + + scrollOnceEnded = false + scrollOnceBeginDragging = false + + scrollTransform.ty = ((top - scrollStartPosition) + inViewTranslationY) + + if scrollTransform.ty < top { + scrollTransform.ty = top + } + + if scrollBegin { + + animationSpring(duration: 0.325) { [weak self] in + guard let _self = self else { return } + _self.changeView(transform: _self.scrollTransform) + } + + scrollBegin = false + + } else { + changeView(transform: scrollTransform) + } + + let position = scrollTransform.ty + let type: ContainerMoveType = .top + let from: ContainerFromType = .scrollBorder + let animation = false + + shadowLevelAlpha(position: position, animation: false) + changeFooterView(position: position) + calculationScrollViewHeight(from: from) + changeMove(position: position, type: type, animation: animation) + + if gesture.state == .ended { + move(type: moveType, animation: true, velocity: inViewVelocityY, from: from) + } + + } else { + + if top == scrollTransform.ty, !scrollOnceBeginDragging { + scrollOnceBeginDragging = true + } + + if top < scrollTransform.ty { + + if inViewVelocityY < 0.0 { + + if moveType == .top { + scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: 0) + } + + scrollTransform = view.transform + scrollTransform.ty = (top - scrollStartPosition) + inViewTranslationY + + if scrollTransform.ty < top { + scrollTransform.ty = top + } + + let position = scrollTransform.ty + let type: ContainerMoveType = .top + let from: ContainerFromType = .scroll + let animation = false + + changeView(transform: scrollTransform) + shadowLevelAlpha(position: position, animation: false) + changeFooterView(position: position) + calculationScrollViewHeight(from: from) + changeMove(position: position, type: type, animation: animation) + } + } + } + } + + // MARK: - Scroll Begin/End Dragging + + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + + isScrolling = true + + scrollStartPosition = scrollView.contentOffset.y + + scrollBegin = true + + if scrollStartPosition < 0 { + scrollStartPosition = 0.0 + } + } + + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + isScrolling = false + } + + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + + if !decelerate { + isScrolling = false + } + + let gesture: UIPanGestureRecognizer = scrollView.panGestureRecognizer + + let inViewVelocityY: CGFloat = gesture.velocity(in: controller?.view).y + + if !scrollOnceEnded { + scrollOnceEnded = true + + let type = calculatePositionTypeFrom(velocity: inViewVelocityY) + + move(type: type, velocity: inViewVelocityY) + } + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerControllerDelegate.swift b/ContainerControllerSwift/Classes/ContainerControllerDelegate.swift new file mode 100644 index 0000000..999e85b --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerControllerDelegate.swift @@ -0,0 +1,36 @@ +// +// ContainerView.swift +// PatternsSwift +// +// Created by mrustaa on 21/04/2020. +// Copyright © 2020 mrustaa. All rights reserved. +// + +import UIKit + +protocol ContainerControllerDelegate { + + /// Reports rotation and orientation changes + func containerControllerRotation(_ containerController: ContainerController) + + /// Reports a click on the background shadow + func containerControllerShadowClick(_ containerController: ContainerController) + + /// Reports the changes current position of the container, after its use + func containerControllerMove(_ containerController: ContainerController, position: CGFloat, type: ContainerMoveType, animation: Bool) + +} + +extension ContainerControllerDelegate { + + func containerControllerRotation(_ containerController: ContainerController) { + } + + + func containerControllerShadowClick(_ containerController: ContainerController) { + } + + func containerControllerMove(_ containerController: ContainerController, position: CGFloat, type: ContainerMoveType, animation: Bool) { + } +} + diff --git a/ContainerControllerSwift/Classes/ContainerDevice.swift b/ContainerControllerSwift/Classes/ContainerDevice.swift new file mode 100644 index 0000000..ad03264 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerDevice.swift @@ -0,0 +1,123 @@ + + +import UIKit + + + +extension ContainerDevice { + + public enum Orientation { + case portrait + case landscapeLeft + case landscapeRight + } +} + +open class ContainerDevice { + + // MARK: - Size + + class public var width: CGFloat { UIScreen.main.bounds.size.width } + class public var height: CGFloat { UIScreen.main.bounds.size.height } + + class public var frame: CGRect { CGRect(x: 0, y: 0, width: width, height: height) } + + // MARK: - Max/Min + + class public var screenMax: CGFloat { max(width, height) } + class public var screenMin: CGFloat { min(width, height) } + + // MARK: - Type + + static public let isIpad = UIDevice.current.userInterfaceIdiom == .pad + static public let isIphone = UIDevice.current.userInterfaceIdiom == .phone + static public let isRetina = UIScreen.main.scale >= 2.0 + + class public var isIphone4: Bool { (isIphone && screenMax < 568.0) } + class public var isIphone5: Bool { (isIphone && screenMax == 568.0) } // SE + class public var isIphone8: Bool { (isIphone && screenMax == 667.0) } // 8 + class public var isIphone8P: Bool { (isIphone && screenMax == 736.0) } // 8 Plus + class public var isIphone11P: Bool { (isIphone && screenMax == 812.0) } // X, 11 Pro + class public var isIphone11: Bool { (isIphone && screenMax == 896.0) } // 11 Max + + class public var isIpad9_7: Bool { (isIpad && screenMax == 1024.0) } // 768 1024 + class public var isIpad10_2: Bool { (isIpad && screenMax == 1080.0) } // 810 1080 + class public var isIpad10_5: Bool { (isIpad && screenMax == 1112.0) } // 834 1112 Air + class public var isIpad11: Bool { (isIpad && screenMax == 1194.0) } // 834 1194 + class public var isIpad12_9: Bool { (isIpad && screenMax == 1366.0) } // 1024 1366 + + class public var isBigIphone: Bool { (isIphone && screenMax > 568.0) } + class public var isIphoneX: Bool { (isIphone && screenMax > 736.0) } + + // MARK: - X Padding + + class public var isIphoneXTop: CGFloat { (isIphoneX ? 24.0 : 0.0) } + class public var isIphoneXBottom: CGFloat { (isIphoneX ? 34.0 : 0.0) } + + // MARK: - StatusBar Height + + class public var statusBarHeight: CGFloat { + var height: CGFloat = 0 + if #available(iOS 13.0, *) { + let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first + height = window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 + } else { + height = UIApplication.shared.statusBarFrame.height + } + return height + } + + // MARK: - Orientation + + class public var isPortrait: Bool { + + var portrait: Bool = false + + let size: CGSize = UIScreen.main.bounds.size + if size.width / size.height > 1 { + portrait = false + } else { + portrait = true + } + + switch UIDevice.current.orientation { + case .landscapeLeft, .landscapeRight: + portrait = false + case .portrait, .portraitUpsideDown: + portrait = true + default: break + } + + return portrait + } + + class var statusBarOrientation: UIInterfaceOrientation? { + get { + guard let orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation else { + #if DEBUG + fatalError("Could not obtain UIInterfaceOrientation from a valid windowScene") + #else + return nil + #endif + } + return orientation + } + } + + class public var orientation: ContainerDevice.Orientation { + if isPortrait { + return .portrait + } else { + if let statusBarOrientation = statusBarOrientation { + if statusBarOrientation == .landscapeLeft { + return .landscapeLeft + } else if statusBarOrientation == .landscapeRight { + return .landscapeRight + } + } + return .landscapeLeft + } + } + + +} diff --git a/ContainerControllerSwift/Classes/ContainerLayout.swift b/ContainerControllerSwift/Classes/ContainerLayout.swift new file mode 100644 index 0000000..14e1d4c --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerLayout.swift @@ -0,0 +1,120 @@ +// +// ContainerView.swift +// PatternsSwift +// +// Created by mrustaa on 21/04/2020. +// Copyright © 2020 mrustaa. All rights reserved. +// + +import UIKit + +// MARK: - Position + +class ContainerPosition { + + var top: CGFloat + + var middle: CGFloat? + + var bottom: CGFloat + + static let zero = ContainerPosition(top: 0, bottom: 0) + + init(top: CGFloat, middle: CGFloat? = nil, bottom: CGFloat) { + self.top = top + self.middle = middle + self.bottom = bottom + } +} + + +// MARK: - Insets + +struct ContainerInsets { + + var right: CGFloat + + var left: CGFloat + + static let zero = ContainerInsets(right: 0, left: 0) + + init(right: CGFloat, left: CGFloat) { + self.right = right + self.left = left + } +} + +// MARK: - Layout + +class ContainerLayout { + + /** + Initialization start position. + */ + var startPosition: ContainerMoveType = .hide + + /** + Disables any moving with gestures. + */ + var movingEnabled: Bool = true + + /** + This is parameters for control footerView. + Padding-top from containerView, if headerView is added, then its + height is summed. + */ + var footerPadding: CGFloat = 0.0 + + /** + This is parameters for control FooterView. + Tracking position ContainerView during animated movement. + */ + var trackingPosition: Bool = false + + /** + This is parameter contentInsets for transmission scrollView added containerView. + */ + var scrollInsets: UIEdgeInsets = UIEdgeInsets.zero + + /** + This is parameter scrollIndicatorInsets for transmission scrollView added containerView. + */ + var scrollIndicatorInsets: UIEdgeInsets = UIEdgeInsets.zero + + /** + This parameter for portrait orientation. + Sets the background shadow under container. + */ + var backgroundShadowShow: Bool = false + + /** + This parameter for Portrait orientation + Sets the new value for positions of animated movement (top, middle, bottom). + */ + var positions: ContainerPosition = ContainerPosition.zero + + /** + This parameter for Portrait orientation. + Insets for containerView (left, right). + */ + var insets: ContainerInsets = ContainerInsets.zero + + /** + This parameter for Landscape orientation. + Sets the background shadow under container. (Default: portrait backgroundShadowShow). + */ + var landscapeBackgroundShadowShow: Bool? + + /** + This parameter for Landscape orientation. + Sets the new value for positions of animated movement (top, middle, bottom). (Default: portrait positions). + */ + var landscapePositions: ContainerPosition? + + /** + This parameter for Landscape orientation. + Insets for containerView (left, right). (Default: portrait insets). + */ + var landscapeInsets: ContainerInsets? + +} + diff --git a/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCell.swift b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCell.swift new file mode 100644 index 0000000..695c208 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCell.swift @@ -0,0 +1,98 @@ +// +// TableAdapterCell.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 17/04/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class TableAdapterCell: UITableViewCell { + + @IBInspectable var hideAnimation: Bool = false + var selectedView: UIView? + + var cellData: TableAdapterCellData? + + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupCommonProperties() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupCommonProperties() + } + + private func setupCommonProperties() { + // self.selectionStyle = .none + } + + open func fill(data: TableAdapterCellData?) { + + } + + let selAlpha: CGFloat = 0.2 // 0.15 + + override func setSelected(_ selected: Bool, animated: Bool) { + + if hideAnimation { + + if selected { + alpha = 0.5 + UIView.animate(withDuration: 0.45) { + self.alpha = 1 + } + } else { + self.alpha = 1 + } + + } else { + if let selectedView = selectedView { + if selected { + selectedView.alpha = selAlpha + UIView.animate(withDuration: 0.45) { + selectedView.alpha = 0.0 + } + } else { + selectedView.alpha = 0.0 + } + } else { + super.setSelected(selected, animated: animated) + } + } + + } + + override func setHighlighted(_ highlighted: Bool, animated: Bool) { + + if hideAnimation { + if highlighted { + UIView.animate(withDuration: 0.1) { + self.alpha = 0.5 + } + } else { + UIView.animate(withDuration: 0.45) { + self.alpha = 1 + } + } + } else { + if let selectedView = selectedView { + if highlighted { + UIView.animate(withDuration: 0.1) { + selectedView.alpha = self.selAlpha + } + } else { + UIView.animate(withDuration: 0.45) { + selectedView.alpha = 0.0 + } + } + } else { + super.setHighlighted(highlighted, animated: animated) + } + } + + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCellData.swift b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCellData.swift new file mode 100644 index 0000000..010e900 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterCellData.swift @@ -0,0 +1,27 @@ +// +// TableAdapterCellData.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 17/04/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class TableAdapterCellData: NSObject { + +// public let cellIdentifier: String +// +// public init(cellIdentifier: String? = UUID().uuidString) { +// self.cellIdentifier = cellIdentifier ?? UUID().uuidString +// } + + open func cellHeight() -> CGFloat { + return UITableView.automaticDimension + } + + open func canEditing() -> Bool { + return false + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerTable/TableAdapterItem.swift b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterItem.swift new file mode 100644 index 0000000..fc8a8e0 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterItem.swift @@ -0,0 +1,34 @@ +// +// TableAdapterItem.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 17/04/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class TableAdapterItem: NSObject { + + public let cellClass: AnyClass + + public let cellData: TableAdapterCellData? + + public var cellReuseIdentifier: String { + return String(describing: cellClass) + } + + init(cellClass: AnyClass, cellData: TableAdapterCellData? = nil) { + self.cellClass = cellClass + self.cellData = cellData + } + + public func height() -> CGFloat { + return cellData?.cellHeight() ?? UITableView.automaticDimension + } + + func canEditing() -> Bool { + return cellData?.canEditing() ?? false + } + +} diff --git a/ContainerControllerSwift/Classes/ContainerTable/TableAdapterTypes.swift b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterTypes.swift new file mode 100644 index 0000000..92c489a --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterTypes.swift @@ -0,0 +1,16 @@ +// +// ContainerTypes.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 21/04/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +typealias TableAdapterCountCallback = () -> Int +typealias TableAdapterCellIndexCallback = (_ index: Int) -> UITableViewCell +typealias TableAdapterHeightIndexCallback = (_ index: Int) -> CGFloat +typealias TableAdapterSelectIndexCallback = (_ index: Int) -> () +typealias TableAdapterDidScrollCallback = () -> () +typealias TableAdapterDeleteIndexCallback = (_ index: Int) -> () diff --git a/ContainerControllerSwift/Classes/ContainerTable/TableAdapterView.swift b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterView.swift new file mode 100644 index 0000000..1a98fb9 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTable/TableAdapterView.swift @@ -0,0 +1,176 @@ +// +// BlockTableView.swift +// PatternsSwift +// +// Created by Рустам Мотыгуллин on 16/04/2020. +// Copyright © 2020 mrusta. All rights reserved. +// + +import UIKit + +class TableAdapterView: UITableView { + + @IBInspectable var separatorClr: UIColor? + + var countCallback: TableAdapterCountCallback? + var cellIndexCallback: TableAdapterCellIndexCallback? + var heightIndexCallback: TableAdapterHeightIndexCallback? + var selectIndexCallback: TableAdapterSelectIndexCallback? + var deleteIndexCallback: TableAdapterDeleteIndexCallback? + var didScrollCallback: TableAdapterDidScrollCallback? + + + var items: [TableAdapterItem] = [] + + required init?(coder: NSCoder) { + super.init(coder: coder) + update() + } + + override init(frame: CGRect, style: UITableView.Style) { + super.init(frame: frame, style: style) + update() + } + + override func draw(_ rect: CGRect) { + if let color = separatorClr { + separatorColor = color + } + } + + func update() { + delegate = self + dataSource = self + + tableFooterView = UIView() + backgroundColor = .clear + } + + func set(items: [TableAdapterItem], animated: Bool = false, reload: Bool = true) { + self.clear() + items.forEach { + self.unsafeAdd(item: $0) + // $0.cellHandler?.delegate = self + } + if reload { reloadData(animated: animated) } + } + + public func clear() { + items.removeAll() + } + + public func reloadData(animated: Bool = false) { + if animated { + self.reloadSections(IndexSet(integer: 0), with: .automatic) + } else { + self.reloadData() + } + } + + + public func scrollToTop() { + self.setContentOffset(CGPoint(x: 0, y: 0), animated: true) + } + + public func unsafeAdd(item: TableAdapterItem) { + items.append(item) + registerNibIfNeeded(for: item) + } + + public func registerNibIfNeeded(for item: TableAdapterItem) { + let nib = UINib(nibName: item.cellReuseIdentifier, bundle: nil) + self.register(nib, forCellReuseIdentifier: item.cellReuseIdentifier) + } + + + private func cellAt(_ indexPath: IndexPath) -> TableAdapterCell? { + let item = items[indexPath.row] + let cellIdentifier = item.cellReuseIdentifier + let cell = self.dequeueReusableCell(withIdentifier: cellIdentifier) as? TableAdapterCell + cell?.cellData = item.cellData + return cell + } +} + +// MARK: DataSource + +extension TableAdapterView: UITableViewDataSource { + + /// колличество + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if !items.isEmpty { + return items.count + } + if let countCallback = countCallback { + return countCallback() + } + return 0 + } + + /// ячейка + public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if !items.isEmpty { + let item = items[indexPath.row] + let cell = cellAt(indexPath) + cell?.fill(data: item.cellData) + return cell ?? UITableViewCell() + } + if let cellIndexCallback = cellIndexCallback { + return cellIndexCallback(indexPath.row) + } + return UITableViewCell() + } + + + func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + if !items.isEmpty { + let item = items[indexPath.row] + return item.canEditing() + } + return false + } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + + items.remove(at: indexPath.row) + self.beginUpdates() + self.deleteRows(at: [indexPath], with: .automatic) + self.endUpdates() + + deleteIndexCallback?(indexPath.row) + } + } +} + +// MARK: Delegate + +extension TableAdapterView: UITableViewDelegate { + + /// высота + public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if !items.isEmpty { + return items[indexPath.row].height() + } + if let heightIndexCallback = heightIndexCallback { + return heightIndexCallback(indexPath.row) + } + return 0 + } + + /// нажал + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + selectIndexCallback?(indexPath.row) + } + +} + +extension TableAdapterView: UIScrollViewDelegate { + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + didScrollCallback?() + } + + +} diff --git a/ContainerControllerSwift/Classes/ContainerTypes.swift b/ContainerControllerSwift/Classes/ContainerTypes.swift new file mode 100644 index 0000000..0a387a3 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerTypes.swift @@ -0,0 +1,27 @@ +// +// ContainerTypes.swift +// PatternsSwift +// +// Created by mrustaa on 21/04/2020. +// Copyright © 2020 mrustaa. All rights reserved. +// + +typealias ContainerCompletion = () -> Void + +public enum ContainerMoveType { + case top + case middle + case bottom + case hide + case custom +} + +enum ContainerFromType { + case pan + case scroll + case scrollBorder + case rotation + case tracking + case custom +} + diff --git a/ContainerControllerSwift/Classes/ContainerView.swift b/ContainerControllerSwift/Classes/ContainerView.swift new file mode 100644 index 0000000..8cc0973 --- /dev/null +++ b/ContainerControllerSwift/Classes/ContainerView.swift @@ -0,0 +1,94 @@ +// +// ContainerView.swift +// PatternsSwift +// +// Created by mrustaa on 21/04/2020. +// Copyright © 2020 mrustaa. All rights reserved. +// + +import UIKit + +class ContainerView: UIView { + + var contentView: UIView? + + var visualEffectView: UIVisualEffectView? + + // MARK: CornerRadius + + var cornerRadius: CGFloat = 0 { + didSet { + let r = radius() + layer.cornerRadius = r + contentView?.layer.cornerRadius = r + contentView?.clipsToBounds = true + visualEffectView?.layer.cornerRadius = r + } + } + + func radius() -> CGFloat { + let minSize = min(frame.width, frame.height) + let radius = (((minSize / 2) < cornerRadius) ? (minSize / 2) : cornerRadius) + return radius + } + + // MARK: Init + + override init(frame: CGRect) { + super.init(frame: frame) + + let contentView = UIView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height)) + contentView.backgroundColor = .clear + contentView.autoresizingMask = [.flexibleLeftMargin, .flexibleWidth, .flexibleRightMargin, .flexibleTopMargin, .flexibleHeight, .flexibleBottomMargin] + addSubview(contentView) + self.contentView = contentView + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + // MARK: Add Custom Shadow + + func addShadow(opacity: CGFloat = 0.1) { + layer.shadowOpacity = Float(opacity) + layer.shadowColor = UIColor.black.cgColor + layer.shadowRadius = 3 + } + + // MARK: Add Blur + + func addBlur(darkStyle: Bool) { + let style: UIBlurEffect.Style = darkStyle ? .systemThinMaterialDark : .systemChromeMaterialLight + backgroundColor = .clear + addBlur(style: style) + } + + func addBlur(style: UIBlurEffect.Style) { + + if visualEffectView == nil { + let blurView = UIVisualEffectView(effect: UIBlurEffect(style: style)) + self.insertSubview(blurView, at: 0) + visualEffectView = blurView + } + + guard let visualEffectView = visualEffectView else { return } + visualEffectView.effect = UIBlurEffect(style: style) + visualEffectView.bounds = bounds + visualEffectView.frame = CGRect(x: 0, y: 0, width: visualEffectView.frame.width, height: visualEffectView.frame.height) + visualEffectView.layer.cornerRadius = radius() + visualEffectView.layer.masksToBounds = true + visualEffectView.autoresizingMask = [.flexibleLeftMargin, .flexibleWidth, .flexibleRightMargin, .flexibleTopMargin, .flexibleHeight, .flexibleBottomMargin] + + } + + // MARK: Remove Blur + + func removeBlur() { + if let visualEffectView = visualEffectView { + visualEffectView.removeFromSuperview() + } + visualEffectView = nil + } + +} diff --git a/ContainerControllerSwift/Classes/ReplaceMe.swift b/ContainerControllerSwift/Classes/ReplaceMe.swift deleted file mode 100644 index e69de29..0000000 diff --git a/Example/ContainerControllerSwift.xcodeproj/project.pbxproj b/Example/ContainerControllerSwift.xcodeproj/project.pbxproj index bd56b5c..a76a19b 100644 --- a/Example/ContainerControllerSwift.xcodeproj/project.pbxproj +++ b/Example/ContainerControllerSwift.xcodeproj/project.pbxproj @@ -30,7 +30,7 @@ /* Begin PBXFileReference section */ 01C7EF19A8C89AA4D02D74D2 /* Pods-ContainerControllerSwift_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerControllerSwift_Tests.debug.xcconfig"; path = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.debug.xcconfig"; sourceTree = ""; }; 0AA8BF39B9F182FE833C0178 /* Pods-ContainerControllerSwift_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerControllerSwift_Example.debug.xcconfig"; path = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.debug.xcconfig"; sourceTree = ""; }; - 1034FE614CC8890CE063531F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; name = README.md; path = ../README.md; sourceTree = ""; }; + 1034FE614CC8890CE063531F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 121FB933CAE3EC5A2A00F4B2 /* Pods_ContainerControllerSwift_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerControllerSwift_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD01AFB9204008FA782 /* ContainerControllerSwift_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ContainerControllerSwift_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -43,10 +43,10 @@ 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 84550121AB9630F101ECE515 /* Pods-ContainerControllerSwift_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerControllerSwift_Example.release.xcconfig"; path = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.release.xcconfig"; sourceTree = ""; }; - 95BE06AF27887E1C134436AD /* ContainerControllerSwift.podspec */ = {isa = PBXFileReference; includeInIndex = 1; name = ContainerControllerSwift.podspec; path = ../ContainerControllerSwift.podspec; sourceTree = ""; }; + 95BE06AF27887E1C134436AD /* ContainerControllerSwift.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = ContainerControllerSwift.podspec; path = ../ContainerControllerSwift.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; D8903A29B31F63B5A7A8607B /* Pods_ContainerControllerSwift_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerControllerSwift_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DF5E269035BE15FBD5F947F3 /* Pods-ContainerControllerSwift_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerControllerSwift_Tests.release.xcconfig"; path = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.release.xcconfig"; sourceTree = ""; }; - E0FB46D7C5BC0F8759A83A60 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + E0FB46D7C5BC0F8759A83A60 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -77,7 +77,6 @@ 01C7EF19A8C89AA4D02D74D2 /* Pods-ContainerControllerSwift_Tests.debug.xcconfig */, DF5E269035BE15FBD5F947F3 /* Pods-ContainerControllerSwift_Tests.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -228,6 +227,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); diff --git a/Example/ContainerControllerSwift.xcworkspace/contents.xcworkspacedata b/Example/ContainerControllerSwift.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..07fc505 --- /dev/null +++ b/Example/ContainerControllerSwift.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Example/ContainerControllerSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/ContainerControllerSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/ContainerControllerSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/Podfile.lock b/Example/Podfile.lock new file mode 100644 index 0000000..e31c676 --- /dev/null +++ b/Example/Podfile.lock @@ -0,0 +1,27 @@ +PODS: + - ContainerControllerSwift (0.1.0) + - FBSnapshotTestCase (2.1.4): + - FBSnapshotTestCase/SwiftSupport (= 2.1.4) + - FBSnapshotTestCase/Core (2.1.4) + - FBSnapshotTestCase/SwiftSupport (2.1.4): + - FBSnapshotTestCase/Core + +DEPENDENCIES: + - ContainerControllerSwift (from `../`) + - FBSnapshotTestCase (~> 2.1.4) + +SPEC REPOS: + https://cdn.cocoapods.org/: + - FBSnapshotTestCase + +EXTERNAL SOURCES: + ContainerControllerSwift: + :path: "../" + +SPEC CHECKSUMS: + ContainerControllerSwift: d9165e33edebeea0b8e0992717b0811328400d3c + FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a + +PODFILE CHECKSUM: 748541873723babe6decea03fbfa834df5db1b55 + +COCOAPODS: 1.9.3 diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h new file mode 100644 index 0000000..eefe11b --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import + +@interface UIApplication (StrictKeyWindow) + +/** + @return The receiver's @c keyWindow. Raises an assertion if @c nil. + */ +- (UIWindow *)fb_strictKeyWindow; + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m new file mode 100644 index 0000000..0f7a0c2 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import + +@implementation UIApplication (StrictKeyWindow) + +- (UIWindow *)fb_strictKeyWindow +{ + UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; + if (!keyWindow) { + [NSException raise:@"FBSnapshotTestCaseNilKeyWindowException" + format:@"Snapshot tests must be hosted by an application with a key window. Please ensure your test" + " host sets up a key window at launch (either via storyboards or programmatically) and doesn't" + " do anything to remove it while snapshot tests are running."]; + } + return keyWindow; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.h new file mode 100644 index 0000000..9091d62 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.h @@ -0,0 +1,37 @@ +// +// Created by Gabriel Handford on 3/1/09. +// Copyright 2009-2013. All rights reserved. +// Created by John Boiles on 10/20/11. +// Copyright (c) 2011. All rights reserved +// Modified by Felix Schulze on 2/11/13. +// Copyright 2013. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import + +@interface UIImage (Compare) + +- (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance; + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.m new file mode 100644 index 0000000..c997f57 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Compare.m @@ -0,0 +1,134 @@ +// +// Created by Gabriel Handford on 3/1/09. +// Copyright 2009-2013. All rights reserved. +// Created by John Boiles on 10/20/11. +// Copyright (c) 2011. All rights reserved +// Modified by Felix Schulze on 2/11/13. +// Copyright 2013. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import + +// This makes debugging much more fun +typedef union { + uint32_t raw; + unsigned char bytes[4]; + struct { + char red; + char green; + char blue; + char alpha; + } __attribute__ ((packed)) pixels; +} FBComparePixel; + +@implementation UIImage (Compare) + +- (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance +{ + NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size."); + + CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); + CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); + + // The images have the equal size, so we could use the smallest amount of bytes because of byte padding + size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); + size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; + void *referenceImagePixels = calloc(1, referenceImageSizeBytes); + void *imagePixels = calloc(1, referenceImageSizeBytes); + + if (!referenceImagePixels || !imagePixels) { + free(referenceImagePixels); + free(imagePixels); + return NO; + } + + CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, + referenceImageSize.width, + referenceImageSize.height, + CGImageGetBitsPerComponent(self.CGImage), + minBytesPerRow, + CGImageGetColorSpace(self.CGImage), + (CGBitmapInfo)kCGImageAlphaPremultipliedLast + ); + CGContextRef imageContext = CGBitmapContextCreate(imagePixels, + imageSize.width, + imageSize.height, + CGImageGetBitsPerComponent(image.CGImage), + minBytesPerRow, + CGImageGetColorSpace(image.CGImage), + (CGBitmapInfo)kCGImageAlphaPremultipliedLast + ); + + if (!referenceImageContext || !imageContext) { + CGContextRelease(referenceImageContext); + CGContextRelease(imageContext); + free(referenceImagePixels); + free(imagePixels); + return NO; + } + + CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); + CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); + + CGContextRelease(referenceImageContext); + CGContextRelease(imageContext); + + BOOL imageEqual = YES; + + // Do a fast compare if we can + if (tolerance == 0) { + imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0); + } else { + // Go through each pixel in turn and see if it is different + const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height; + + FBComparePixel *p1 = referenceImagePixels; + FBComparePixel *p2 = imagePixels; + + NSInteger numDiffPixels = 0; + for (int n = 0; n < pixelCount; ++n) { + // If this pixel is different, increment the pixel diff count and see + // if we have hit our limit. + if (p1->raw != p2->raw) { + numDiffPixels ++; + + CGFloat percent = (CGFloat)numDiffPixels / pixelCount; + if (percent > tolerance) { + imageEqual = NO; + break; + } + } + + p1++; + p2++; + } + } + + free(referenceImagePixels); + free(imagePixels); + + return imageEqual; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.h new file mode 100644 index 0000000..a0863f3 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.h @@ -0,0 +1,37 @@ +// +// Created by Gabriel Handford on 3/1/09. +// Copyright 2009-2013. All rights reserved. +// Created by John Boiles on 10/20/11. +// Copyright (c) 2011. All rights reserved +// Modified by Felix Schulze on 2/11/13. +// Copyright 2013. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import + +@interface UIImage (Diff) + +- (UIImage *)fb_diffWithImage:(UIImage *)image; + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.m new file mode 100644 index 0000000..ebb72fe --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Diff.m @@ -0,0 +1,56 @@ +// +// Created by Gabriel Handford on 3/1/09. +// Copyright 2009-2013. All rights reserved. +// Created by John Boiles on 10/20/11. +// Copyright (c) 2011. All rights reserved +// Modified by Felix Schulze on 2/11/13. +// Copyright 2013. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#import + +@implementation UIImage (Diff) + +- (UIImage *)fb_diffWithImage:(UIImage *)image +{ + if (!image) { + return nil; + } + CGSize imageSize = CGSizeMake(MAX(self.size.width, image.size.width), MAX(self.size.height, image.size.height)); + UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; + CGContextSetAlpha(context, 0.5); + CGContextBeginTransparencyLayer(context, NULL); + [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; + CGContextSetBlendMode(context, kCGBlendModeDifference); + CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor); + CGContextFillRect(context, CGRectMake(0, 0, self.size.width, self.size.height)); + CGContextEndTransparencyLayer(context); + UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return returnImage; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.h new file mode 100644 index 0000000..b0d5b26 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import + +@interface UIImage (Snapshot) + +/// Uses renderInContext: to get a snapshot of the layer. ++ (UIImage *)fb_imageForLayer:(CALayer *)layer; + +/// Uses renderInContext: to get a snapshot of the view layer. ++ (UIImage *)fb_imageForViewLayer:(UIView *)view; + +/// Uses drawViewHierarchyInRect: to get a snapshot of the view and adds the view into a window if needed. ++ (UIImage *)fb_imageForView:(UIView *)view; + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.m new file mode 100644 index 0000000..968091b --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/Categories/UIImage+Snapshot.m @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import + +@implementation UIImage (Snapshot) + ++ (UIImage *)fb_imageForLayer:(CALayer *)layer +{ + CGRect bounds = layer.bounds; + NSAssert1(CGRectGetWidth(bounds), @"Zero width for layer %@", layer); + NSAssert1(CGRectGetHeight(bounds), @"Zero height for layer %@", layer); + + UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + NSAssert1(context, @"Could not generate context for layer %@", layer); + CGContextSaveGState(context); + [layer layoutIfNeeded]; + [layer renderInContext:context]; + CGContextRestoreGState(context); + + UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return snapshot; +} + ++ (UIImage *)fb_imageForViewLayer:(UIView *)view +{ + [view layoutIfNeeded]; + return [self fb_imageForLayer:view.layer]; +} + ++ (UIImage *)fb_imageForView:(UIView *)view +{ + CGRect bounds = view.bounds; + NSAssert1(CGRectGetWidth(bounds), @"Zero width for view %@", view); + NSAssert1(CGRectGetHeight(bounds), @"Zero height for view %@", view); + + // If the input view is already a UIWindow, then just use that. Otherwise wrap in a window. + UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *)view : view.window; + BOOL removeFromSuperview = NO; + if (!window) { + window = [[UIApplication sharedApplication] fb_strictKeyWindow]; + } + + if (!view.window && view != window) { + [window addSubview:view]; + removeFromSuperview = YES; + } + + UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0); + [view layoutIfNeeded]; + [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; + + UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + if (removeFromSuperview) { + [view removeFromSuperview]; + } + + return snapshot; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h new file mode 100644 index 0000000..72abc3c --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import + +#import + +#import + +#import + +/* + There are three ways of setting reference image directories. + + 1. Set the preprocessor macro FB_REFERENCE_IMAGE_DIR to a double quoted + c-string with the path. + 2. Set an environment variable named FB_REFERENCE_IMAGE_DIR with the path. This + takes precedence over the preprocessor macro to allow for run-time override. + 3. Keep everything unset, which will cause the reference images to be looked up + inside the bundle holding the current test, in the + Resources/ReferenceImages_* directories. + */ +#ifndef FB_REFERENCE_IMAGE_DIR +#define FB_REFERENCE_IMAGE_DIR "" +#endif + +/** + Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. + @param view The view to snapshot + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param suffixes An NSOrderedSet of strings for the different suffixes + @param tolerance The percentage of pixels that can differ and still count as an 'identical' view + */ +#define FBSnapshotVerifyViewWithOptions(view__, identifier__, suffixes__, tolerance__) \ + FBSnapshotVerifyViewOrLayerWithOptions(View, view__, identifier__, suffixes__, tolerance__) + +#define FBSnapshotVerifyView(view__, identifier__) \ + FBSnapshotVerifyViewWithOptions(view__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) + + +/** + Similar to our much-loved XCTAssert() macros. Use this to perform your test. No need to write an explanation, though. + @param layer The layer to snapshot + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param suffixes An NSOrderedSet of strings for the different suffixes + @param tolerance The percentage of pixels that can differ and still count as an 'identical' layer + */ +#define FBSnapshotVerifyLayerWithOptions(layer__, identifier__, suffixes__, tolerance__) \ + FBSnapshotVerifyViewOrLayerWithOptions(Layer, layer__, identifier__, suffixes__, tolerance__) + +#define FBSnapshotVerifyLayer(layer__, identifier__) \ + FBSnapshotVerifyLayerWithOptions(layer__, identifier__, FBSnapshotTestCaseDefaultSuffixes(), 0) + + +#define FBSnapshotVerifyViewOrLayerWithOptions(what__, viewOrLayer__, identifier__, suffixes__, tolerance__) \ +{ \ + NSString *errorDescription = [self snapshotVerifyViewOrLayer:viewOrLayer__ identifier:identifier__ suffixes:suffixes__ tolerance:tolerance__]; \ + BOOL noErrors = (errorDescription == nil); \ + XCTAssertTrue(noErrors, @"%@", errorDescription); \ +} + + +/** + The base class of view snapshotting tests. If you have small UI component, it's often easier to configure it in a test + and compare an image of the view to a reference image that write lots of complex layout-code tests. + + In order to flip the tests in your subclass to record the reference images set @c recordMode to @c YES. + + @attention When recording, the reference image directory should be explicitly + set, otherwise the images may be written to somewhere inside the + simulator directory. + + For example: + @code + - (void)setUp + { + [super setUp]; + self.recordMode = YES; + } + @endcode + */ +@interface FBSnapshotTestCase : XCTestCase + +/** + When YES, the test macros will save reference images, rather than performing an actual test. + */ +@property (readwrite, nonatomic, assign) BOOL recordMode; + +/** + When @c YES appends the name of the device model and OS to the snapshot file name. + The default value is @c NO. + */ +@property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; + +/** + When YES, renders a snapshot of the complete view hierarchy as visible onscreen. + There are several things that do not work if renderInContext: is used. + - UIVisualEffect #70 + - UIAppearance #91 + - Size Classes #92 + + @attention If the view does't belong to a UIWindow, it will create one and add the view as a subview. + */ +@property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; + +- (void)setUp NS_REQUIRES_SUPER; +- (void)tearDown NS_REQUIRES_SUPER; + +/** + Performs the comparison or records a snapshot of the layer if recordMode is YES. + @param viewOrLayer The UIView or CALayer to snapshot + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param suffixes An NSOrderedSet of strings for the different suffixes + @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care + @returns nil if the comparison (or saving of the reference image) succeeded. Otherwise it contains an error description. + */ +- (NSString *)snapshotVerifyViewOrLayer:(id)viewOrLayer + identifier:(NSString *)identifier + suffixes:(NSOrderedSet *)suffixes + tolerance:(CGFloat)tolerance; + +/** + Performs the comparison or records a snapshot of the layer if recordMode is YES. + @param layer The Layer to snapshot + @param referenceImagesDirectory The directory in which reference images are stored. + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care + @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if the comparison (or saving of the reference image) succeeded. + */ +- (BOOL)compareSnapshotOfLayer:(CALayer *)layer + referenceImagesDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr; + +/** + Performs the comparison or records a snapshot of the view if recordMode is YES. + @param view The view to snapshot + @param referenceImagesDirectory The directory in which reference images are stored. + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param tolerance The percentage difference to still count as identical - 0 mean pixel perfect, 1 means I don't care + @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if the comparison (or saving of the reference image) succeeded. + */ +- (BOOL)compareSnapshotOfView:(UIView *)view + referenceImagesDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr; + +/** + Checks if reference image with identifier based name exists in the reference images directory. + @param referenceImagesDirectory The directory in which reference images are stored. + @param identifier An optional identifier, used if there are multiple snapshot tests in a given -test method. + @param errorPtr An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if reference image exists. + */ +- (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + error:(NSError **)errorPtr; + +/** + Returns the reference image directory. + + Helper function used to implement the assert macros. + + @param dir directory to use if environment variable not specified. Ignored if null or empty. + */ +- (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir; + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m new file mode 100644 index 0000000..f44458c --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCase.m @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import + +@implementation FBSnapshotTestCase +{ + FBSnapshotTestController *_snapshotController; +} + +#pragma mark - Overrides + +- (void)setUp +{ + [super setUp]; + _snapshotController = [[FBSnapshotTestController alloc] initWithTestName:NSStringFromClass([self class])]; +} + +- (void)tearDown +{ + _snapshotController = nil; + [super tearDown]; +} + +- (BOOL)recordMode +{ + return _snapshotController.recordMode; +} + +- (void)setRecordMode:(BOOL)recordMode +{ + NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); + _snapshotController.recordMode = recordMode; +} + +- (BOOL)isDeviceAgnostic +{ + return _snapshotController.deviceAgnostic; +} + +- (void)setDeviceAgnostic:(BOOL)deviceAgnostic +{ + NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); + _snapshotController.deviceAgnostic = deviceAgnostic; +} + +- (BOOL)usesDrawViewHierarchyInRect +{ + return _snapshotController.usesDrawViewHierarchyInRect; +} + +- (void)setUsesDrawViewHierarchyInRect:(BOOL)usesDrawViewHierarchyInRect +{ + NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); + _snapshotController.usesDrawViewHierarchyInRect = usesDrawViewHierarchyInRect; +} + +#pragma mark - Public API + +- (NSString *)snapshotVerifyViewOrLayer:(id)viewOrLayer + identifier:(NSString *)identifier + suffixes:(NSOrderedSet *)suffixes + tolerance:(CGFloat)tolerance +{ + if (nil == viewOrLayer) { + return @"Object to be snapshotted must not be nil"; + } + NSString *referenceImageDirectory = [self getReferenceImageDirectoryWithDefault:(@ FB_REFERENCE_IMAGE_DIR)]; + if (referenceImageDirectory == nil) { + return @"Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme."; + } + if (suffixes.count == 0) { + return [NSString stringWithFormat:@"Suffixes set cannot be empty %@", suffixes]; + } + + BOOL testSuccess = NO; + NSError *error = nil; + NSMutableArray *errors = [NSMutableArray array]; + + if (self.recordMode) { + NSString *referenceImagesDirectory = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffixes.firstObject]; + BOOL referenceImageSaved = [self _compareSnapshotOfViewOrLayer:viewOrLayer referenceImagesDirectory:referenceImagesDirectory identifier:(identifier) tolerance:tolerance error:&error]; + if (!referenceImageSaved) { + [errors addObject:error]; + } + } else { + for (NSString *suffix in suffixes) { + NSString *referenceImagesDirectory = [NSString stringWithFormat:@"%@%@", referenceImageDirectory, suffix]; + BOOL referenceImageAvailable = [self referenceImageRecordedInDirectory:referenceImagesDirectory identifier:(identifier) error:&error]; + + if (referenceImageAvailable) { + BOOL comparisonSuccess = [self _compareSnapshotOfViewOrLayer:viewOrLayer referenceImagesDirectory:referenceImagesDirectory identifier:identifier tolerance:tolerance error:&error]; + [errors removeAllObjects]; + if (comparisonSuccess) { + testSuccess = YES; + break; + } else { + [errors addObject:error]; + } + } else { + [errors addObject:error]; + } + } + } + + if (!testSuccess) { + return [NSString stringWithFormat:@"Snapshot comparison failed: %@", errors.firstObject]; + } + if (self.recordMode) { + return @"Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!"; + } + + return nil; +} + +- (BOOL)compareSnapshotOfLayer:(CALayer *)layer + referenceImagesDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + return [self _compareSnapshotOfViewOrLayer:layer + referenceImagesDirectory:referenceImagesDirectory + identifier:identifier + tolerance:tolerance + error:errorPtr]; +} + +- (BOOL)compareSnapshotOfView:(UIView *)view + referenceImagesDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + return [self _compareSnapshotOfViewOrLayer:view + referenceImagesDirectory:referenceImagesDirectory + identifier:identifier + tolerance:tolerance + error:errorPtr]; +} + +- (BOOL)referenceImageRecordedInDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + NSAssert1(_snapshotController, @"%s cannot be called before [super setUp]", __FUNCTION__); + _snapshotController.referenceImagesDirectory = referenceImagesDirectory; + UIImage *referenceImage = [_snapshotController referenceImageForSelector:self.invocation.selector + identifier:identifier + error:errorPtr]; + + return (referenceImage != nil); +} + +- (NSString *)getReferenceImageDirectoryWithDefault:(NSString *)dir +{ + NSString *envReferenceImageDirectory = [NSProcessInfo processInfo].environment[@"FB_REFERENCE_IMAGE_DIR"]; + if (envReferenceImageDirectory) { + return envReferenceImageDirectory; + } + if (dir && dir.length > 0) { + return dir; + } + return [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:@"ReferenceImages"]; +} + + +#pragma mark - Private API + +- (BOOL)_compareSnapshotOfViewOrLayer:(id)viewOrLayer + referenceImagesDirectory:(NSString *)referenceImagesDirectory + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + _snapshotController.referenceImagesDirectory = referenceImagesDirectory; + return [_snapshotController compareSnapshotOfViewOrLayer:viewOrLayer + selector:self.invocation.selector + identifier:identifier + tolerance:tolerance + error:errorPtr]; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h new file mode 100644 index 0000000..e04acf2 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Returns a Boolean value that indicates whether the snapshot test is running in 64Bit. + This method is a convenience for creating the suffixes set based on the architecture + that the test is running. + + @returns @c YES if the test is running in 64bit, otherwise @c NO. + */ +BOOL FBSnapshotTestCaseIs64Bit(void); + +/** + Returns a default set of strings that is used to append a suffix based on the architectures. + @warning Do not modify this function, you can create your own and use it with @c FBSnapshotVerifyViewWithOptions() + + @returns An @c NSOrderedSet object containing strings that are appended to the reference images directory. + */ +NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void); + +/** + Returns a fully «normalized» file name. + Strips punctuation and spaces and replaces them with @c _. Also appends the device model, running OS and screen size to the file name. + + @returns An @c NSString object containing the passed @c fileName with the device model, OS and screen size appended at the end. + */ +NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName); + +#ifdef __cplusplus +} +#endif diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m new file mode 100644 index 0000000..d8709d8 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestCasePlatform.m @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import +#import + +BOOL FBSnapshotTestCaseIs64Bit(void) +{ +#if __LP64__ + return YES; +#else + return NO; +#endif +} + +NSOrderedSet *FBSnapshotTestCaseDefaultSuffixes(void) +{ + NSMutableOrderedSet *suffixesSet = [[NSMutableOrderedSet alloc] init]; + [suffixesSet addObject:@"_32"]; + [suffixesSet addObject:@"_64"]; + if (FBSnapshotTestCaseIs64Bit()) { + return [suffixesSet reversedOrderedSet]; + } + return [suffixesSet copy]; +} + +NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName) +{ + UIDevice *device = [UIDevice currentDevice]; + UIWindow *keyWindow = [[UIApplication sharedApplication] fb_strictKeyWindow]; + CGSize screenSize = keyWindow.bounds.size; + NSString *os = device.systemVersion; + + fileName = [NSString stringWithFormat:@"%@_%@%@_%.0fx%.0f", fileName, device.model, os, screenSize.width, screenSize.height]; + + NSMutableCharacterSet *invalidCharacters = [NSMutableCharacterSet new]; + [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; + [invalidCharacters formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; + NSArray *validComponents = [fileName componentsSeparatedByCharactersInSet:invalidCharacters]; + fileName = [validComponents componentsJoinedByString:@"_"]; + + return fileName; +} \ No newline at end of file diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h new file mode 100644 index 0000000..a0285ad --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import + +typedef NS_ENUM(NSInteger, FBSnapshotTestControllerErrorCode) { + FBSnapshotTestControllerErrorCodeUnknown, + FBSnapshotTestControllerErrorCodeNeedsRecord, + FBSnapshotTestControllerErrorCodePNGCreationFailed, + FBSnapshotTestControllerErrorCodeImagesDifferentSizes, + FBSnapshotTestControllerErrorCodeImagesDifferent, +}; +/** + Errors returned by the methods of FBSnapshotTestController use this domain. + */ +extern NSString *const FBSnapshotTestControllerErrorDomain; + +/** + Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. + */ +extern NSString *const FBReferenceImageFilePathKey; + +/** + Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. + */ +extern NSString *const FBReferenceImageKey; + +/** + Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. + */ +extern NSString *const FBCapturedImageKey; + +/** + Errors returned by the methods of FBSnapshotTestController sometimes contain this key in the `userInfo` dictionary. + */ +extern NSString *const FBDiffedImageKey; + +/** + Provides the heavy-lifting for FBSnapshotTestCase. It loads and saves images, along with performing the actual pixel- + by-pixel comparison of images. + Instances are initialized with the test class, and directories to read and write to. + */ +@interface FBSnapshotTestController : NSObject + +/** + Record snapshots. + */ +@property (readwrite, nonatomic, assign) BOOL recordMode; + +/** + When @c YES appends the name of the device model and OS to the snapshot file name. + The default value is @c NO. + */ +@property (readwrite, nonatomic, assign, getter=isDeviceAgnostic) BOOL deviceAgnostic; + +/** + Uses drawViewHierarchyInRect:afterScreenUpdates: to draw the image instead of renderInContext: + */ +@property (readwrite, nonatomic, assign) BOOL usesDrawViewHierarchyInRect; + +/** + The directory in which referfence images are stored. + */ +@property (readwrite, nonatomic, copy) NSString *referenceImagesDirectory; + +/** + @param testClass The subclass of FBSnapshotTestCase that is using this controller. + @returns An instance of FBSnapshotTestController. + */ +- (instancetype)initWithTestClass:(Class)testClass; + +/** + Designated initializer. + @param testName The name of the tests. + @returns An instance of FBSnapshotTestController. + */ +- (instancetype)initWithTestName:(NSString *)testName; + +/** + Performs the comparison of the layer. + @param layer The Layer to snapshot. + @param selector The test method being run. + @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. + @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if the comparison (or saving of the reference image) succeeded. + */ +- (BOOL)compareSnapshotOfLayer:(CALayer *)layer + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr; + +/** + Performs the comparison of the view. + @param view The view to snapshot. + @param selector The test method being run. + @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. + @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if the comparison (or saving of the reference image) succeeded. + */ +- (BOOL)compareSnapshotOfView:(UIView *)view + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr; + +/** + Performs the comparison of a view or layer. + @param view The view or layer to snapshot. + @param selector The test method being run. + @param identifier An optional identifier, used is there are muliptle snapshot tests in a given -test method. + @param tolerance The percentage of pixels that can differ and still be considered 'identical' + @param error An error to log in an XCTAssert() macro if the method fails (missing reference image, images differ, etc). + @returns YES if the comparison (or saving of the reference image) succeeded. + */ +- (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer + selector:(SEL)selector + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr; + +/** + Loads a reference image. + @param selector The test method being run. + @param identifier The optional identifier, used when multiple images are tested in a single -test method. + @param errorPtr An error, if this methods returns nil, the error will be something useful. + @returns An image. + */ +- (UIImage *)referenceImageForSelector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr; + +/** + Performs a pixel-by-pixel comparison of the two images with an allowable margin of error. + @param referenceImage The reference (correct) image. + @param image The image to test against the reference. + @param tolerance The percentage of pixels that can differ and still be considered 'identical' + @param errorPtr An error that indicates why the comparison failed if it does. + @returns YES if the comparison succeeded and the images are the same(ish). + */ +- (BOOL)compareReferenceImage:(UIImage *)referenceImage + toImage:(UIImage *)image + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr; + +/** + Saves the reference image and the test image to `failedOutputDirectory`. + @param referenceImage The reference (correct) image. + @param testImage The image to test against the reference. + @param selector The test method being run. + @param identifier The optional identifier, used when multiple images are tested in a single -test method. + @param errorPtr An error that indicates why the comparison failed if it does. + @returns YES if the save succeeded. + */ +- (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage + testImage:(UIImage *)testImage + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr; +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m new file mode 100644 index 0000000..74c5a0a --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/FBSnapshotTestController.m @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + */ + +#import +#import +#import +#import +#import + +#import + +NSString *const FBSnapshotTestControllerErrorDomain = @"FBSnapshotTestControllerErrorDomain"; +NSString *const FBReferenceImageFilePathKey = @"FBReferenceImageFilePathKey"; +NSString *const FBReferenceImageKey = @"FBReferenceImageKey"; +NSString *const FBCapturedImageKey = @"FBCapturedImageKey"; +NSString *const FBDiffedImageKey = @"FBDiffedImageKey"; + +typedef NS_ENUM(NSUInteger, FBTestSnapshotFileNameType) { + FBTestSnapshotFileNameTypeReference, + FBTestSnapshotFileNameTypeFailedReference, + FBTestSnapshotFileNameTypeFailedTest, + FBTestSnapshotFileNameTypeFailedTestDiff, +}; + +@implementation FBSnapshotTestController +{ + NSString *_testName; + NSFileManager *_fileManager; +} + +#pragma mark - Initializers + +- (instancetype)initWithTestClass:(Class)testClass; +{ + return [self initWithTestName:NSStringFromClass(testClass)]; +} + +- (instancetype)initWithTestName:(NSString *)testName +{ + if (self = [super init]) { + _testName = [testName copy]; + _deviceAgnostic = NO; + + _fileManager = [[NSFileManager alloc] init]; + } + return self; +} + +#pragma mark - Overrides + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ %@", [super description], _referenceImagesDirectory]; +} + +#pragma mark - Public API + +- (BOOL)compareSnapshotOfLayer:(CALayer *)layer + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + return [self compareSnapshotOfViewOrLayer:layer + selector:selector + identifier:identifier + tolerance:0 + error:errorPtr]; +} + +- (BOOL)compareSnapshotOfView:(UIView *)view + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + return [self compareSnapshotOfViewOrLayer:view + selector:selector + identifier:identifier + tolerance:0 + error:errorPtr]; +} + +- (BOOL)compareSnapshotOfViewOrLayer:(id)viewOrLayer + selector:(SEL)selector + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + if (self.recordMode) { + return [self _recordSnapshotOfViewOrLayer:viewOrLayer selector:selector identifier:identifier error:errorPtr]; + } else { + return [self _performPixelComparisonWithViewOrLayer:viewOrLayer selector:selector identifier:identifier tolerance:tolerance error:errorPtr]; + } +} + +- (UIImage *)referenceImageForSelector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; + UIImage *image = [UIImage imageWithContentsOfFile:filePath]; + if (nil == image && NULL != errorPtr) { + BOOL exists = [_fileManager fileExistsAtPath:filePath]; + if (!exists) { + *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain + code:FBSnapshotTestControllerErrorCodeNeedsRecord + userInfo:@{ + FBReferenceImageFilePathKey: filePath, + NSLocalizedDescriptionKey: @"Unable to load reference image.", + NSLocalizedFailureReasonErrorKey: @"Reference image not found. You need to run the test in record mode", + }]; + } else { + *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain + code:FBSnapshotTestControllerErrorCodeUnknown + userInfo:nil]; + } + } + return image; +} + +- (BOOL)compareReferenceImage:(UIImage *)referenceImage + toImage:(UIImage *)image + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + BOOL sameImageDimensions = CGSizeEqualToSize(referenceImage.size, image.size); + if (sameImageDimensions && [referenceImage fb_compareWithImage:image tolerance:tolerance]) { + return YES; + } + + if (NULL != errorPtr) { + NSString *errorDescription = sameImageDimensions ? @"Images different" : @"Images different sizes"; + NSString *errorReason = sameImageDimensions ? [NSString stringWithFormat:@"image pixels differed by more than %.2f%% from the reference image", tolerance * 100] + : [NSString stringWithFormat:@"referenceImage:%@, image:%@", NSStringFromCGSize(referenceImage.size), NSStringFromCGSize(image.size)]; + FBSnapshotTestControllerErrorCode errorCode = sameImageDimensions ? FBSnapshotTestControllerErrorCodeImagesDifferent : FBSnapshotTestControllerErrorCodeImagesDifferentSizes; + + *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain + code:errorCode + userInfo:@{ + NSLocalizedDescriptionKey: errorDescription, + NSLocalizedFailureReasonErrorKey: errorReason, + FBReferenceImageKey: referenceImage, + FBCapturedImageKey: image, + FBDiffedImageKey: [referenceImage fb_diffWithImage:image], + }]; + } + return NO; +} + +- (BOOL)saveFailedReferenceImage:(UIImage *)referenceImage + testImage:(UIImage *)testImage + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + NSData *referencePNGData = UIImagePNGRepresentation(referenceImage); + NSData *testPNGData = UIImagePNGRepresentation(testImage); + + NSString *referencePath = [self _failedFilePathForSelector:selector + identifier:identifier + fileNameType:FBTestSnapshotFileNameTypeFailedReference]; + + NSError *creationError = nil; + BOOL didCreateDir = [_fileManager createDirectoryAtPath:[referencePath stringByDeletingLastPathComponent] + withIntermediateDirectories:YES + attributes:nil + error:&creationError]; + if (!didCreateDir) { + if (NULL != errorPtr) { + *errorPtr = creationError; + } + return NO; + } + + if (![referencePNGData writeToFile:referencePath options:NSDataWritingAtomic error:errorPtr]) { + return NO; + } + + NSString *testPath = [self _failedFilePathForSelector:selector + identifier:identifier + fileNameType:FBTestSnapshotFileNameTypeFailedTest]; + + if (![testPNGData writeToFile:testPath options:NSDataWritingAtomic error:errorPtr]) { + return NO; + } + + NSString *diffPath = [self _failedFilePathForSelector:selector + identifier:identifier + fileNameType:FBTestSnapshotFileNameTypeFailedTestDiff]; + + UIImage *diffImage = [referenceImage fb_diffWithImage:testImage]; + NSData *diffImageData = UIImagePNGRepresentation(diffImage); + + if (![diffImageData writeToFile:diffPath options:NSDataWritingAtomic error:errorPtr]) { + return NO; + } + + NSLog(@"If you have Kaleidoscope installed you can run this command to see an image diff:\n" + @"ksdiff \"%@\" \"%@\"", referencePath, testPath); + + return YES; +} + +#pragma mark - Private API + +- (NSString *)_fileNameForSelector:(SEL)selector + identifier:(NSString *)identifier + fileNameType:(FBTestSnapshotFileNameType)fileNameType +{ + NSString *fileName = nil; + switch (fileNameType) { + case FBTestSnapshotFileNameTypeFailedReference: + fileName = @"reference_"; + break; + case FBTestSnapshotFileNameTypeFailedTest: + fileName = @"failed_"; + break; + case FBTestSnapshotFileNameTypeFailedTestDiff: + fileName = @"diff_"; + break; + default: + fileName = @""; + break; + } + fileName = [fileName stringByAppendingString:NSStringFromSelector(selector)]; + if (0 < identifier.length) { + fileName = [fileName stringByAppendingFormat:@"_%@", identifier]; + } + + if (self.isDeviceAgnostic) { + fileName = FBDeviceAgnosticNormalizedFileName(fileName); + } + + if ([[UIScreen mainScreen] scale] > 1) { + fileName = [fileName stringByAppendingFormat:@"@%.fx", [[UIScreen mainScreen] scale]]; + } + fileName = [fileName stringByAppendingPathExtension:@"png"]; + return fileName; +} + +- (NSString *)_referenceFilePathForSelector:(SEL)selector + identifier:(NSString *)identifier +{ + NSString *fileName = [self _fileNameForSelector:selector + identifier:identifier + fileNameType:FBTestSnapshotFileNameTypeReference]; + NSString *filePath = [_referenceImagesDirectory stringByAppendingPathComponent:_testName]; + filePath = [filePath stringByAppendingPathComponent:fileName]; + return filePath; +} + +- (NSString *)_failedFilePathForSelector:(SEL)selector + identifier:(NSString *)identifier + fileNameType:(FBTestSnapshotFileNameType)fileNameType +{ + NSString *fileName = [self _fileNameForSelector:selector + identifier:identifier + fileNameType:fileNameType]; + NSString *folderPath = NSTemporaryDirectory(); + if (getenv("IMAGE_DIFF_DIR")) { + folderPath = @(getenv("IMAGE_DIFF_DIR")); + } + NSString *filePath = [folderPath stringByAppendingPathComponent:_testName]; + filePath = [filePath stringByAppendingPathComponent:fileName]; + return filePath; +} + +- (BOOL)_performPixelComparisonWithViewOrLayer:(id)viewOrLayer + selector:(SEL)selector + identifier:(NSString *)identifier + tolerance:(CGFloat)tolerance + error:(NSError **)errorPtr +{ + UIImage *referenceImage = [self referenceImageForSelector:selector identifier:identifier error:errorPtr]; + if (nil != referenceImage) { + UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; + BOOL imagesSame = [self compareReferenceImage:referenceImage toImage:snapshot tolerance:tolerance error:errorPtr]; + if (!imagesSame) { + NSError *saveError = nil; + if ([self saveFailedReferenceImage:referenceImage testImage:snapshot selector:selector identifier:identifier error:&saveError] == NO) { + NSLog(@"Error saving test images: %@", saveError); + } + } + return imagesSame; + } + return NO; +} + +- (BOOL)_recordSnapshotOfViewOrLayer:(id)viewOrLayer + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + UIImage *snapshot = [self _imageForViewOrLayer:viewOrLayer]; + return [self _saveReferenceImage:snapshot selector:selector identifier:identifier error:errorPtr]; +} + +- (BOOL)_saveReferenceImage:(UIImage *)image + selector:(SEL)selector + identifier:(NSString *)identifier + error:(NSError **)errorPtr +{ + BOOL didWrite = NO; + if (nil != image) { + NSString *filePath = [self _referenceFilePathForSelector:selector identifier:identifier]; + NSData *pngData = UIImagePNGRepresentation(image); + if (nil != pngData) { + NSError *creationError = nil; + BOOL didCreateDir = [_fileManager createDirectoryAtPath:[filePath stringByDeletingLastPathComponent] + withIntermediateDirectories:YES + attributes:nil + error:&creationError]; + if (!didCreateDir) { + if (NULL != errorPtr) { + *errorPtr = creationError; + } + return NO; + } + didWrite = [pngData writeToFile:filePath options:NSDataWritingAtomic error:errorPtr]; + if (didWrite) { + NSLog(@"Reference image save at: %@", filePath); + } + } else { + if (nil != errorPtr) { + *errorPtr = [NSError errorWithDomain:FBSnapshotTestControllerErrorDomain + code:FBSnapshotTestControllerErrorCodePNGCreationFailed + userInfo:@{ + FBReferenceImageFilePathKey: filePath, + }]; + } + } + } + return didWrite; +} + +- (UIImage *)_imageForViewOrLayer:(id)viewOrLayer +{ + if ([viewOrLayer isKindOfClass:[UIView class]]) { + if (_usesDrawViewHierarchyInRect) { + return [UIImage fb_imageForView:viewOrLayer]; + } else { + return [UIImage fb_imageForViewLayer:viewOrLayer]; + } + } else if ([viewOrLayer isKindOfClass:[CALayer class]]) { + return [UIImage fb_imageForLayer:viewOrLayer]; + } else { + [NSException raise:@"Only UIView and CALayer classes can be snapshotted" format:@"%@", viewOrLayer]; + } + return nil; +} + +@end diff --git a/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift new file mode 100644 index 0000000..471bb0d --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/FBSnapshotTestCase/SwiftSupport.swift @@ -0,0 +1,125 @@ +/* +* Copyright (c) 2015, Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the BSD-style license found in the +* LICENSE file in the root directory of this source tree. An additional grant +* of patent rights can be found in the PATENTS file in the same directory. +* +*/ + +#if swift(>=3) + public extension FBSnapshotTestCase { + public func FBSnapshotVerifyView(_ view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + FBSnapshotVerifyViewOrLayer(view, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) + } + + public func FBSnapshotVerifyLayer(_ layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + FBSnapshotVerifyViewOrLayer(layer, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) + } + + private func FBSnapshotVerifyViewOrLayer(_ viewOrLayer: AnyObject, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + let envReferenceImageDirectory = self.getReferenceImageDirectory(withDefault: FB_REFERENCE_IMAGE_DIR) + var error: NSError? + var comparisonSuccess = false + + if let envReferenceImageDirectory = envReferenceImageDirectory { + for suffix in suffixes { + let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)" + if viewOrLayer.isKind(of: UIView.self) { + do { + try compareSnapshot(of: viewOrLayer as! UIView, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) + comparisonSuccess = true + } catch let error1 as NSError { + error = error1 + comparisonSuccess = false + } + } else if viewOrLayer.isKind(of: CALayer.self) { + do { + try compareSnapshot(of: viewOrLayer as! CALayer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) + comparisonSuccess = true + } catch let error1 as NSError { + error = error1 + comparisonSuccess = false + } + } else { + assertionFailure("Only UIView and CALayer classes can be snapshotted") + } + + assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line) + + if comparisonSuccess || recordMode { + break + } + + assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line) + } + } else { + XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.") + } + } + + func assert(_ assertion: Bool, message: String, file: StaticString, line: UInt) { + if !assertion { + XCTFail(message, file: file, line: line) + } + } + } +#else +public extension FBSnapshotTestCase { + public func FBSnapshotVerifyView(view: UIView, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + FBSnapshotVerifyViewOrLayer(view, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) + } + + public func FBSnapshotVerifyLayer(layer: CALayer, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + FBSnapshotVerifyViewOrLayer(layer, identifier: identifier, suffixes: suffixes, tolerance: tolerance, file: file, line: line) + } + + private func FBSnapshotVerifyViewOrLayer(viewOrLayer: AnyObject, identifier: String = "", suffixes: NSOrderedSet = FBSnapshotTestCaseDefaultSuffixes(), tolerance: CGFloat = 0, file: StaticString = #file, line: UInt = #line) { + let envReferenceImageDirectory = self.getReferenceImageDirectoryWithDefault(FB_REFERENCE_IMAGE_DIR) + var error: NSError? + var comparisonSuccess = false + + if let envReferenceImageDirectory = envReferenceImageDirectory { + for suffix in suffixes { + let referenceImagesDirectory = "\(envReferenceImageDirectory)\(suffix)" + if viewOrLayer.isKindOfClass(UIView) { + do { + try compareSnapshotOfView(viewOrLayer as! UIView, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) + comparisonSuccess = true + } catch let error1 as NSError { + error = error1 + comparisonSuccess = false + } + } else if viewOrLayer.isKindOfClass(CALayer) { + do { + try compareSnapshotOfLayer(viewOrLayer as! CALayer, referenceImagesDirectory: referenceImagesDirectory, identifier: identifier, tolerance: tolerance) + comparisonSuccess = true + } catch let error1 as NSError { + error = error1 + comparisonSuccess = false + } + } else { + assertionFailure("Only UIView and CALayer classes can be snapshotted") + } + + assert(recordMode == false, message: "Test ran in record mode. Reference image is now saved. Disable record mode to perform an actual snapshot comparison!", file: file, line: line) + + if comparisonSuccess || recordMode { + break + } + + assert(comparisonSuccess, message: "Snapshot comparison failed: \(error)", file: file, line: line) + } + } else { + XCTFail("Missing value for referenceImagesDirectory - Set FB_REFERENCE_IMAGE_DIR as Environment variable in your scheme.") + } + } + + func assert(assertion: Bool, message: String, file: StaticString, line: UInt) { + if !assertion { + XCTFail(message, file: file, line: line) + } + } +} +#endif diff --git a/Example/Pods/FBSnapshotTestCase/LICENSE b/Example/Pods/FBSnapshotTestCase/LICENSE new file mode 100644 index 0000000..2dd780c --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/LICENSE @@ -0,0 +1,29 @@ +BSD License + +For the FBSnapshotTestCase software + +Copyright (c) 2013, Facebook, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Example/Pods/FBSnapshotTestCase/README.md b/Example/Pods/FBSnapshotTestCase/README.md new file mode 100644 index 0000000..bc23b83 --- /dev/null +++ b/Example/Pods/FBSnapshotTestCase/README.md @@ -0,0 +1,97 @@ +FBSnapshotTestCase +====================== + +[![Build Status](https://travis-ci.org/facebook/ios-snapshot-test-case.svg)](https://travis-ci.org/facebook/ios-snapshot-test-case) [![Cocoa Pod Version](https://cocoapod-badges.herokuapp.com/v/FBSnapshotTestCase/badge.svg)](http://cocoadocs.org/docsets/FBSnapshotTestCase/) + +What it does +------------ + +A "snapshot test case" takes a configured `UIView` or `CALayer` and uses the +`renderInContext:` method to get an image snapshot of its contents. It +compares this snapshot to a "reference image" stored in your source code +repository and fails the test if the two images don't match. + +Why? +---- + +At Facebook we write a lot of UI code. As you might imagine, each type of +feed story is rendered using a subclass of `UIView`. There are a lot of edge +cases that we want to handle correctly: + +- What if there is more text than can fit in the space available? +- What if an image doesn't match the size of an image view? +- What should the highlighted state look like? + +It's straightforward to test logic code, but less obvious how you should test +views. You can do a lot of rectangle asserts, but these are hard to understand +or visualize. Looking at an image diff shows you exactly what changed and how +it will look to users. + +We developed `FBSnapshotTestCase` to make snapshot tests easy. + +Installation with CocoaPods +--------------------------- + +1. Add the following lines to your Podfile: + + ``` + target "Tests" do + pod 'FBSnapshotTestCase' + end + ``` + + If you support iOS 7 use `FBSnapshotTestCase/Core` instead, which doesn't contain Swift support. + + Replace "Tests" with the name of your test project. + +2. There are [three ways](https://github.com/facebook/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/FBSnapshotTestCase.h#L19-L29) of setting reference image directories, the recommended one is to define `FB_REFERENCE_IMAGE_DIR` in your scheme. This should point to the directory where you want reference images to be stored. At Facebook, we normally use this: + +|Name|Value| +|:---|:----| +|`FB_REFERENCE_IMAGE_DIR`|`$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages`| + + +![](FBSnapshotTestCaseDemo/Scheme_FB_REFERENCE_IMAGE_DIR.png) + +Creating a snapshot test +------------------------ + +1. Subclass `FBSnapshotTestCase` instead of `XCTestCase`. +2. From within your test, use `FBSnapshotVerifyView`. +3. Run the test once with `self.recordMode = YES;` in the test's `-setUp` + method. (This creates the reference images on disk.) +4. Remove the line enabling record mode and run the test. + +Features +-------- + +- Automatically names reference images on disk according to test class and + selector. +- Prints a descriptive error message to the console on failure. (Bonus: + failure message includes a one-line command to see an image diff if + you have [Kaleidoscope](http://www.kaleidoscopeapp.com) installed.) +- Supply an optional "identifier" if you want to perform multiple snapshots + in a single test method. +- Support for `CALayer` via `FBSnapshotVerifyLayer`. +- `usesDrawViewHierarchyInRect` to handle cases like `UIVisualEffect`, `UIAppearance` and Size Classes. +- `isDeviceAgnostic` to allow appending the device model (`iPhone`, `iPad`, `iPod Touch`, etc), OS version and screen size to the images (allowing to have multiple tests for the same «snapshot» for different `OS`s and devices). + +Notes +----- + +Your unit test must be an "application test", not a "logic test." (That is, it +must be run within the Simulator so that it has access to UIKit.) In Xcode 5 +and later new projects only offer application tests, but older projects will +have separate targets for the two types. + +Authors +------- + +`FBSnapshotTestCase` was written at Facebook by +[Jonathan Dann](https://facebook.com/j.p.dann) with significant contributions by +[Todd Krabach](https://facebook.com/toddkrabach). + +License +------- + +`FBSnapshotTestCase` is BSD-licensed. See `LICENSE`. diff --git a/Example/Pods/Local Podspecs/ContainerControllerSwift.podspec.json b/Example/Pods/Local Podspecs/ContainerControllerSwift.podspec.json new file mode 100644 index 0000000..ebd02aa --- /dev/null +++ b/Example/Pods/Local Podspecs/ContainerControllerSwift.podspec.json @@ -0,0 +1,22 @@ +{ + "name": "ContainerControllerSwift", + "version": "0.1.0", + "summary": "A short description of ContainerControllerSwift.", + "description": "TODO: Add long description of the pod here.", + "homepage": "https://github.com/rustamburger@gmail.com/ContainerControllerSwift", + "license": { + "type": "MIT", + "file": "LICENSE" + }, + "authors": { + "rustamburger@gmail.com": "rustamburger@gmail.com" + }, + "source": { + "git": "https://github.com/rustamburger@gmail.com/ContainerControllerSwift.git", + "tag": "0.1.0" + }, + "platforms": { + "ios": "8.0" + }, + "source_files": "ContainerControllerSwift/Classes/**/*" +} diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock new file mode 100644 index 0000000..e31c676 --- /dev/null +++ b/Example/Pods/Manifest.lock @@ -0,0 +1,27 @@ +PODS: + - ContainerControllerSwift (0.1.0) + - FBSnapshotTestCase (2.1.4): + - FBSnapshotTestCase/SwiftSupport (= 2.1.4) + - FBSnapshotTestCase/Core (2.1.4) + - FBSnapshotTestCase/SwiftSupport (2.1.4): + - FBSnapshotTestCase/Core + +DEPENDENCIES: + - ContainerControllerSwift (from `../`) + - FBSnapshotTestCase (~> 2.1.4) + +SPEC REPOS: + https://cdn.cocoapods.org/: + - FBSnapshotTestCase + +EXTERNAL SOURCES: + ContainerControllerSwift: + :path: "../" + +SPEC CHECKSUMS: + ContainerControllerSwift: d9165e33edebeea0b8e0992717b0811328400d3c + FBSnapshotTestCase: 094f9f314decbabe373b87cc339bea235a63e07a + +PODFILE CHECKSUM: 748541873723babe6decea03fbfa834df5db1b55 + +COCOAPODS: 1.9.3 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c66971c --- /dev/null +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,1119 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 00224C929D57F45B70E87359E719948D /* FBSnapshotTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = FEE661E58CA6655B39AA49AA4C021C33 /* FBSnapshotTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 11C410135C7E89353B480AC8DE0BFB77 /* UIApplication+StrictKeyWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F538C426803AE34255FC6E35B408CCA /* UIApplication+StrictKeyWindow.m */; }; + 14A6E587C564CE411EE5FB59184450FA /* Pods-ContainerControllerSwift_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3362BA1EBE2DE493F763CC82EDD4EBDB /* Pods-ContainerControllerSwift_Tests-dummy.m */; }; + 14AD81D52FAD9CF2C065C61FB00C3B4F /* UIImage+Diff.m in Sources */ = {isa = PBXBuildFile; fileRef = 4568279DE47DC3AB91598E1317503995 /* UIImage+Diff.m */; }; + 14C511527597E5846AB2627F791C7D8E /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 716A9972B9D9103B54DB950893FAF104 /* QuartzCore.framework */; }; + 235CFE0A3232BE4573B1ACCD9E77AFA4 /* ContainerControllerSwift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A6BDE2A835C4F455E69F423C3891EC5C /* ContainerControllerSwift-dummy.m */; }; + 2429128D526EC6E28E24A616F34D8423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */; }; + 2DCFF0CE0BD295F1D46D3247F36B192C /* UIImage+Compare.m in Sources */ = {isa = PBXBuildFile; fileRef = 235A78CFFA6D8B8D86CACD733531CB13 /* UIImage+Compare.m */; }; + 40039E0AF0D764360B1D4FC4F7950D2E /* UIApplication+StrictKeyWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 99A67367E018411D614EC8536A8A1C5B /* UIApplication+StrictKeyWindow.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46ACEF81249007DB00FAAD43 /* ContainerTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF6F249007DA00FAAD43 /* ContainerTypes.swift */; }; + 46ACEF82249007DB00FAAD43 /* ContainerLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF70249007DA00FAAD43 /* ContainerLayout.swift */; }; + 46ACEF83249007DB00FAAD43 /* ContainerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF71249007DA00FAAD43 /* ContainerController.swift */; }; + 46ACEF84249007DB00FAAD43 /* ContainerControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF72249007DA00FAAD43 /* ContainerControllerDelegate.swift */; }; + 46ACEF85249007DB00FAAD43 /* ContainerDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF73249007DA00FAAD43 /* ContainerDevice.swift */; }; + 46ACEF86249007DB00FAAD43 /* CollectionAdapterItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF75249007DA00FAAD43 /* CollectionAdapterItem.swift */; }; + 46ACEF87249007DB00FAAD43 /* CollectionAdapterCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF76249007DA00FAAD43 /* CollectionAdapterCell.swift */; }; + 46ACEF88249007DB00FAAD43 /* CollectionAdapterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF77249007DA00FAAD43 /* CollectionAdapterView.swift */; }; + 46ACEF89249007DB00FAAD43 /* CollectionAdapterCellData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF78249007DA00FAAD43 /* CollectionAdapterCellData.swift */; }; + 46ACEF8A249007DB00FAAD43 /* CollectionAdapterTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF79249007DA00FAAD43 /* CollectionAdapterTypes.swift */; }; + 46ACEF8B249007DB00FAAD43 /* ContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF7A249007DA00FAAD43 /* ContainerView.swift */; }; + 46ACEF8C249007DB00FAAD43 /* TableAdapterCellData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF7C249007DB00FAAD43 /* TableAdapterCellData.swift */; }; + 46ACEF8D249007DB00FAAD43 /* TableAdapterItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF7D249007DB00FAAD43 /* TableAdapterItem.swift */; }; + 46ACEF8E249007DB00FAAD43 /* TableAdapterCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF7E249007DB00FAAD43 /* TableAdapterCell.swift */; }; + 46ACEF8F249007DB00FAAD43 /* TableAdapterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF7F249007DB00FAAD43 /* TableAdapterView.swift */; }; + 46ACEF90249007DB00FAAD43 /* TableAdapterTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46ACEF80249007DB00FAAD43 /* TableAdapterTypes.swift */; }; + 5A2024BB8D0E03480CB50AD822D9FC7A /* ContainerControllerSwift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BAE91C6FBA356FAA071EB03FFF5C33CF /* ContainerControllerSwift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 665078810E1C8EE838095A04D8821F21 /* Pods-ContainerControllerSwift_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = EC38C7705E778E849D814E9D392F447E /* Pods-ContainerControllerSwift_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6832A37E4BE96FFAB256437366565B3A /* Pods-ContainerControllerSwift_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B430FEACD25602B4F88F4D77A75C37D /* Pods-ContainerControllerSwift_Example-dummy.m */; }; + 68F16EE7A3E26D1AA1C5B7D4D664CEA1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */; }; + 6AE239C5D116E1C06F5705699FB9EAF0 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E601BD54DA9BF4071437E60125281FA /* XCTest.framework */; }; + 6BA9901BD72359C688E66F3F7F4FCDD5 /* Pods-ContainerControllerSwift_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DD609B0B32F8D8A476DC311E2DBE715D /* Pods-ContainerControllerSwift_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DBC8EB7532E931C2FBDA71D1E0B66A4 /* FBSnapshotTestCase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADA6E655DC84D06359BD0ED5E36C783 /* FBSnapshotTestCase-dummy.m */; }; + 88396E68DC05A379282F3B374F75F43C /* FBSnapshotTestController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E1B7EA746BF6557FD565BAE12AF9198 /* FBSnapshotTestController.m */; }; + 8CE3BF0ACE07EA42DD5DAC871BF4B767 /* FBSnapshotTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 277B6BE10C665F515606A22FD60C6DCC /* FBSnapshotTestCase.m */; }; + 90142C6259374E18E640396A59AD379A /* FBSnapshotTestController.h in Headers */ = {isa = PBXBuildFile; fileRef = AE9FF9459FBCDC4AF88FB6B5A4CC1439 /* FBSnapshotTestController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D65089019D558E5A9661F2DCAD20313 /* SwiftSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F0D66CF296ABBC57EC4D0452397E235 /* SwiftSupport.swift */; }; + A525E29E0A8079B35B793D8A2B5FBDF2 /* UIImage+Snapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = D872A3EE224412D4057C234FBC629F9C /* UIImage+Snapshot.m */; }; + B25D795BDC4F426BC01EFC911F368B81 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */; }; + B74CD6E6EBEA0B642776BCB37850415D /* UIImage+Snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 284833D18C244D2B42966B6EE425AA59 /* UIImage+Snapshot.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C49D52712466511E332C952834C81FE1 /* FBSnapshotTestCasePlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 88B1DEEBF6316A84D7413645212492FF /* FBSnapshotTestCasePlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D04AAC8B22E4A4DC4F39891C4E52F251 /* UIImage+Diff.h in Headers */ = {isa = PBXBuildFile; fileRef = 96187BF3038121CC146335E9FF0B0AFF /* UIImage+Diff.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E0B8D095C732352C854D365B9E5B993D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CAA89EEF1039078430D7A886477E365 /* UIKit.framework */; }; + E8AC509D18EBF21B1FEA909652A01108 /* FBSnapshotTestCasePlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 6ABB3EB3CCC5BCA82F40FE8DC87BB778 /* FBSnapshotTestCasePlatform.m */; }; + F1AAAE00BB32B733B238E2B4E8424506 /* UIImage+Compare.h in Headers */ = {isa = PBXBuildFile; fileRef = 656116C8FA5458F45D4707110C9530EC /* UIImage+Compare.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F720FAF13A108CE6901E0A8B0580E1E8 /* FBSnapshotTestCase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E5923010B02074CAA9AAF6EA02D66AA /* FBSnapshotTestCase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FF5ED999C368088A1250700BBBCF4C41 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 65FC883BECB76655B966D1157DC123BC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5DA187609B115AA5A2E3705A1CC63904; + remoteInfo = ContainerControllerSwift; + }; + 82F26AEEE2A59411EE5528E6573A7FFF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CE197115FA4CB443FE4917D7ACF96849; + remoteInfo = "Pods-ContainerControllerSwift_Example"; + }; + A0B58295CE357EBF9C3C2A36E87FEC4A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 98A98149697C80CEF8D5772791E92E66; + remoteInfo = FBSnapshotTestCase; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0CF37DA02484D8B6F5DC49CEB1B8A5BC /* Pods-ContainerControllerSwift_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-ContainerControllerSwift_Tests.modulemap"; sourceTree = ""; }; + 0F538C426803AE34255FC6E35B408CCA /* UIApplication+StrictKeyWindow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+StrictKeyWindow.m"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.m"; sourceTree = ""; }; + 0F5E3421275B9E083BB8A450D07A3650 /* Pods-ContainerControllerSwift_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ContainerControllerSwift_Tests-frameworks.sh"; sourceTree = ""; }; + 11CF775E58F73F25421FC1063F87B2FB /* ContainerControllerSwift-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ContainerControllerSwift-Info.plist"; sourceTree = ""; }; + 148A1CC4CCA9A45E6679C0483EC257F1 /* Pods_ContainerControllerSwift_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerControllerSwift_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1ADA6E655DC84D06359BD0ED5E36C783 /* FBSnapshotTestCase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FBSnapshotTestCase-dummy.m"; sourceTree = ""; }; + 235A78CFFA6D8B8D86CACD733531CB13 /* UIImage+Compare.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Compare.m"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.m"; sourceTree = ""; }; + 277B6BE10C665F515606A22FD60C6DCC /* FBSnapshotTestCase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCase.m; path = FBSnapshotTestCase/FBSnapshotTestCase.m; sourceTree = ""; }; + 284833D18C244D2B42966B6EE425AA59 /* UIImage+Snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Snapshot.h"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.h"; sourceTree = ""; }; + 301C608669646EC60E6DBEF1610B3625 /* Pods-ContainerControllerSwift_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ContainerControllerSwift_Tests.debug.xcconfig"; sourceTree = ""; }; + 32ECAD422FF141DA5B41E0BB5D1EA3C0 /* Pods-ContainerControllerSwift_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-ContainerControllerSwift_Example-frameworks.sh"; sourceTree = ""; }; + 3362BA1EBE2DE493F763CC82EDD4EBDB /* Pods-ContainerControllerSwift_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ContainerControllerSwift_Tests-dummy.m"; sourceTree = ""; }; + 3F0D66CF296ABBC57EC4D0452397E235 /* SwiftSupport.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftSupport.swift; path = FBSnapshotTestCase/SwiftSupport.swift; sourceTree = ""; }; + 4568279DE47DC3AB91598E1317503995 /* UIImage+Diff.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Diff.m"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.m"; sourceTree = ""; }; + 46ACEF6F249007DA00FAAD43 /* ContainerTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerTypes.swift; path = ContainerControllerSwift/Classes/ContainerTypes.swift; sourceTree = ""; }; + 46ACEF70249007DA00FAAD43 /* ContainerLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerLayout.swift; path = ContainerControllerSwift/Classes/ContainerLayout.swift; sourceTree = ""; }; + 46ACEF71249007DA00FAAD43 /* ContainerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerController.swift; path = ContainerControllerSwift/Classes/ContainerController.swift; sourceTree = ""; }; + 46ACEF72249007DA00FAAD43 /* ContainerControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerControllerDelegate.swift; path = ContainerControllerSwift/Classes/ContainerControllerDelegate.swift; sourceTree = ""; }; + 46ACEF73249007DA00FAAD43 /* ContainerDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerDevice.swift; path = ContainerControllerSwift/Classes/ContainerDevice.swift; sourceTree = ""; }; + 46ACEF75249007DA00FAAD43 /* CollectionAdapterItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdapterItem.swift; sourceTree = ""; }; + 46ACEF76249007DA00FAAD43 /* CollectionAdapterCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdapterCell.swift; sourceTree = ""; }; + 46ACEF77249007DA00FAAD43 /* CollectionAdapterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdapterView.swift; sourceTree = ""; }; + 46ACEF78249007DA00FAAD43 /* CollectionAdapterCellData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdapterCellData.swift; sourceTree = ""; }; + 46ACEF79249007DA00FAAD43 /* CollectionAdapterTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionAdapterTypes.swift; sourceTree = ""; }; + 46ACEF7A249007DA00FAAD43 /* ContainerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContainerView.swift; path = ContainerControllerSwift/Classes/ContainerView.swift; sourceTree = ""; }; + 46ACEF7C249007DB00FAAD43 /* TableAdapterCellData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableAdapterCellData.swift; sourceTree = ""; }; + 46ACEF7D249007DB00FAAD43 /* TableAdapterItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableAdapterItem.swift; sourceTree = ""; }; + 46ACEF7E249007DB00FAAD43 /* TableAdapterCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableAdapterCell.swift; sourceTree = ""; }; + 46ACEF7F249007DB00FAAD43 /* TableAdapterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableAdapterView.swift; sourceTree = ""; }; + 46ACEF80249007DB00FAAD43 /* TableAdapterTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableAdapterTypes.swift; sourceTree = ""; }; + 46AFBEAD35607114821A98D6BB115E4E /* Pods-ContainerControllerSwift_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ContainerControllerSwift_Example.debug.xcconfig"; sourceTree = ""; }; + 49C0EBFD282C6B3133818F8DA13F7C32 /* Pods-ContainerControllerSwift_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ContainerControllerSwift_Tests.release.xcconfig"; sourceTree = ""; }; + 4C6513B09838318BD763CFD5390D1DE0 /* FBSnapshotTestCase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.release.xcconfig; sourceTree = ""; }; + 4D341C6D33795B9BE49E45CAEFD59E75 /* Pods-ContainerControllerSwift_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-ContainerControllerSwift_Example.release.xcconfig"; sourceTree = ""; }; + 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FBSnapshotTestCase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E601BD54DA9BF4071437E60125281FA /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 656116C8FA5458F45D4707110C9530EC /* UIImage+Compare.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Compare.h"; path = "FBSnapshotTestCase/Categories/UIImage+Compare.h"; sourceTree = ""; }; + 66A0D2D122209704AE9D4CA342355063 /* Pods-ContainerControllerSwift_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ContainerControllerSwift_Tests-acknowledgements.plist"; sourceTree = ""; }; + 6ABB3EB3CCC5BCA82F40FE8DC87BB778 /* FBSnapshotTestCasePlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestCasePlatform.m; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.m; sourceTree = ""; }; + 716A9972B9D9103B54DB950893FAF104 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 717C009359AD259D4B0DC77D5032C778 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 77CF0FB52D0D5DBAEF25D1AF2D110C37 /* Pods-ContainerControllerSwift_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-ContainerControllerSwift_Example.modulemap"; sourceTree = ""; }; + 7B430FEACD25602B4F88F4D77A75C37D /* Pods-ContainerControllerSwift_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-ContainerControllerSwift_Example-dummy.m"; sourceTree = ""; }; + 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 7E1B7EA746BF6557FD565BAE12AF9198 /* FBSnapshotTestController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBSnapshotTestController.m; path = FBSnapshotTestCase/FBSnapshotTestController.m; sourceTree = ""; }; + 88289C16D7EE3DABA481CCA2A23F6606 /* Pods_ContainerControllerSwift_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerControllerSwift_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 88B1DEEBF6316A84D7413645212492FF /* FBSnapshotTestCasePlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCasePlatform.h; path = FBSnapshotTestCase/FBSnapshotTestCasePlatform.h; sourceTree = ""; }; + 8CAA89EEF1039078430D7A886477E365 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 8CF330763B8EC74910A743BC692ED2A9 /* Pods-ContainerControllerSwift_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ContainerControllerSwift_Example-acknowledgements.plist"; sourceTree = ""; }; + 8E5923010B02074CAA9AAF6EA02D66AA /* FBSnapshotTestCase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-umbrella.h"; sourceTree = ""; }; + 93B723DA20DD1ABD15748B90CDDC9C6B /* ContainerControllerSwift.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = ContainerControllerSwift.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9468E867498BBAF36F9AFFE4845F8B09 /* FBSnapshotTestCase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FBSnapshotTestCase.debug.xcconfig; sourceTree = ""; }; + 96187BF3038121CC146335E9FF0B0AFF /* UIImage+Diff.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+Diff.h"; path = "FBSnapshotTestCase/Categories/UIImage+Diff.h"; sourceTree = ""; }; + 992C8F5FFB94D2E11E13259B470147AB /* Pods-ContainerControllerSwift_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ContainerControllerSwift_Example-Info.plist"; sourceTree = ""; }; + 99A67367E018411D614EC8536A8A1C5B /* UIApplication+StrictKeyWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIApplication+StrictKeyWindow.h"; path = "FBSnapshotTestCase/Categories/UIApplication+StrictKeyWindow.h"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + A629ADBA03C7F2C6D097B825491C51D8 /* Pods-ContainerControllerSwift_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ContainerControllerSwift_Example-acknowledgements.markdown"; sourceTree = ""; }; + A6BDE2A835C4F455E69F423C3891EC5C /* ContainerControllerSwift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ContainerControllerSwift-dummy.m"; sourceTree = ""; }; + A71A65086BF3EF5C21466C854ED78DEB /* Pods-ContainerControllerSwift_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-ContainerControllerSwift_Tests-Info.plist"; sourceTree = ""; }; + AE9FF9459FBCDC4AF88FB6B5A4CC1439 /* FBSnapshotTestController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestController.h; path = FBSnapshotTestCase/FBSnapshotTestController.h; sourceTree = ""; }; + B7103CA00AED20722C5B69CA5B4F6938 /* FBSnapshotTestCase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FBSnapshotTestCase-Info.plist"; sourceTree = ""; }; + BAE91C6FBA356FAA071EB03FFF5C33CF /* ContainerControllerSwift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ContainerControllerSwift-umbrella.h"; sourceTree = ""; }; + CBFF6C5FD9C3A84274A9314D3E940B6E /* FBSnapshotTestCase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FBSnapshotTestCase.modulemap; sourceTree = ""; }; + CEBF07FB532E468F36FCF3E25F9312A9 /* Pods-ContainerControllerSwift_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-ContainerControllerSwift_Tests-acknowledgements.markdown"; sourceTree = ""; }; + D08CEBB9BDD9EF7A662ECFC0305C169E /* FBSnapshotTestCase-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FBSnapshotTestCase-prefix.pch"; sourceTree = ""; }; + D717D7836C69C554BA29F49FFD21BD99 /* ContainerControllerSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ContainerControllerSwift.release.xcconfig; sourceTree = ""; }; + D872A3EE224412D4057C234FBC629F9C /* UIImage+Snapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+Snapshot.m"; path = "FBSnapshotTestCase/Categories/UIImage+Snapshot.m"; sourceTree = ""; }; + DD609B0B32F8D8A476DC311E2DBE715D /* Pods-ContainerControllerSwift_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ContainerControllerSwift_Example-umbrella.h"; sourceTree = ""; }; + E20CCE883FD054058028CD499E8853BE /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + EC38C7705E778E849D814E9D392F447E /* Pods-ContainerControllerSwift_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-ContainerControllerSwift_Tests-umbrella.h"; sourceTree = ""; }; + EE0922322919343E3F27C99B2BB05246 /* ContainerControllerSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ContainerControllerSwift.debug.xcconfig; sourceTree = ""; }; + EE39D914C10E9DA3195D8B4FA7C957A7 /* ContainerControllerSwift-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ContainerControllerSwift-prefix.pch"; sourceTree = ""; }; + F976F9D3CEF51D2530649D115424E24B /* ContainerControllerSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ContainerControllerSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FB9AB8D98CCA87BB9D5397D0A6F571BE /* ContainerControllerSwift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = ContainerControllerSwift.modulemap; sourceTree = ""; }; + FEE661E58CA6655B39AA49AA4C021C33 /* FBSnapshotTestCase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBSnapshotTestCase.h; path = FBSnapshotTestCase/FBSnapshotTestCase.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 29CBBA589A4FEB04C5A69211E237F2F3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FF5ED999C368088A1250700BBBCF4C41 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 36DEF5C29829FEE10700BD84BBD093D3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68F16EE7A3E26D1AA1C5B7D4D664CEA1 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CEA466CF45F113A3E1A202FEF2A4DE54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2429128D526EC6E28E24A616F34D8423 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E581515110D66F94F80A6937831489A1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B25D795BDC4F426BC01EFC911F368B81 /* Foundation.framework in Frameworks */, + 14C511527597E5846AB2627F791C7D8E /* QuartzCore.framework in Frameworks */, + E0B8D095C732352C854D365B9E5B993D /* UIKit.framework in Frameworks */, + 6AE239C5D116E1C06F5705699FB9EAF0 /* XCTest.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 46ACEF74249007DA00FAAD43 /* ContainerCollection */ = { + isa = PBXGroup; + children = ( + 46ACEF75249007DA00FAAD43 /* CollectionAdapterItem.swift */, + 46ACEF76249007DA00FAAD43 /* CollectionAdapterCell.swift */, + 46ACEF77249007DA00FAAD43 /* CollectionAdapterView.swift */, + 46ACEF78249007DA00FAAD43 /* CollectionAdapterCellData.swift */, + 46ACEF79249007DA00FAAD43 /* CollectionAdapterTypes.swift */, + ); + name = ContainerCollection; + path = ContainerControllerSwift/Classes/ContainerCollection; + sourceTree = ""; + }; + 46ACEF7B249007DB00FAAD43 /* ContainerTable */ = { + isa = PBXGroup; + children = ( + 46ACEF7C249007DB00FAAD43 /* TableAdapterCellData.swift */, + 46ACEF7D249007DB00FAAD43 /* TableAdapterItem.swift */, + 46ACEF7E249007DB00FAAD43 /* TableAdapterCell.swift */, + 46ACEF7F249007DB00FAAD43 /* TableAdapterView.swift */, + 46ACEF80249007DB00FAAD43 /* TableAdapterTypes.swift */, + ); + name = ContainerTable; + path = ContainerControllerSwift/Classes/ContainerTable; + sourceTree = ""; + }; + 4BA2479549DD918290454B1CDCD0B92B /* Core */ = { + isa = PBXGroup; + children = ( + FEE661E58CA6655B39AA49AA4C021C33 /* FBSnapshotTestCase.h */, + 277B6BE10C665F515606A22FD60C6DCC /* FBSnapshotTestCase.m */, + 88B1DEEBF6316A84D7413645212492FF /* FBSnapshotTestCasePlatform.h */, + 6ABB3EB3CCC5BCA82F40FE8DC87BB778 /* FBSnapshotTestCasePlatform.m */, + AE9FF9459FBCDC4AF88FB6B5A4CC1439 /* FBSnapshotTestController.h */, + 7E1B7EA746BF6557FD565BAE12AF9198 /* FBSnapshotTestController.m */, + 99A67367E018411D614EC8536A8A1C5B /* UIApplication+StrictKeyWindow.h */, + 0F538C426803AE34255FC6E35B408CCA /* UIApplication+StrictKeyWindow.m */, + 656116C8FA5458F45D4707110C9530EC /* UIImage+Compare.h */, + 235A78CFFA6D8B8D86CACD733531CB13 /* UIImage+Compare.m */, + 96187BF3038121CC146335E9FF0B0AFF /* UIImage+Diff.h */, + 4568279DE47DC3AB91598E1317503995 /* UIImage+Diff.m */, + 284833D18C244D2B42966B6EE425AA59 /* UIImage+Snapshot.h */, + D872A3EE224412D4057C234FBC629F9C /* UIImage+Snapshot.m */, + ); + name = Core; + sourceTree = ""; + }; + 59EA9F360290DCA9B082DDAC24FD4A0A /* Support Files */ = { + isa = PBXGroup; + children = ( + FB9AB8D98CCA87BB9D5397D0A6F571BE /* ContainerControllerSwift.modulemap */, + A6BDE2A835C4F455E69F423C3891EC5C /* ContainerControllerSwift-dummy.m */, + 11CF775E58F73F25421FC1063F87B2FB /* ContainerControllerSwift-Info.plist */, + EE39D914C10E9DA3195D8B4FA7C957A7 /* ContainerControllerSwift-prefix.pch */, + BAE91C6FBA356FAA071EB03FFF5C33CF /* ContainerControllerSwift-umbrella.h */, + EE0922322919343E3F27C99B2BB05246 /* ContainerControllerSwift.debug.xcconfig */, + D717D7836C69C554BA29F49FFD21BD99 /* ContainerControllerSwift.release.xcconfig */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/ContainerControllerSwift"; + sourceTree = ""; + }; + 6090372AED4F5F449DCD962CD169E221 /* Pods-ContainerControllerSwift_Example */ = { + isa = PBXGroup; + children = ( + 77CF0FB52D0D5DBAEF25D1AF2D110C37 /* Pods-ContainerControllerSwift_Example.modulemap */, + A629ADBA03C7F2C6D097B825491C51D8 /* Pods-ContainerControllerSwift_Example-acknowledgements.markdown */, + 8CF330763B8EC74910A743BC692ED2A9 /* Pods-ContainerControllerSwift_Example-acknowledgements.plist */, + 7B430FEACD25602B4F88F4D77A75C37D /* Pods-ContainerControllerSwift_Example-dummy.m */, + 32ECAD422FF141DA5B41E0BB5D1EA3C0 /* Pods-ContainerControllerSwift_Example-frameworks.sh */, + 992C8F5FFB94D2E11E13259B470147AB /* Pods-ContainerControllerSwift_Example-Info.plist */, + DD609B0B32F8D8A476DC311E2DBE715D /* Pods-ContainerControllerSwift_Example-umbrella.h */, + 46AFBEAD35607114821A98D6BB115E4E /* Pods-ContainerControllerSwift_Example.debug.xcconfig */, + 4D341C6D33795B9BE49E45CAEFD59E75 /* Pods-ContainerControllerSwift_Example.release.xcconfig */, + ); + name = "Pods-ContainerControllerSwift_Example"; + path = "Target Support Files/Pods-ContainerControllerSwift_Example"; + sourceTree = ""; + }; + 6497942BDC176AB8D51B9B7E15576A3C /* ContainerControllerSwift */ = { + isa = PBXGroup; + children = ( + 46ACEF74249007DA00FAAD43 /* ContainerCollection */, + 46ACEF7B249007DB00FAAD43 /* ContainerTable */, + 46ACEF71249007DA00FAAD43 /* ContainerController.swift */, + 46ACEF72249007DA00FAAD43 /* ContainerControllerDelegate.swift */, + 46ACEF73249007DA00FAAD43 /* ContainerDevice.swift */, + 46ACEF70249007DA00FAAD43 /* ContainerLayout.swift */, + 46ACEF6F249007DA00FAAD43 /* ContainerTypes.swift */, + 46ACEF7A249007DA00FAAD43 /* ContainerView.swift */, + C5364B17E8D2043898EEC132167315B5 /* Pod */, + 59EA9F360290DCA9B082DDAC24FD4A0A /* Support Files */, + ); + name = ContainerControllerSwift; + path = ../..; + sourceTree = ""; + }; + 7DE5752EED0A4C4A430975244947611A /* iOS */ = { + isa = PBXGroup; + children = ( + 7BD4ED544B638D07C7D755AF1C27116A /* Foundation.framework */, + 716A9972B9D9103B54DB950893FAF104 /* QuartzCore.framework */, + 8CAA89EEF1039078430D7A886477E365 /* UIKit.framework */, + 5E601BD54DA9BF4071437E60125281FA /* XCTest.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 906402ECC4C6C5EB58DD365FD2C64E92 /* SwiftSupport */ = { + isa = PBXGroup; + children = ( + 3F0D66CF296ABBC57EC4D0452397E235 /* SwiftSupport.swift */, + ); + name = SwiftSupport; + sourceTree = ""; + }; + AA23148E2F932A12017195A2D568C0A5 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 6497942BDC176AB8D51B9B7E15576A3C /* ContainerControllerSwift */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + AD261C349AD0CE7FDE202A19C056FD62 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 6090372AED4F5F449DCD962CD169E221 /* Pods-ContainerControllerSwift_Example */, + D73362ABF89A3B83420EAC88C9DC726A /* Pods-ContainerControllerSwift_Tests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + B69B2ECE2D2C9A3924A9231138CE0BBC /* Support Files */ = { + isa = PBXGroup; + children = ( + CBFF6C5FD9C3A84274A9314D3E940B6E /* FBSnapshotTestCase.modulemap */, + 1ADA6E655DC84D06359BD0ED5E36C783 /* FBSnapshotTestCase-dummy.m */, + B7103CA00AED20722C5B69CA5B4F6938 /* FBSnapshotTestCase-Info.plist */, + D08CEBB9BDD9EF7A662ECFC0305C169E /* FBSnapshotTestCase-prefix.pch */, + 8E5923010B02074CAA9AAF6EA02D66AA /* FBSnapshotTestCase-umbrella.h */, + 9468E867498BBAF36F9AFFE4845F8B09 /* FBSnapshotTestCase.debug.xcconfig */, + 4C6513B09838318BD763CFD5390D1DE0 /* FBSnapshotTestCase.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FBSnapshotTestCase"; + sourceTree = ""; + }; + BA4F31F07263C99FC76E66D632A59F09 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7DE5752EED0A4C4A430975244947611A /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + BD2D60DE56CBB8C87BA07E0C1CCD0592 /* FBSnapshotTestCase */ = { + isa = PBXGroup; + children = ( + 4BA2479549DD918290454B1CDCD0B92B /* Core */, + B69B2ECE2D2C9A3924A9231138CE0BBC /* Support Files */, + 906402ECC4C6C5EB58DD365FD2C64E92 /* SwiftSupport */, + ); + path = FBSnapshotTestCase; + sourceTree = ""; + }; + C5364B17E8D2043898EEC132167315B5 /* Pod */ = { + isa = PBXGroup; + children = ( + 93B723DA20DD1ABD15748B90CDDC9C6B /* ContainerControllerSwift.podspec */, + E20CCE883FD054058028CD499E8853BE /* LICENSE */, + 717C009359AD259D4B0DC77D5032C778 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; + C93BE1B647079AEDD87CD5DC21F47B87 /* Products */ = { + isa = PBXGroup; + children = ( + F976F9D3CEF51D2530649D115424E24B /* ContainerControllerSwift.framework */, + 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase.framework */, + 148A1CC4CCA9A45E6679C0483EC257F1 /* Pods_ContainerControllerSwift_Example.framework */, + 88289C16D7EE3DABA481CCA2A23F6606 /* Pods_ContainerControllerSwift_Tests.framework */, + ); + name = Products; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + AA23148E2F932A12017195A2D568C0A5 /* Development Pods */, + BA4F31F07263C99FC76E66D632A59F09 /* Frameworks */, + E81A37DBDE41E671312C56736544E2FA /* Pods */, + C93BE1B647079AEDD87CD5DC21F47B87 /* Products */, + AD261C349AD0CE7FDE202A19C056FD62 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D73362ABF89A3B83420EAC88C9DC726A /* Pods-ContainerControllerSwift_Tests */ = { + isa = PBXGroup; + children = ( + 0CF37DA02484D8B6F5DC49CEB1B8A5BC /* Pods-ContainerControllerSwift_Tests.modulemap */, + CEBF07FB532E468F36FCF3E25F9312A9 /* Pods-ContainerControllerSwift_Tests-acknowledgements.markdown */, + 66A0D2D122209704AE9D4CA342355063 /* Pods-ContainerControllerSwift_Tests-acknowledgements.plist */, + 3362BA1EBE2DE493F763CC82EDD4EBDB /* Pods-ContainerControllerSwift_Tests-dummy.m */, + 0F5E3421275B9E083BB8A450D07A3650 /* Pods-ContainerControllerSwift_Tests-frameworks.sh */, + A71A65086BF3EF5C21466C854ED78DEB /* Pods-ContainerControllerSwift_Tests-Info.plist */, + EC38C7705E778E849D814E9D392F447E /* Pods-ContainerControllerSwift_Tests-umbrella.h */, + 301C608669646EC60E6DBEF1610B3625 /* Pods-ContainerControllerSwift_Tests.debug.xcconfig */, + 49C0EBFD282C6B3133818F8DA13F7C32 /* Pods-ContainerControllerSwift_Tests.release.xcconfig */, + ); + name = "Pods-ContainerControllerSwift_Tests"; + path = "Target Support Files/Pods-ContainerControllerSwift_Tests"; + sourceTree = ""; + }; + E81A37DBDE41E671312C56736544E2FA /* Pods */ = { + isa = PBXGroup; + children = ( + BD2D60DE56CBB8C87BA07E0C1CCD0592 /* FBSnapshotTestCase */, + ); + name = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 23FFCFE740738E36CE184ABCBA03B459 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 665078810E1C8EE838095A04D8821F21 /* Pods-ContainerControllerSwift_Tests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3209EBB5E1EB3F096D8CE62F865CA233 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6BA9901BD72359C688E66F3F7F4FCDD5 /* Pods-ContainerControllerSwift_Example-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 384DE8A8021C5DA5E256BCFEC3D478A9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F720FAF13A108CE6901E0A8B0580E1E8 /* FBSnapshotTestCase-umbrella.h in Headers */, + 00224C929D57F45B70E87359E719948D /* FBSnapshotTestCase.h in Headers */, + C49D52712466511E332C952834C81FE1 /* FBSnapshotTestCasePlatform.h in Headers */, + 90142C6259374E18E640396A59AD379A /* FBSnapshotTestController.h in Headers */, + 40039E0AF0D764360B1D4FC4F7950D2E /* UIApplication+StrictKeyWindow.h in Headers */, + F1AAAE00BB32B733B238E2B4E8424506 /* UIImage+Compare.h in Headers */, + D04AAC8B22E4A4DC4F39891C4E52F251 /* UIImage+Diff.h in Headers */, + B74CD6E6EBEA0B642776BCB37850415D /* UIImage+Snapshot.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 91025BC977887359295085DE9B62148D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 5A2024BB8D0E03480CB50AD822D9FC7A /* ContainerControllerSwift-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1169D43D75A981EA7C2522A5530B2CFF /* Pods-ContainerControllerSwift_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4334A2E51270607282452446639F0FF1 /* Build configuration list for PBXNativeTarget "Pods-ContainerControllerSwift_Tests" */; + buildPhases = ( + 23FFCFE740738E36CE184ABCBA03B459 /* Headers */, + 0C95D3E760FBE56DADCA8FF5225BC06B /* Sources */, + 36DEF5C29829FEE10700BD84BBD093D3 /* Frameworks */, + 60BE0CB18DBEBE6022B16EDE57F838C2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DC70913F68EE696D174D4F80C840BACC /* PBXTargetDependency */, + D6657B4F218D6E28626014C93866072A /* PBXTargetDependency */, + ); + name = "Pods-ContainerControllerSwift_Tests"; + productName = "Pods-ContainerControllerSwift_Tests"; + productReference = 88289C16D7EE3DABA481CCA2A23F6606 /* Pods_ContainerControllerSwift_Tests.framework */; + productType = "com.apple.product-type.framework"; + }; + 5DA187609B115AA5A2E3705A1CC63904 /* ContainerControllerSwift */ = { + isa = PBXNativeTarget; + buildConfigurationList = F11CFC9839971698EA914B4526A4890E /* Build configuration list for PBXNativeTarget "ContainerControllerSwift" */; + buildPhases = ( + 91025BC977887359295085DE9B62148D /* Headers */, + 179E5D44C11E9CCB29BAA3C8919F3D3C /* Sources */, + CEA466CF45F113A3E1A202FEF2A4DE54 /* Frameworks */, + 4371C46D56A429BC875D05A794822B14 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ContainerControllerSwift; + productName = ContainerControllerSwift; + productReference = F976F9D3CEF51D2530649D115424E24B /* ContainerControllerSwift.framework */; + productType = "com.apple.product-type.framework"; + }; + 98A98149697C80CEF8D5772791E92E66 /* FBSnapshotTestCase */ = { + isa = PBXNativeTarget; + buildConfigurationList = A38070E189561F257BBD5A0A55CACCCF /* Build configuration list for PBXNativeTarget "FBSnapshotTestCase" */; + buildPhases = ( + 384DE8A8021C5DA5E256BCFEC3D478A9 /* Headers */, + A48201AC594B2E6B09C0EE0396BC1377 /* Sources */, + E581515110D66F94F80A6937831489A1 /* Frameworks */, + 5CC655F1A6C7A45A9693160581076BAE /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = FBSnapshotTestCase; + productName = FBSnapshotTestCase; + productReference = 5C4F31330DFA99D699E4BDC8C3573D73 /* FBSnapshotTestCase.framework */; + productType = "com.apple.product-type.framework"; + }; + CE197115FA4CB443FE4917D7ACF96849 /* Pods-ContainerControllerSwift_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 705E809BF51E50D9619902BC075C9866 /* Build configuration list for PBXNativeTarget "Pods-ContainerControllerSwift_Example" */; + buildPhases = ( + 3209EBB5E1EB3F096D8CE62F865CA233 /* Headers */, + 2188AC3092E4803D1084D9C11397B57D /* Sources */, + 29CBBA589A4FEB04C5A69211E237F2F3 /* Frameworks */, + D2E9760AEBB67731AE4FE9BC60795F8B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 065D679D97DDDBFE9D3D1D2A679EB6E6 /* PBXTargetDependency */, + ); + name = "Pods-ContainerControllerSwift_Example"; + productName = "Pods-ContainerControllerSwift_Example"; + productReference = 148A1CC4CCA9A45E6679C0483EC257F1 /* Pods_ContainerControllerSwift_Example.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = C93BE1B647079AEDD87CD5DC21F47B87 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5DA187609B115AA5A2E3705A1CC63904 /* ContainerControllerSwift */, + 98A98149697C80CEF8D5772791E92E66 /* FBSnapshotTestCase */, + CE197115FA4CB443FE4917D7ACF96849 /* Pods-ContainerControllerSwift_Example */, + 1169D43D75A981EA7C2522A5530B2CFF /* Pods-ContainerControllerSwift_Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4371C46D56A429BC875D05A794822B14 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5CC655F1A6C7A45A9693160581076BAE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 60BE0CB18DBEBE6022B16EDE57F838C2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D2E9760AEBB67731AE4FE9BC60795F8B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0C95D3E760FBE56DADCA8FF5225BC06B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 14A6E587C564CE411EE5FB59184450FA /* Pods-ContainerControllerSwift_Tests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 179E5D44C11E9CCB29BAA3C8919F3D3C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 46ACEF84249007DB00FAAD43 /* ContainerControllerDelegate.swift in Sources */, + 46ACEF85249007DB00FAAD43 /* ContainerDevice.swift in Sources */, + 46ACEF88249007DB00FAAD43 /* CollectionAdapterView.swift in Sources */, + 46ACEF8D249007DB00FAAD43 /* TableAdapterItem.swift in Sources */, + 46ACEF90249007DB00FAAD43 /* TableAdapterTypes.swift in Sources */, + 46ACEF86249007DB00FAAD43 /* CollectionAdapterItem.swift in Sources */, + 235CFE0A3232BE4573B1ACCD9E77AFA4 /* ContainerControllerSwift-dummy.m in Sources */, + 46ACEF87249007DB00FAAD43 /* CollectionAdapterCell.swift in Sources */, + 46ACEF83249007DB00FAAD43 /* ContainerController.swift in Sources */, + 46ACEF82249007DB00FAAD43 /* ContainerLayout.swift in Sources */, + 46ACEF8C249007DB00FAAD43 /* TableAdapterCellData.swift in Sources */, + 46ACEF8E249007DB00FAAD43 /* TableAdapterCell.swift in Sources */, + 46ACEF81249007DB00FAAD43 /* ContainerTypes.swift in Sources */, + 46ACEF8A249007DB00FAAD43 /* CollectionAdapterTypes.swift in Sources */, + 46ACEF8B249007DB00FAAD43 /* ContainerView.swift in Sources */, + 46ACEF8F249007DB00FAAD43 /* TableAdapterView.swift in Sources */, + 46ACEF89249007DB00FAAD43 /* CollectionAdapterCellData.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2188AC3092E4803D1084D9C11397B57D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6832A37E4BE96FFAB256437366565B3A /* Pods-ContainerControllerSwift_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A48201AC594B2E6B09C0EE0396BC1377 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6DBC8EB7532E931C2FBDA71D1E0B66A4 /* FBSnapshotTestCase-dummy.m in Sources */, + 8CE3BF0ACE07EA42DD5DAC871BF4B767 /* FBSnapshotTestCase.m in Sources */, + E8AC509D18EBF21B1FEA909652A01108 /* FBSnapshotTestCasePlatform.m in Sources */, + 88396E68DC05A379282F3B374F75F43C /* FBSnapshotTestController.m in Sources */, + 9D65089019D558E5A9661F2DCAD20313 /* SwiftSupport.swift in Sources */, + 11C410135C7E89353B480AC8DE0BFB77 /* UIApplication+StrictKeyWindow.m in Sources */, + 2DCFF0CE0BD295F1D46D3247F36B192C /* UIImage+Compare.m in Sources */, + 14AD81D52FAD9CF2C065C61FB00C3B4F /* UIImage+Diff.m in Sources */, + A525E29E0A8079B35B793D8A2B5FBDF2 /* UIImage+Snapshot.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 065D679D97DDDBFE9D3D1D2A679EB6E6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ContainerControllerSwift; + target = 5DA187609B115AA5A2E3705A1CC63904 /* ContainerControllerSwift */; + targetProxy = 65FC883BECB76655B966D1157DC123BC /* PBXContainerItemProxy */; + }; + D6657B4F218D6E28626014C93866072A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-ContainerControllerSwift_Example"; + target = CE197115FA4CB443FE4917D7ACF96849 /* Pods-ContainerControllerSwift_Example */; + targetProxy = 82F26AEEE2A59411EE5528E6573A7FFF /* PBXContainerItemProxy */; + }; + DC70913F68EE696D174D4F80C840BACC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FBSnapshotTestCase; + target = 98A98149697C80CEF8D5772791E92E66 /* FBSnapshotTestCase */; + targetProxy = A0B58295CE357EBF9C3C2A36E87FEC4A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 09B8ED349DF8287BE8E03CB4B06B1919 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 49C0EBFD282C6B3133818F8DA13F7C32 /* Pods-ContainerControllerSwift_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3F42077401BA99F2F8D2DCB3C237F1AD /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4D341C6D33795B9BE49E45CAEFD59E75 /* Pods-ContainerControllerSwift_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 43048FA455FFC270F1DE5C04AB758E32 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 46AFBEAD35607114821A98D6BB115E4E /* Pods-ContainerControllerSwift_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 441C7939108738A0C7CD37CBADE0B85E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9468E867498BBAF36F9AFFE4845F8B09 /* FBSnapshotTestCase.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap"; + PRODUCT_MODULE_NAME = FBSnapshotTestCase; + PRODUCT_NAME = FBSnapshotTestCase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7AD91BD2B3DC0FAE5979C0E10DD0C95A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D717D7836C69C554BA29F49FFD21BD99 /* ContainerControllerSwift.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift.modulemap"; + PRODUCT_MODULE_NAME = ContainerControllerSwift; + PRODUCT_NAME = ContainerControllerSwift; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7B8AD59B378AFA18A434753742EE8139 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 301C608669646EC60E6DBEF1610B3625 /* Pods-ContainerControllerSwift_Tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B0087CB4594321EF41619F3181FE120E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + B8BCBD0110C2658BB5DAADB9B7D97B92 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + BE874B114A0991701B09229EAAA4CA84 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4C6513B09838318BD763CFD5390D1DE0 /* FBSnapshotTestCase.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap"; + PRODUCT_MODULE_NAME = FBSnapshotTestCase; + PRODUCT_NAME = FBSnapshotTestCase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D6329CE17E1B2A2889FDB8023ACB25EC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EE0922322919343E3F27C99B2BB05246 /* ContainerControllerSwift.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/ContainerControllerSwift/ContainerControllerSwift.modulemap"; + PRODUCT_MODULE_NAME = ContainerControllerSwift; + PRODUCT_NAME = ContainerControllerSwift; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4334A2E51270607282452446639F0FF1 /* Build configuration list for PBXNativeTarget "Pods-ContainerControllerSwift_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B8AD59B378AFA18A434753742EE8139 /* Debug */, + 09B8ED349DF8287BE8E03CB4B06B1919 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B8BCBD0110C2658BB5DAADB9B7D97B92 /* Debug */, + B0087CB4594321EF41619F3181FE120E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 705E809BF51E50D9619902BC075C9866 /* Build configuration list for PBXNativeTarget "Pods-ContainerControllerSwift_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 43048FA455FFC270F1DE5C04AB758E32 /* Debug */, + 3F42077401BA99F2F8D2DCB3C237F1AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A38070E189561F257BBD5A0A55CACCCF /* Build configuration list for PBXNativeTarget "FBSnapshotTestCase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 441C7939108738A0C7CD37CBADE0B85E /* Debug */, + BE874B114A0991701B09229EAAA4CA84 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F11CFC9839971698EA914B4526A4890E /* Build configuration list for PBXNativeTarget "ContainerControllerSwift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D6329CE17E1B2A2889FDB8023ACB25EC /* Debug */, + 7AD91BD2B3DC0FAE5979C0E10DD0C95A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-Info.plist b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-Info.plist new file mode 100644 index 0000000..161a9d3 --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-dummy.m b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-dummy.m new file mode 100644 index 0000000..606d79d --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_ContainerControllerSwift : NSObject +@end +@implementation PodsDummy_ContainerControllerSwift +@end diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-prefix.pch b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-umbrella.h b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-umbrella.h new file mode 100644 index 0000000..d65005e --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double ContainerControllerSwiftVersionNumber; +FOUNDATION_EXPORT const unsigned char ContainerControllerSwiftVersionString[]; + diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.debug.xcconfig b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.debug.xcconfig new file mode 100644 index 0000000..15093a9 --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.modulemap b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.modulemap new file mode 100644 index 0000000..fc40a06 --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.modulemap @@ -0,0 +1,6 @@ +framework module ContainerControllerSwift { + umbrella header "ContainerControllerSwift-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.release.xcconfig b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.release.xcconfig new file mode 100644 index 0000000..15093a9 --- /dev/null +++ b/Example/Pods/Target Support Files/ContainerControllerSwift/ContainerControllerSwift.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-Info.plist b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-Info.plist new file mode 100644 index 0000000..57b76a5 --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.1.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-dummy.m b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-dummy.m new file mode 100644 index 0000000..fb0c8fe --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FBSnapshotTestCase : NSObject +@end +@implementation PodsDummy_FBSnapshotTestCase +@end diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-umbrella.h b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-umbrella.h new file mode 100644 index 0000000..1734e02 --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FBSnapshotTestCase.h" +#import "FBSnapshotTestCasePlatform.h" +#import "FBSnapshotTestController.h" + +FOUNDATION_EXPORT double FBSnapshotTestCaseVersionNumber; +FOUNDATION_EXPORT const unsigned char FBSnapshotTestCaseVersionString[]; + diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.debug.xcconfig b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.debug.xcconfig new file mode 100644 index 0000000..e1d2576 --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.debug.xcconfig @@ -0,0 +1,16 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase +ENABLE_BITCODE = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" +OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSnapshotTestCase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_INCLUDE_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" +SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap new file mode 100644 index 0000000..45b74ec --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.modulemap @@ -0,0 +1,6 @@ +framework module FBSnapshotTestCase { + umbrella header "FBSnapshotTestCase-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.release.xcconfig b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.release.xcconfig new file mode 100644 index 0000000..e1d2576 --- /dev/null +++ b/Example/Pods/Target Support Files/FBSnapshotTestCase/FBSnapshotTestCase.release.xcconfig @@ -0,0 +1,16 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase +ENABLE_BITCODE = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LIBRARY_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" +OTHER_LDFLAGS = $(inherited) -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FBSnapshotTestCase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_INCLUDE_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/usr/lib" +SYSTEM_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-Info.plist b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.markdown new file mode 100644 index 0000000..5784dea --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## ContainerControllerSwift + +Copyright (c) 2020 rustamburger@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.plist new file mode 100644 index 0000000..334c601 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2020 rustamburger@gmail.com <rustamburger@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + ContainerControllerSwift + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-dummy.m b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-dummy.m new file mode 100644 index 0000000..6374178 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_ContainerControllerSwift_Example : NSObject +@end +@implementation PodsDummy_Pods_ContainerControllerSwift_Example +@end diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-frameworks.sh new file mode 100755 index 0000000..da409d4 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-frameworks.sh @@ -0,0 +1,207 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +install_artifact() { + artifact="$1" + base="$(basename "$artifact")" + case $base in + *.framework) + install_framework "$artifact" + ;; + *.dSYM) + # Suppress arch warnings since XCFrameworks will include many dSYM files + install_dsym "$artifact" "false" + ;; + *.bcsymbolmap) + install_bcsymbolmap "$artifact" + ;; + *) + echo "error: Unrecognized artifact "$artifact"" + ;; + esac +} + +copy_artifacts() { + file_list="$1" + while read artifact; do + install_artifact "$artifact" + done <$file_list +} + +ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" +if [ -r "${ARTIFACT_LIST_FILE}" ]; then + copy_artifacts "${ARTIFACT_LIST_FILE}" +fi + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-umbrella.h b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-umbrella.h new file mode 100644 index 0000000..7513373 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_ContainerControllerSwift_ExampleVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_ContainerControllerSwift_ExampleVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.debug.xcconfig new file mode 100644 index 0000000..cedf0a1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.debug.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "ContainerControllerSwift" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.modulemap b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.modulemap new file mode 100644 index 0000000..561eb91 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.modulemap @@ -0,0 +1,6 @@ +framework module Pods_ContainerControllerSwift_Example { + umbrella header "Pods-ContainerControllerSwift_Example-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.release.xcconfig new file mode 100644 index 0000000..cedf0a1 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Example/Pods-ContainerControllerSwift_Example.release.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "ContainerControllerSwift" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-Info.plist b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.markdown new file mode 100644 index 0000000..2a27ea6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.markdown @@ -0,0 +1,36 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## FBSnapshotTestCase + +BSD License + +For the FBSnapshotTestCase software + +Copyright (c) 2013, Facebook, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.plist new file mode 100644 index 0000000..7f6bd1a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-acknowledgements.plist @@ -0,0 +1,68 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + BSD License + +For the FBSnapshotTestCase software + +Copyright (c) 2013, Facebook, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + BSD + Title + FBSnapshotTestCase + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-dummy.m b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-dummy.m new file mode 100644 index 0000000..16ba5f4 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_ContainerControllerSwift_Tests : NSObject +@end +@implementation PodsDummy_Pods_ContainerControllerSwift_Tests +@end diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-frameworks.sh b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-frameworks.sh new file mode 100755 index 0000000..0a3acf6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-frameworks.sh @@ -0,0 +1,207 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +install_artifact() { + artifact="$1" + base="$(basename "$artifact")" + case $base in + *.framework) + install_framework "$artifact" + ;; + *.dSYM) + # Suppress arch warnings since XCFrameworks will include many dSYM files + install_dsym "$artifact" "false" + ;; + *.bcsymbolmap) + install_bcsymbolmap "$artifact" + ;; + *) + echo "error: Unrecognized artifact "$artifact"" + ;; + esac +} + +copy_artifacts() { + file_list="$1" + while read artifact; do + install_artifact "$artifact" + done <$file_list +} + +ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" +if [ -r "${ARTIFACT_LIST_FILE}" ]; then + copy_artifacts "${ARTIFACT_LIST_FILE}" +fi + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-umbrella.h b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-umbrella.h new file mode 100644 index 0000000..d0e271a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_ContainerControllerSwift_TestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_ContainerControllerSwift_TestsVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.debug.xcconfig new file mode 100644 index 0000000..1880dfd --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.debug.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "ContainerControllerSwift" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.modulemap b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.modulemap new file mode 100644 index 0000000..1ddf52a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_ContainerControllerSwift_Tests { + umbrella header "Pods-ContainerControllerSwift_Tests-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.release.xcconfig new file mode 100644 index 0000000..1880dfd --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-ContainerControllerSwift_Tests/Pods-ContainerControllerSwift_Tests.release.xcconfig @@ -0,0 +1,12 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ContainerControllerSwift/ContainerControllerSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSnapshotTestCase/FBSnapshotTestCase.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "ContainerControllerSwift" -framework "FBSnapshotTestCase" -framework "Foundation" -framework "QuartzCore" -framework "UIKit" -framework "XCTest" +OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES