├── Cartfile
├── .gitignore
├── Cartfile.resolved
├── Mensa
├── Dependencies
│ ├── Model.swift
│ ├── View.swift
│ └── Controller.swift
├── Sources
│ ├── Controller
│ │ ├── Identifier
│ │ │ ├── Identifier.swift
│ │ │ ├── ItemTypeIdentifier.swift
│ │ │ └── ItemTypeVariantIdentifier.swift
│ │ ├── Interface
│ │ │ ├── ItemInterfacing.swift
│ │ │ └── DataInterfacing.swift
│ │ └── Mediator
│ │ │ ├── ItemMediator.swift
│ │ │ └── DataMediator.swift
│ ├── View
│ │ ├── Hosting
│ │ │ ├── Table View
│ │ │ │ ├── HostingHeaderFooterView.swift
│ │ │ │ ├── HostingTableViewCell.swift
│ │ │ │ └── HostingTableView.swift
│ │ │ ├── HostingStrategy.swift
│ │ │ ├── Collection View
│ │ │ │ ├── HostingSupplementaryView.swift
│ │ │ │ ├── HostingCollectionViewCell.swift
│ │ │ │ └── HostingCollectionView.swift
│ │ │ └── HostingView.swift
│ │ ├── Reusable
│ │ │ └── ReusableView.swift
│ │ ├── Display
│ │ │ ├── DataDisplayContext.swift
│ │ │ ├── DataDisplaying.swift
│ │ │ └── ItemDisplaying.swift
│ │ └── Scrolling
│ │ │ └── ScrollEvent.swift
│ └── Model
│ │ └── Data
│ │ ├── SectionIndexPath.swift
│ │ ├── MutableDataSource.swift
│ │ ├── ItemPosition.swift
│ │ ├── Section.swift
│ │ ├── SingleSectionDataSource.swift
│ │ ├── MutableSingleSectionDataSource.swift
│ │ └── DataSource.swift
└── Resources
│ └── Info.plist
├── Mensa.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ ├── jkay010.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── Jordan.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
└── LICENSE
/Cartfile:
--------------------------------------------------------------------------------
1 | github "CultivR/Tangram" "0.2.0/view"
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | Carthage
3 | xcuserdata
4 | xcuserstate
5 |
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "CultivR/Tangram" "93175305a7bc397d8975009fc9a629ec4ae42b64"
2 |
--------------------------------------------------------------------------------
/Mensa/Dependencies/Model.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mensa.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/16/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
--------------------------------------------------------------------------------
/Mensa.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Mensa/Dependencies/View.swift:
--------------------------------------------------------------------------------
1 | //
2 | // View.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 3/27/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | @_exported import UIKit
10 | @_exported import Tangram
11 |
--------------------------------------------------------------------------------
/Mensa/Dependencies/Controller.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Controller.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | @_exported import UIKit
10 | @_exported import Tangram
11 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Identifier/Identifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Identifier.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/22/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | protocol Identifier: Hashable {
10 | var value: String { get }
11 | }
12 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Table View/HostingHeaderFooterView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HeaderFooterView.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 5/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | class HostingHeaderFooterView: UITableViewHeaderFooterView {}
10 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/HostingStrategy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HostingStrategy.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 6/7/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | enum HostingStrategy {
10 | case itemSize
11 | case viewSize
12 | case pinToEdges
13 | }
14 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Reusable/ReusableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ReusableView.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 5/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | //public protocol ReusableView: UIView {
10 | // var viewController: UIViewController! { get set }
11 | //}
12 |
--------------------------------------------------------------------------------
/Mensa.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/SectionIndexPath.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionIndexPath.swift
3 | // Model
4 | //
5 | // Created by Jordan Kay on 4/16/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | protocol SectionIndexPath {
10 | var section: Int { get }
11 | var row: Int { get }
12 | var item: Int { get }
13 | }
14 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Display/DataDisplayContext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataDisplayContext.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 5/8/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public enum DataDisplayContext {
10 | case tableView
11 | case collectionView(layout: UICollectionViewLayout)
12 | }
13 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Scrolling/ScrollEvent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ScrollEvent.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 6/5/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public enum ScrollEvent {
10 | case didScroll
11 | case willEndDragging(velocity: CGPoint, targetContentOffset: CGPoint)
12 | case didEndDecelerating
13 | case didEndScrollingAnimation
14 | }
15 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Identifier/ItemTypeIdentifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemTypeIdentifier.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/22/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | struct ItemTypeIdentifier {
10 | let value: String
11 |
12 | init(itemType: Any.Type) {
13 | value = String(describing: itemType)
14 | }
15 | }
16 |
17 | extension ItemTypeIdentifier: Identifier {}
18 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Identifier/ItemTypeVariantIdentifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemTypeVariantIdentifier.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/22/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | struct ItemTypeVariantIdentifier {
10 | let value: String
11 |
12 | init(itemTypeIdentifier: ItemTypeIdentifier, variant: Variant) {
13 | value = itemTypeIdentifier.value + variant.name
14 | }
15 | }
16 |
17 | extension ItemTypeVariantIdentifier: Identifier {}
18 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/MutableDataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MutableDataSource.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 6/5/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol MutableDataSource: DataSource where Item: Equatable {
10 | var sections: [Section- ] { get set }
11 | }
12 |
13 | // MARK: -
14 | extension MutableDataSource {
15 | mutating func setItem(_ item: Item, at indexPath: IndexPath) {
16 | sections[indexPath.section][indexPath.row] = item
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Mensa.xcodeproj/xcuserdata/jkay010.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Mensa.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 | MensaExample.xcscheme
13 |
14 | orderHint
15 | 1
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Collection View/HostingSupplementaryView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SupplementaryView.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 5/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | class HostingSupplementaryView: UICollectionReusableView {
10 | weak var viewController: UIViewController!
11 | }
12 |
13 | // MARK: -
14 | extension HostingSupplementaryView: HostingView {
15 | var contentView: UIView {
16 | return self
17 | }
18 |
19 | func addSizeConstraints(toHostedView hostedView: UIView) {
20 | return
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Display/DataDisplaying.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataDisplaying.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | protocol DataDisplaying: UIScrollView {
10 | var retainedDelegate: UIScrollViewDelegate { get }
11 |
12 | func reloadData()
13 |
14 | func register(_ hostingViewType: HostingView.Type, reuseIdentifier: String)
15 | func register(_ headerFooterViewType: HostingHeaderFooterView.Type, reuseIdentifier: String)
16 | func register(_ supplementaryViewType: HostingSupplementaryView.Type, reuseIdentifier: String)
17 | }
18 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Table View/HostingTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HostingTableViewCell.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | final class HostingTableViewCell: UITableViewCell {
10 | weak var viewController: UIViewController!
11 | }
12 |
13 | // MARK: -
14 | extension HostingTableViewCell: HostingView {
15 | func addSizeConstraints(toHostedView hostedView: UIView) {
16 | let heightConstraint = NSLayoutConstraint(item: hostedView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: hostedView.bounds.height)
17 | hostedView.addConstraint(heightConstraint)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/ItemPosition.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemPosition.swift
3 | // Model
4 | //
5 | // Created by Jordan Kay on 5/14/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public enum ItemPosition: String {
10 | case top
11 | case middle
12 | case bottom
13 | case lone
14 | }
15 |
16 | // MARK: -
17 | extension ItemPosition {
18 | init(indexPath: SectionIndexPath, itemCount: Int) {
19 | switch indexPath.item {
20 | case 0:
21 | self = (itemCount == 1) ? .lone : .top
22 | case itemCount - 1:
23 | self = .bottom
24 | default:
25 | self = .middle
26 | }
27 | }
28 | }
29 |
30 | // MARK: -
31 | extension ItemPosition: CaseIterable {}
32 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/Section.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Section.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public struct Section
- {
10 | let header: Header?
11 | var items: [Item]
12 |
13 | public init(header: Header? = nil, items: [Item]) {
14 | self.items = items
15 | self.header = header
16 | }
17 | }
18 |
19 | // MARK: -
20 | extension Section {
21 | var itemCount: Int {
22 | return items.count
23 | }
24 |
25 | subscript(index: Int) -> Item {
26 | get {
27 | return items[index]
28 | }
29 | set {
30 | items[index] = newValue
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/SingleSectionDataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SingleSectionDataSource.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol SingleSectionDataSource: DataSource {
10 | var items: [Item] { get }
11 | var header: Header? { get }
12 | }
13 |
14 | // MARK: -
15 | public extension SingleSectionDataSource {
16 | var header: Header? {
17 | return nil
18 | }
19 |
20 | func item(at index: Int) -> Item? {
21 | guard index >= 0, index < items.count else { return nil }
22 | return items[index]
23 | }
24 |
25 | // MARK: DataSource
26 | var sections: [Section
- ] {
27 | return [.init(header: header, items: items)]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Mensa/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/MutableSingleSectionDataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MutableSingleSectionDataSource.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 6/5/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol MutableSingleSectionDataSource: MutableDataSource {
10 | var items: [Item] { get set }
11 | }
12 |
13 | // MARK: -
14 | public extension MutableSingleSectionDataSource {
15 | var header: Header? {
16 | return nil
17 | }
18 |
19 | func item(at index: Int) -> Item? {
20 | guard index >= 0, index < items.count else { return nil }
21 | return items[index]
22 | }
23 |
24 | // MARK: DataSource
25 | var sections: [Section
- ] {
26 | get {
27 | return [.init(header: header, items: items)]
28 | }
29 | set {
30 | guard let section = newValue.first else { return }
31 | items = section.items
32 | }
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Collection View/HostingCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HostingCollectionViewCell.swift
3 | // Mensan
4 | //
5 | // Created by Jordan Kay on 5/7/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | final class HostingCollectionViewCell: UICollectionViewCell {
10 | weak var viewController: UIViewController!
11 | }
12 |
13 | // MARK: -
14 | extension HostingCollectionViewCell: HostingView {
15 | func addSizeConstraints(toHostedView hostedView: UIView) {
16 | let widthConstraint = NSLayoutConstraint(item: hostedView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: hostedView.bounds.width)
17 | let heightConstraint = NSLayoutConstraint(item: hostedView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: hostedView.bounds.height)
18 | let constraints = [widthConstraint, heightConstraint]
19 | hostedView.addConstraints(constraints)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Mensa.xcodeproj/xcuserdata/Jordan.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Controller.xcscheme
8 |
9 | orderHint
10 | 2
11 |
12 | MensaExample.xcscheme
13 |
14 | orderHint
15 | 1
16 |
17 | Model.xcscheme
18 |
19 | orderHint
20 | 0
21 |
22 | View.xcscheme
23 |
24 | orderHint
25 | 1
26 |
27 |
28 | SuppressBuildableAutocreation
29 |
30 | 17DFC9EF225E7E9C00871C7D
31 |
32 | primary
33 |
34 |
35 | 17F803042255940300212525
36 |
37 | primary
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Mensa/Sources/Model/Data/DataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataSource.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/3/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol DataSource {
10 | associatedtype Item
11 | associatedtype Header
12 |
13 | var sections: [Section
- ] { get }
14 | }
15 |
16 | // MARK: -
17 | extension DataSource {
18 | func item(at indexPath: IndexPath) -> Item {
19 | return sections[indexPath.section][indexPath.row]
20 | }
21 |
22 | func header(for section: Int) -> Header? {
23 | return sections[section].header
24 | }
25 | }
26 |
27 | // MARK: -
28 | extension DataSource where Item: Equatable {
29 | func indexPath(for item: Item) -> IndexPath? {
30 | for (sectionIndex, section) in sections.enumerated() {
31 | for (itemIndex, sectionItem) in section.items.enumerated() {
32 | if item == sectionItem {
33 | return IndexPath(item: itemIndex, section: sectionIndex)
34 | }
35 | }
36 | }
37 | return nil
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 CultivR
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Display/ItemDisplaying.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemDisplaying.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol ItemDisplaying: CustomDisplaying {
10 | typealias Item = Model
11 |
12 | static var itemDisplayVariants: [DisplayVariant] { get }
13 |
14 | func setHighlighted(_ highlighted: Bool, animated: Bool)
15 | }
16 |
17 | // MARK: -
18 | public extension ItemDisplaying {
19 | func setHighlighted(_ highlighted: Bool, animated: Bool) {
20 | return
21 | }
22 | }
23 |
24 | // MARK: -
25 | public extension ItemDisplaying where DisplayVariant == Invariant {
26 | static var defaultVariant: Invariant {
27 | return .init()
28 | }
29 |
30 | static var itemDisplayVariants: [Invariant] {
31 | return [.init()]
32 | }
33 | }
34 |
35 | public extension ItemDisplaying where DisplayVariant: CaseIterable, DisplayVariant.AllCases == [DisplayVariant] {
36 | static var itemDisplayVariants: [DisplayVariant] {
37 | return DisplayVariant.allCases
38 | }
39 | }
40 |
41 | // MARK: -
42 | extension ItemPosition: Variant {}
43 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Table View/HostingTableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HostingTableView.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/12/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | final class HostingTableView: UITableView {
10 | let retainedDelegate: UIScrollViewDelegate
11 |
12 | init(frame: CGRect, delegate: UITableViewDelegate) {
13 | retainedDelegate = delegate
14 | super.init(frame: frame, style: .plain)
15 | self.delegate = delegate
16 | autoresizingMask = [.flexibleWidth, .flexibleHeight]
17 | }
18 |
19 | required init?(coder: NSCoder) {
20 | fatalError()
21 | }
22 | }
23 |
24 | // MARK: -
25 | extension HostingTableView: DataDisplaying {
26 | // MARK: DataDisplaying
27 | func register(_ hostingViewType: HostingView.Type, reuseIdentifier: String) {
28 | register(hostingViewType, forCellReuseIdentifier: reuseIdentifier)
29 | }
30 |
31 | func register(_ headerFooterViewType: HostingHeaderFooterView.Type, reuseIdentifier: String) {
32 | register(headerFooterViewType, forHeaderFooterViewReuseIdentifier: reuseIdentifier)
33 | }
34 |
35 | func register(_ supplementaryViewType: HostingSupplementaryView.Type, reuseIdentifier: String) {
36 | return
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Interface/ItemInterfacing.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemInterfacing.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol ItemInterfacing: UIViewController {
10 | associatedtype View: ItemDisplaying
11 |
12 | func interface(with item: View.Item)
13 | func set(_ item: View.Item, selected: Bool)
14 | func select(_ item: View.Item)
15 | func deselect(_ item: View.Item)
16 | func shouldSelect(_ item: View.Item) -> Bool
17 | func prepareToSelect(_ item: View.Item)
18 | }
19 |
20 | public extension ItemInterfacing {
21 | var view: View {
22 | return view as! View
23 | }
24 |
25 | func interface(with item: View.Item) {
26 | view.display(item)
27 | }
28 |
29 | func set(_ item: View.Item, selected: Bool) {
30 | if selected {
31 | select(item)
32 | } else {
33 | deselect(item)
34 | }
35 | }
36 |
37 | func select(_ item: View.Item) {
38 | return
39 | }
40 |
41 | func deselect(_ item: View.Item) {
42 | return
43 | }
44 |
45 | func shouldSelect(_ item: View.Item) -> Bool {
46 | return true
47 | }
48 |
49 | func prepareToSelect(_ item: View.Item) {
50 | return
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/Collection View/HostingCollectionView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HostingCollectionView.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 5/7/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | final class HostingCollectionView: UICollectionView {
10 | let retainedDelegate: UIScrollViewDelegate
11 |
12 | init(frame: CGRect, layout: UICollectionViewLayout, delegate: UICollectionViewDelegate) {
13 | retainedDelegate = delegate
14 | super.init(frame: frame, collectionViewLayout: layout)
15 | self.delegate = delegate
16 |
17 | backgroundColor = .clear
18 | isPrefetchingEnabled = false
19 | autoresizingMask = [.flexibleWidth, .flexibleHeight]
20 | }
21 |
22 | required init?(coder: NSCoder) {
23 | fatalError()
24 | }
25 | }
26 |
27 | // MARK: -
28 | extension HostingCollectionView: DataDisplaying {
29 | // MARK: DataDisplaying
30 | func register(_ hostingViewType: HostingView.Type, reuseIdentifier: String) {
31 | register(hostingViewType, forCellWithReuseIdentifier: reuseIdentifier)
32 | }
33 |
34 | func register(_ headerFooterViewType: HostingHeaderFooterView.Type, reuseIdentifier: String) {
35 | return
36 | }
37 |
38 | func register(_ supplementaryViewType: HostingSupplementaryView.Type, reuseIdentifier: String) {
39 | register(supplementaryViewType, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: reuseIdentifier)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Mediator/ItemMediator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnyItemInterfacing.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/11/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | struct ItemMediator {
10 | let displayVariant: Variant
11 | let interface: (UIViewController, Any) -> Void
12 | let setSelected: (UIViewController, Any, Bool) -> Void
13 | let shouldSelect: (UIViewController, Any) -> Bool
14 | let prepareToSelect: (UIViewController, Any) -> Void
15 | let highlight: (UIViewController, Bool, Bool) -> Void
16 | }
17 |
18 | // MARK: -
19 | extension ItemMediator {
20 | init(interfaceType: Interface.Type, displayVariant: Interface.View.DisplayVariant, dataInterface: DataInterface) {
21 | self.displayVariant = displayVariant
22 | interface = { [weak dataInterface] in
23 | guard let dataInterface = dataInterface else { return }
24 |
25 | let viewController = $0 as! Interface
26 | let item = $1 as! Interface.View.Item
27 |
28 | if let item = item as? DataInterface.Item, let viewController = viewController as? DataInterface.ItemViewController {
29 | dataInterface.handleDisplayingItem(item, using: viewController)
30 | } else if let header = item as? DataInterface.Header, let viewController = viewController as? DataInterface.HeaderViewController {
31 | dataInterface.handleDisplayingHeader(header, using: viewController)
32 | }
33 | viewController.interface(with: item)
34 | }
35 | setSelected = {
36 | let viewController = $0 as! Interface
37 | let item = $1 as! Interface.View.Item
38 | let selected = $2
39 | viewController.set(item, selected: selected)
40 | }
41 | shouldSelect = {
42 | let viewController = $0 as! Interface
43 | let item = $1 as! Interface.View.Item
44 | return viewController.shouldSelect(item)
45 | }
46 | prepareToSelect = {
47 | let viewController = $0 as! Interface
48 | let item = $1 as! Interface.View.Item
49 | viewController.prepareToSelect(item)
50 | }
51 | highlight = {
52 | let viewController = $0 as! Interface
53 | let view: Interface.View = viewController.view
54 | view.setHighlighted($1, animated: $2)
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Mensa/Sources/View/Hosting/HostingView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Hosting.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | protocol HostingView: UIView {
10 | var contentView: UIView { get }
11 | var viewController: UIViewController! { get set }
12 |
13 | func addSizeConstraints(toHostedView hostedView: UIView)
14 | }
15 |
16 | // MARK: -
17 | extension HostingView {
18 | func hostContent(of type: NibLoadable.Type, from viewController: UIViewController, with variant: Variant) {
19 | let hostedView = type.hostedView(of: variant)
20 | hostedView.backgroundColor = .clear
21 | hostedView.frame.size.width = contentView.bounds.width
22 | viewController.view = hostedView
23 | viewController.viewDidLoad()
24 | self.viewController = viewController
25 |
26 | contentView.addSubview(hostedView)
27 | addEdgeConstraints(toHostedView: hostedView)
28 | }
29 | }
30 |
31 | // MARK: -
32 | private extension HostingView {
33 | func addEdgeConstraints(toHostedView hostedView: UIView) {
34 | for attribute: NSLayoutConstraint.Attribute in [.top, .left, .bottom, .right] {
35 | let constraint = NSLayoutConstraint(item: contentView, attribute: attribute, relatedBy: .equal, toItem: hostedView, attribute: attribute, multiplier: 1, constant: 0)
36 | if attribute == .bottom {
37 | constraint.priority -= 1
38 | }
39 | contentView.addConstraint(constraint)
40 | }
41 | }
42 |
43 | func addPinConstraints(withWidth width: CGFloat, toHostedView hostedView: UIView) {
44 | let widthConstraint = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1, constant: width)
45 | let heightConstraint = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1, constant: bounds.height)
46 | addConstraint(widthConstraint)
47 | addConstraint(heightConstraint)
48 |
49 | for attribute: NSLayoutConstraint.Attribute in [.top, .bottom,] {
50 | let constraint = NSLayoutConstraint(item: contentView, attribute: attribute, relatedBy: .equal, toItem: hostedView, attribute: attribute, multiplier: 1, constant: 0)
51 | if attribute == .bottom {
52 | constraint.priority -= 1
53 | }
54 | contentView.addConstraint(constraint)
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Interface/DataInterfacing.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataInterfacing.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | public protocol DataInterfacing: UIViewController, UIScrollViewDelegate {
10 | typealias Item = DataSourceType.Item
11 | typealias Header = DataSourceType.Header
12 |
13 | associatedtype DataSourceType: DataSource
14 | associatedtype ItemViewController: UIViewController = UIViewController
15 | associatedtype HeaderViewController: UIViewController = UIViewController
16 |
17 | var displayContext: DataDisplayContext { get }
18 |
19 | func displayVariant(for item: Item, at position: ItemPosition) -> Variant?
20 | func displayVariant(for header: Header) -> Variant?
21 | func prepareAndAddDataView(_ dataView: UIScrollView)
22 | func supportInterfacingWithData()
23 | func handleDisplayingItem(_ item: Item, using viewController: ItemViewController)
24 | func handleDisplayingHeader(_ header: Header, using viewController: HeaderViewController)
25 | func handle(_ scrollEvent: ScrollEvent, for scrollView: UIScrollView)
26 | }
27 |
28 | public extension DataInterfacing {
29 | var dataSource: DataSourceType? {
30 | return dataMediator?.dataSource
31 | }
32 |
33 | var scrollView: UIScrollView? {
34 | return dataView
35 | }
36 |
37 | var selectedItem: Item? {
38 | return dataMediator?.selectedIndexPath.flatMap { dataSource?.item(at: $0) }
39 | }
40 |
41 | func useData(from dataSource: DataSourceType, reload: Bool = true) {
42 | if let dataView = dataView {
43 | dataMediator.dataSource = dataSource
44 | if reload {
45 | dataView.reloadData()
46 | }
47 | } else {
48 | setupDataView()
49 | supportInterfacingWithData()
50 |
51 | dataView!.registerIdentifiers(for: displayContext, using: dataMediator)
52 | dataMediator.dataSource = dataSource
53 | }
54 | }
55 |
56 | // MARK: DataInterfacing
57 | func displayVariant(for item: Item, at position: ItemPosition) -> Variant? {
58 | return nil
59 | }
60 |
61 | func displayVariant(for header: Header) -> Variant? {
62 | return nil
63 | }
64 |
65 | func prepareAndAddDataView(_ dataView: UIScrollView) {
66 | dataView.alwaysBounceVertical = true
67 | view.addSubview(dataView)
68 | }
69 |
70 | func supportInterfacing(with itemType: Interface.View.Item.Type, conformedToBy conformingTypes: Any.Type..., using interfaceType: Interface.Type) {
71 | if conformingTypes.count > 0 {
72 | conformingTypes.forEach {
73 | dataMediator.supportInterfacing(with: $0, using: interfaceType)
74 | }
75 | } else {
76 | dataMediator.supportInterfacing(with: itemType, using: interfaceType)
77 | }
78 | }
79 |
80 | func handleDisplayingItem(_ item: Item, using viewController: ItemViewController) {
81 | return
82 | }
83 |
84 | func handleDisplayingHeader(_ header: Header, using viewController: HeaderViewController) {
85 | return
86 | }
87 |
88 | func handle(_ scrollEvent: ScrollEvent, for scrollView: UIScrollView) {
89 | return
90 | }
91 | }
92 |
93 | public extension DataInterfacing where Item: Equatable {
94 | func select(_ item: Item) {
95 | guard let indexPath = dataSource?.indexPath(for: item) else { return }
96 |
97 | dataMediator?.selectedIndexPath = indexPath
98 | }
99 |
100 | func select(_ item: Item, scrollPosition: UICollectionView.ScrollPosition, animated: Bool) {
101 | guard let indexPath = dataSource?.indexPath(for: item) else { return }
102 |
103 | position(item, at: scrollPosition, animated: animated)
104 | dataMediator?.selectedIndexPath = indexPath
105 | }
106 |
107 | func position(_ item: Item, at scrollPosition: UICollectionView.ScrollPosition, animated: Bool) {
108 | guard let indexPath = dataSource?.indexPath(for: item), let collectionView = collectionView else { return }
109 |
110 | collectionView.scrollToItem(at: indexPath, at: scrollPosition, animated: animated)
111 | }
112 | }
113 |
114 | public extension DataInterfacing where DataSourceType: MutableDataSource {
115 | func replace(_ item: Item, with replacementItem: Item) {
116 | guard let indexPath = dataSource?.indexPath(for: item) else { return }
117 |
118 | dataMediator?.dataSource?.setItem(replacementItem, at: indexPath)
119 | if let collectionView = collectionView {
120 | UIView.performWithoutAnimation {
121 | collectionView.reloadItems(at: [indexPath])
122 | }
123 | }
124 | }
125 | }
126 |
127 | private extension DataInterfacing {
128 | var dataView: DataDisplaying? {
129 | get {
130 | return objc_getAssociatedObject(self, &key) as? DataDisplaying
131 | }
132 | set {
133 | objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN)
134 | }
135 | }
136 |
137 | var tableView: UITableView? {
138 | return dataView as? UITableView
139 | }
140 |
141 | var collectionView: UICollectionView? {
142 | return dataView as? UICollectionView
143 | }
144 |
145 | var dataMediator: DataMediator! {
146 | return tableView?.delegate as? DataMediator ?? collectionView?.delegate as? DataMediator
147 | }
148 |
149 | func setupDataView() {
150 | let dataMediator = DataMediator(dataInterface: self)
151 |
152 | switch displayContext {
153 | case .tableView:
154 | setupTableView(with: dataMediator)
155 | case let .collectionView(layout):
156 | setupCollectionViewWith(dataMediator: dataMediator, layout: layout)
157 | }
158 | }
159 |
160 | func setupTableView(with dataMediator: DataMediator) {
161 | let tableView = HostingTableView(frame: view.bounds, delegate: dataMediator)
162 | tableView.dataSource = dataMediator
163 | dataView = tableView
164 | prepareAndAddDataView(tableView)
165 | }
166 |
167 | func setupCollectionViewWith(dataMediator: DataMediator, layout: UICollectionViewLayout) {
168 | let collectionView = HostingCollectionView(frame: view.bounds, layout: layout, delegate: dataMediator)
169 | collectionView.dataSource = dataMediator
170 | dataView = collectionView
171 | prepareAndAddDataView(collectionView)
172 | }
173 | }
174 |
175 | private extension DataDisplaying {
176 | func registerIdentifiers(for displayContext: DataDisplayContext, using dataMediator: DataMediator) {
177 | let identifiers = dataMediator.itemTypeVariantIdentifiers
178 | identifiers.forEach { register($0, for: displayContext) }
179 | }
180 |
181 | func register(_ identifier: ItemTypeVariantIdentifier, for displayContext: DataDisplayContext) {
182 | let reuseIdentifier = identifier.value
183 | switch displayContext {
184 | case .tableView:
185 | register(HostingTableViewCell.self, reuseIdentifier: reuseIdentifier)
186 | register(HostingHeaderFooterView.self, reuseIdentifier: reuseIdentifier)
187 | case .collectionView:
188 | register(HostingCollectionViewCell.self, reuseIdentifier: reuseIdentifier)
189 | register(HostingSupplementaryView.self, reuseIdentifier: reuseIdentifier)
190 | }
191 | }
192 | }
193 |
194 | // MARK: -
195 | private var key: Void?
196 |
--------------------------------------------------------------------------------
/Mensa/Sources/Controller/Mediator/DataMediator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataMediator.swift
3 | // Mensa
4 | //
5 | // Created by Jordan Kay on 4/10/19.
6 | // Copyright © 2019 CultivR. All rights reserved.
7 | //
8 |
9 | final class DataMediator: NSObject, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
10 | typealias Item = DataInterface.DataSourceType.Item
11 | typealias Header = DataInterface.DataSourceType.Header
12 |
13 | var dataSource: DataInterface.DataSourceType?
14 | var selectedIndexPath: IndexPath?
15 |
16 | private var defaultDisplayVariants: [ItemTypeIdentifier: Variant] = [:]
17 | private var itemMediators: [ItemTypeVariantIdentifier: ItemMediator] = [:]
18 | private var viewControllerTypes: [ItemTypeVariantIdentifier: UIViewController.Type] = [:]
19 | private var registeredSupplementaryViewIdentifiers: Set = []
20 | private var headerHeightCache: [Int: CGFloat] = [:]
21 |
22 | private weak var dataInterface: DataInterface!
23 |
24 | init(dataInterface: DataInterface) {
25 | self.dataInterface = dataInterface
26 | }
27 |
28 | // MARK: UIScrollViewDelegate
29 | func scrollViewDidScroll(_ scrollView: UIScrollView) {
30 | dataInterface.handle(.didScroll, for: scrollView)
31 | }
32 |
33 | func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) {
34 | let scrollEvent = ScrollEvent.willEndDragging(velocity: velocity, targetContentOffset: targetContentOffset.pointee)
35 | dataInterface.handle(scrollEvent, for: scrollView)
36 | }
37 |
38 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
39 | dataInterface.handle(.didEndDecelerating, for: scrollView)
40 | }
41 |
42 | func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
43 | dataInterface.handle(.didEndScrollingAnimation, for: scrollView)
44 | }
45 |
46 | // MARK: UITableViewDataSource
47 | func numberOfSections(in tableView: UITableView) -> Int {
48 | return sectionCount
49 | }
50 |
51 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
52 | return itemCount(forSection: section)
53 | }
54 |
55 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
56 | let (identifier, itemMediator, item) = info(for: indexPath)
57 | let cell = tableView.dequeueReusableCell(withIdentifier: identifier.value, for: indexPath) as! HostingView
58 | let viewController = cell.viewController ?? hostContent(in: cell, for: identifier)
59 |
60 | itemMediator.interface(viewController, item)
61 | return cell as! UITableViewCell
62 | }
63 |
64 | // MARK: UICollectionViewDataSource
65 | func numberOfSections(in collectionView: UICollectionView) -> Int {
66 | return sectionCount
67 | }
68 |
69 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
70 | return itemCount(forSection: section)
71 | }
72 |
73 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
74 | let (identifier, itemMediator, item) = info(for: indexPath)
75 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier.value, for: indexPath) as! HostingView
76 | let viewController = cell.viewController ?? hostContent(in: cell, for: identifier)
77 |
78 | itemMediator.interface(viewController, item)
79 | return cell as! UICollectionViewCell
80 | }
81 |
82 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
83 | switch kind {
84 | case UICollectionView.elementKindSectionHeader:
85 | guard let (identifier, itemMediator, header) = headerInfo(for: indexPath.section) else { return (nil as UICollectionReusableView?)! }
86 |
87 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: identifier.value, for: indexPath) as! HostingView
88 | let viewController = headerView.viewController ?? hostContent(in: headerView, for: identifier)
89 |
90 | itemMediator.interface(viewController, header)
91 | return headerView as! UICollectionReusableView
92 | default:
93 | return (nil as UICollectionReusableView?)!
94 | }
95 | }
96 |
97 | // MARK: UICollectionViewDelegate
98 | func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
99 | let (viewController, itemMediator, item) = viewControllerInfo(for: indexPath, in: collectionView)
100 | return itemMediator.shouldSelect(viewController, item)
101 | }
102 |
103 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
104 | let (viewController, itemMediator, item) = viewControllerInfo(for: indexPath, in: collectionView)
105 |
106 | itemMediator.prepareToSelect(viewController, item)
107 | selectedIndexPath = indexPath
108 | itemMediator.setSelected(viewController, item, true)
109 | }
110 |
111 | func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
112 | let (viewController, itemMediator, _) = viewControllerInfo(for: indexPath, in: collectionView)
113 | let highlighted = true
114 | let animated = false
115 |
116 | itemMediator.highlight(viewController, highlighted, animated)
117 | }
118 |
119 | func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
120 | let (viewController, itemMediator, _) = viewControllerInfo(for: indexPath, in: collectionView)
121 | let highlighted = false
122 | let animated = !collectionView.isDragging
123 |
124 | itemMediator.highlight(viewController, highlighted, animated)
125 | }
126 |
127 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
128 | guard let (identifier, itemMediator, _) = headerInfo(for: section) else { return .zero }
129 |
130 | let height = headerHeightCache[section] ?? {
131 | let viewControllerType = viewControllerTypes[identifier]!
132 | let viewType = self.viewType(for: viewControllerType)
133 | let displayVariant = itemMediator.displayVariant
134 | let view = viewType.hostedView(of: displayVariant)
135 | let height = view.bounds.height
136 | headerHeightCache[section] = height
137 | return height
138 | }()
139 |
140 | return .init(width: collectionView.bounds.width, height: height)
141 | }
142 | }
143 |
144 | // MARK: -
145 | extension DataMediator {
146 | var itemTypeVariantIdentifiers: [ItemTypeVariantIdentifier] {
147 | return Array(viewControllerTypes.keys)
148 | }
149 |
150 | func supportInterfacing(with itemType: Any.Type, using interfaceType: Interface.Type) {
151 | let variants = Interface.View.itemDisplayVariants
152 | for variant in variants {
153 | let itemTypeIdentifier = ItemTypeIdentifier(itemType: itemType)
154 | let itemTypeVariantIdentifier = ItemTypeVariantIdentifier(itemTypeIdentifier: itemTypeIdentifier, variant: variant)
155 |
156 | defaultDisplayVariants[itemTypeIdentifier] = Interface.View.defaultVariant
157 | itemMediators[itemTypeVariantIdentifier] = .init(interfaceType: interfaceType, displayVariant: variant, dataInterface: dataInterface)
158 | viewControllerTypes[itemTypeVariantIdentifier] = interfaceType
159 | }
160 | }
161 | }
162 |
163 | // MARK: -
164 | private extension DataMediator {
165 | var sectionCount: Int {
166 | let sections = dataSource?.sections
167 | return sections?.count ?? 0
168 | }
169 |
170 | func itemCount(forSection section: Int) -> Int {
171 | let section = dataSource?.sections[section]
172 | return section?.itemCount ?? 0
173 | }
174 |
175 | func info(for indexPath: IndexPath) -> (ItemTypeVariantIdentifier, ItemMediator, Item) {
176 | let item = dataSource!.item(at: indexPath)
177 | let itemType = type(of: item as Any)
178 | let itemTypeIdentifier = ItemTypeIdentifier(itemType: itemType)
179 | let itemCount = self.itemCount(forSection: indexPath.section)
180 | let itemPosition = ItemPosition(indexPath: indexPath, itemCount: itemCount)
181 | let displayVariant = dataInterface.displayVariant(for: item, at: itemPosition) ?? defaultDisplayVariants[itemTypeIdentifier] ?? Invariant()
182 | let itemTypeVariantIdentifier = ItemTypeVariantIdentifier(itemTypeIdentifier: itemTypeIdentifier, variant: displayVariant)
183 | let itemMediator = itemMediators[itemTypeVariantIdentifier]!
184 | return (itemTypeVariantIdentifier, itemMediator, item)
185 | }
186 |
187 | func headerInfo(for section: Int) -> (ItemTypeVariantIdentifier, ItemMediator, Header)? {
188 | guard let header = dataSource!.header(for: section) else { return nil }
189 |
190 | let itemType = type(of: header)
191 | let itemTypeIdentifier = ItemTypeIdentifier(itemType: itemType)
192 | let displayVariant = dataInterface.displayVariant(for: header) ?? defaultDisplayVariants[itemTypeIdentifier] ?? Invariant()
193 | let itemTypeVariantIdentifier = ItemTypeVariantIdentifier(itemTypeIdentifier: itemTypeIdentifier, variant: displayVariant)
194 | let itemMediator = itemMediators[itemTypeVariantIdentifier]!
195 | return (itemTypeVariantIdentifier, itemMediator, header)
196 | }
197 |
198 | func viewControllerInfo(for indexPath: IndexPath, in tableView: UITableView) -> (UIViewController, ItemMediator, Item) {
199 | let (_, itemMediator, item) = info(for: indexPath)
200 | let cell = tableView.cellForRow(at: indexPath) as! HostingView
201 | let viewController = cell.viewController!
202 | return (viewController, itemMediator, item)
203 | }
204 |
205 | func viewControllerInfo(for indexPath: IndexPath, in collectionView: UICollectionView) -> (UIViewController, ItemMediator, Item) {
206 | let (_, itemMediator, item) = info(for: indexPath)
207 | let cell = collectionView.cellForItem(at: indexPath) as! HostingView
208 | let viewController = cell.viewController!
209 | return (viewController, itemMediator, item)
210 | }
211 |
212 | func viewType(for viewControllerType: UIViewController.Type) -> NibLoadable.Type {
213 | let viewControllerName = String(describing: viewControllerType)
214 | let viewName = viewControllerName.replacingOccurrences(of: "Controller", with: "")
215 | return NSClassFromString("View.\(viewName)") as! NibLoadable.Type
216 | }
217 |
218 | func headerIdentifier(for section: Int) -> ItemTypeVariantIdentifier? {
219 | guard let header = dataSource?.sections[section].header else { return nil }
220 |
221 | let headerTypeIdentifier = ItemTypeIdentifier(itemType: type(of: header))
222 | return .init(itemTypeIdentifier: headerTypeIdentifier, variant: Invariant())
223 | }
224 |
225 | func hostContent(in hostingView: HostingView, for identifier: ItemTypeVariantIdentifier) -> UIViewController {
226 | let viewControllerType = viewControllerTypes[identifier]!
227 | let viewController = viewControllerType.init()
228 | let viewType = self.viewType(for: viewControllerType)
229 | let hostingViewController = dataInterface as UIViewController
230 | let mediator = itemMediators[identifier]!
231 | let displayVariant = mediator.displayVariant
232 |
233 | hostingView.hostContent(of: viewType, from: viewController, with: displayVariant)
234 | hostingViewController.addChild(viewController)
235 | viewController.didMove(toParent: hostingViewController)
236 |
237 | return viewController
238 | }
239 | }
240 |
241 | // MARK: -
242 | extension IndexPath: SectionIndexPath {}
243 |
244 | private extension CGSize {
245 | static let defaultItemSize: CGSize = .init(width: 50, height: 50)
246 | }
247 |
--------------------------------------------------------------------------------
/Mensa.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 172766182255983600C11D4A /* DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172766172255983600C11D4A /* DataSource.swift */; };
11 | 176A2549226E93100064488F /* Identifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176A2544226E92990064488F /* Identifier.swift */; };
12 | 176A254A226E93100064488F /* ItemTypeIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176A2547226E93040064488F /* ItemTypeIdentifier.swift */; };
13 | 176A254F226E967A0064488F /* ItemTypeVariantIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 176A254B226E93AA0064488F /* ItemTypeVariantIdentifier.swift */; };
14 | 17700131228B1BDB006EB3FD /* ItemPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17700130228B1BDB006EB3FD /* ItemPosition.swift */; };
15 | 17700132228B1C99006EB3FD /* ItemPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17700130228B1BDB006EB3FD /* ItemPosition.swift */; };
16 | 17700133228B1CA5006EB3FD /* ItemPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17700130228B1BDB006EB3FD /* ItemPosition.swift */; };
17 | 17718EFC22A834B3004351DE /* ScrollEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718EFA22A834B3004351DE /* ScrollEvent.swift */; };
18 | 17718EFD22A834BE004351DE /* ScrollEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718EFA22A834B3004351DE /* ScrollEvent.swift */; };
19 | 17718F0822A855E9004351DE /* MutableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F0722A855E9004351DE /* MutableDataSource.swift */; };
20 | 17718F0A22A8563C004351DE /* MutableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F0722A855E9004351DE /* MutableDataSource.swift */; };
21 | 17718F0C22A857F2004351DE /* MutableSingleSectionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F0B22A857F2004351DE /* MutableSingleSectionDataSource.swift */; };
22 | 17718F0D22A857F2004351DE /* MutableSingleSectionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F0B22A857F2004351DE /* MutableSingleSectionDataSource.swift */; };
23 | 17718F6422AB2685004351DE /* HostingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F6322AB2685004351DE /* HostingStrategy.swift */; };
24 | 17718F6522AB2685004351DE /* HostingStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17718F6322AB2685004351DE /* HostingStrategy.swift */; };
25 | 17D4F2352283720D00FDD335 /* DataDisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F2342283720D00FDD335 /* DataDisplayContext.swift */; };
26 | 17D4F2362283720D00FDD335 /* DataDisplayContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F2342283720D00FDD335 /* DataDisplayContext.swift */; };
27 | 17D4F27A2285E38700FDD335 /* HostingHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F2792285E38700FDD335 /* HostingHeaderFooterView.swift */; };
28 | 17D4F27B2285E38700FDD335 /* HostingHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F2792285E38700FDD335 /* HostingHeaderFooterView.swift */; };
29 | 17D4F27D2285E39500FDD335 /* HostingSupplementaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F27C2285E39400FDD335 /* HostingSupplementaryView.swift */; };
30 | 17D4F27E2285E39500FDD335 /* HostingSupplementaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F27C2285E39400FDD335 /* HostingSupplementaryView.swift */; };
31 | 17D4F2802285E8F200FDD335 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F27F2285E8F200FDD335 /* ReusableView.swift */; };
32 | 17D4F2812285E8F200FDD335 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17D4F27F2285E8F200FDD335 /* ReusableView.swift */; };
33 | 17DFC9E4225E6D4200871C7D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9E3225E6D4200871C7D /* Section.swift */; };
34 | 17DFC9E6225E6D8200871C7D /* SingleSectionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9E5225E6D8200871C7D /* SingleSectionDataSource.swift */; };
35 | 17DFC9F8225E7F2E00871C7D /* Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9E9225E7E8000871C7D /* Controller.swift */; };
36 | 17DFC9FA225E7F3600871C7D /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9E3225E6D4200871C7D /* Section.swift */; };
37 | 17DFC9FB225E7F3600871C7D /* DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 172766172255983600C11D4A /* DataSource.swift */; };
38 | 17DFC9FC225E7F3600871C7D /* SingleSectionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9E5225E6D8200871C7D /* SingleSectionDataSource.swift */; };
39 | 17DFCA02225EA56A00871C7D /* ItemDisplaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9FF225EA46400871C7D /* ItemDisplaying.swift */; };
40 | 17DFCA05225EA9B100871C7D /* ItemInterfacing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA03225EA58000871C7D /* ItemInterfacing.swift */; };
41 | 17DFCA06225EA9FA00871C7D /* ItemDisplaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFC9FF225EA46400871C7D /* ItemDisplaying.swift */; };
42 | 17DFCA1D225ECE3A00871C7D /* DataDisplaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA1B225ECE2C00871C7D /* DataDisplaying.swift */; };
43 | 17DFCA1F225ECEA100871C7D /* DataDisplaying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA1B225ECE2C00871C7D /* DataDisplaying.swift */; };
44 | 17DFCA2D225EDA8900871C7D /* DataMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA2B225EDA6D00871C7D /* DataMediator.swift */; };
45 | 17DFCA392260272200871C7D /* ItemMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA372260270300871C7D /* ItemMediator.swift */; };
46 | 17DFCA442261166100871C7D /* DataInterfacing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA09225EAA7000871C7D /* DataInterfacing.swift */; };
47 | 17DFCA5A2266958800871C7D /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA592266958800871C7D /* Model.swift */; };
48 | 17DFCA5C22669F7900871C7D /* SectionIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA5B22669F7900871C7D /* SectionIndexPath.swift */; };
49 | 17DFCA5D22669FB400871C7D /* SectionIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA5B22669F7900871C7D /* SectionIndexPath.swift */; };
50 | 17F29F0D22825CF0009F5121 /* HostingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17F29F0B22825CEE009F5121 /* HostingCollectionView.swift */; };
51 | 17F29F0E22825CF1009F5121 /* HostingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17F29F0B22825CEE009F5121 /* HostingCollectionView.swift */; };
52 | 17F29F1122825CFC009F5121 /* HostingCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17F29F0F22825CF9009F5121 /* HostingCollectionViewCell.swift */; };
53 | 17F29F1222825CFC009F5121 /* HostingCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17F29F0F22825CF9009F5121 /* HostingCollectionViewCell.swift */; };
54 | 17F6A9282266A3C000CBC866 /* HostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA28225ED9C600871C7D /* HostingView.swift */; };
55 | 17F6A9292266A3C000CBC866 /* HostingTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA40226113F100871C7D /* HostingTableView.swift */; };
56 | 17F6A92A2266A3C000CBC866 /* HostingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA25225ED98F00871C7D /* HostingTableViewCell.swift */; };
57 | 17F6A92B2266A3C100CBC866 /* HostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA28225ED9C600871C7D /* HostingView.swift */; };
58 | 17F6A92C2266A3C100CBC866 /* HostingTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA40226113F100871C7D /* HostingTableView.swift */; };
59 | 17F6A92D2266A3C100CBC866 /* HostingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17DFCA25225ED98F00871C7D /* HostingTableViewCell.swift */; };
60 | 17F80310225594A300212525 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1717B5BC224C479100E2ADF3 /* View.swift */; };
61 | /* End PBXBuildFile section */
62 |
63 | /* Begin PBXFileReference section */
64 | 1717B5BC224C479100E2ADF3 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; };
65 | 172766172255983600C11D4A /* DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSource.swift; sourceTree = ""; };
66 | 176A2544226E92990064488F /* Identifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identifier.swift; sourceTree = ""; };
67 | 176A2547226E93040064488F /* ItemTypeIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemTypeIdentifier.swift; sourceTree = ""; };
68 | 176A254B226E93AA0064488F /* ItemTypeVariantIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemTypeVariantIdentifier.swift; sourceTree = ""; };
69 | 17700130228B1BDB006EB3FD /* ItemPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPosition.swift; sourceTree = ""; };
70 | 17718EFA22A834B3004351DE /* ScrollEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollEvent.swift; sourceTree = ""; };
71 | 17718F0722A855E9004351DE /* MutableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutableDataSource.swift; sourceTree = ""; };
72 | 17718F0B22A857F2004351DE /* MutableSingleSectionDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutableSingleSectionDataSource.swift; sourceTree = ""; };
73 | 17718F6322AB2685004351DE /* HostingStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingStrategy.swift; sourceTree = ""; };
74 | 1772ABBA1D188BA0007DC99F /* Mensa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mensa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
75 | 1772ABBF1D188BA0007DC99F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
76 | 17D4F2342283720D00FDD335 /* DataDisplayContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDisplayContext.swift; sourceTree = ""; };
77 | 17D4F2792285E38700FDD335 /* HostingHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingHeaderFooterView.swift; sourceTree = ""; };
78 | 17D4F27C2285E39400FDD335 /* HostingSupplementaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingSupplementaryView.swift; sourceTree = ""; };
79 | 17D4F27F2285E8F200FDD335 /* ReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReusableView.swift; sourceTree = ""; };
80 | 17DFC9E3225E6D4200871C7D /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = ""; };
81 | 17DFC9E5225E6D8200871C7D /* SingleSectionDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleSectionDataSource.swift; sourceTree = ""; };
82 | 17DFC9E9225E7E8000871C7D /* Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Controller.swift; sourceTree = ""; };
83 | 17DFC9F0225E7E9C00871C7D /* Mensa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mensa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84 | 17DFC9FF225EA46400871C7D /* ItemDisplaying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDisplaying.swift; sourceTree = ""; };
85 | 17DFCA03225EA58000871C7D /* ItemInterfacing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemInterfacing.swift; sourceTree = ""; };
86 | 17DFCA09225EAA7000871C7D /* DataInterfacing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataInterfacing.swift; sourceTree = ""; };
87 | 17DFCA1B225ECE2C00871C7D /* DataDisplaying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDisplaying.swift; sourceTree = ""; };
88 | 17DFCA25225ED98F00871C7D /* HostingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingTableViewCell.swift; sourceTree = ""; };
89 | 17DFCA28225ED9C600871C7D /* HostingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingView.swift; sourceTree = ""; };
90 | 17DFCA2B225EDA6D00871C7D /* DataMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataMediator.swift; sourceTree = ""; };
91 | 17DFCA372260270300871C7D /* ItemMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemMediator.swift; sourceTree = ""; };
92 | 17DFCA40226113F100871C7D /* HostingTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingTableView.swift; sourceTree = ""; };
93 | 17DFCA592266958800871C7D /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = ""; };
94 | 17DFCA5B22669F7900871C7D /* SectionIndexPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionIndexPath.swift; sourceTree = ""; };
95 | 17F29F0B22825CEE009F5121 /* HostingCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingCollectionView.swift; sourceTree = ""; };
96 | 17F29F0F22825CF9009F5121 /* HostingCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingCollectionViewCell.swift; sourceTree = ""; };
97 | 17F803052255940300212525 /* Mensa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mensa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
98 | /* End PBXFileReference section */
99 |
100 | /* Begin PBXFrameworksBuildPhase section */
101 | 1772ABB61D188BA0007DC99F /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | );
106 | runOnlyForDeploymentPostprocessing = 0;
107 | };
108 | 17DFC9ED225E7E9C00871C7D /* Frameworks */ = {
109 | isa = PBXFrameworksBuildPhase;
110 | buildActionMask = 2147483647;
111 | files = (
112 | );
113 | runOnlyForDeploymentPostprocessing = 0;
114 | };
115 | 17F803022255940300212525 /* Frameworks */ = {
116 | isa = PBXFrameworksBuildPhase;
117 | buildActionMask = 2147483647;
118 | files = (
119 | );
120 | runOnlyForDeploymentPostprocessing = 0;
121 | };
122 | /* End PBXFrameworksBuildPhase section */
123 |
124 | /* Begin PBXGroup section */
125 | 1717B5B9224C478800E2ADF3 /* Dependencies */ = {
126 | isa = PBXGroup;
127 | children = (
128 | 17DFCA592266958800871C7D /* Model.swift */,
129 | 1717B5BC224C479100E2ADF3 /* View.swift */,
130 | 17DFC9E9225E7E8000871C7D /* Controller.swift */,
131 | );
132 | path = Dependencies;
133 | sourceTree = "";
134 | };
135 | 175B360C1EBD2060004FA581 /* Resources */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 1772ABBF1D188BA0007DC99F /* Info.plist */,
139 | );
140 | path = Resources;
141 | sourceTree = "";
142 | };
143 | 176A2546226E92F90064488F /* Identifier */ = {
144 | isa = PBXGroup;
145 | children = (
146 | 176A2544226E92990064488F /* Identifier.swift */,
147 | 176A2547226E93040064488F /* ItemTypeIdentifier.swift */,
148 | 176A254B226E93AA0064488F /* ItemTypeVariantIdentifier.swift */,
149 | );
150 | path = Identifier;
151 | sourceTree = "";
152 | };
153 | 17718EF922A8349D004351DE /* Scrolling */ = {
154 | isa = PBXGroup;
155 | children = (
156 | 17718EFA22A834B3004351DE /* ScrollEvent.swift */,
157 | );
158 | path = Scrolling;
159 | sourceTree = "";
160 | };
161 | 1772ABB01D188BA0007DC99F = {
162 | isa = PBXGroup;
163 | children = (
164 | 1772ABBC1D188BA0007DC99F /* Mensa */,
165 | 1772ABBB1D188BA0007DC99F /* Products */,
166 | );
167 | sourceTree = "";
168 | };
169 | 1772ABBB1D188BA0007DC99F /* Products */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 1772ABBA1D188BA0007DC99F /* Mensa.framework */,
173 | 17F803052255940300212525 /* Mensa.framework */,
174 | 17DFC9F0225E7E9C00871C7D /* Mensa.framework */,
175 | );
176 | name = Products;
177 | sourceTree = "";
178 | };
179 | 1772ABBC1D188BA0007DC99F /* Mensa */ = {
180 | isa = PBXGroup;
181 | children = (
182 | 17F8030D2255947300212525 /* Sources */,
183 | 1717B5B9224C478800E2ADF3 /* Dependencies */,
184 | 175B360C1EBD2060004FA581 /* Resources */,
185 | );
186 | path = Mensa;
187 | sourceTree = "";
188 | };
189 | 17D4F2782285E37500FDD335 /* Reusable */ = {
190 | isa = PBXGroup;
191 | children = (
192 | 17D4F27F2285E8F200FDD335 /* ReusableView.swift */,
193 | );
194 | path = Reusable;
195 | sourceTree = "";
196 | };
197 | 17DFC9E2225E6D3100871C7D /* Data */ = {
198 | isa = PBXGroup;
199 | children = (
200 | 17DFC9E3225E6D4200871C7D /* Section.swift */,
201 | 17DFCA5B22669F7900871C7D /* SectionIndexPath.swift */,
202 | 17700130228B1BDB006EB3FD /* ItemPosition.swift */,
203 | 172766172255983600C11D4A /* DataSource.swift */,
204 | 17718F0722A855E9004351DE /* MutableDataSource.swift */,
205 | 17DFC9E5225E6D8200871C7D /* SingleSectionDataSource.swift */,
206 | 17718F0B22A857F2004351DE /* MutableSingleSectionDataSource.swift */,
207 | );
208 | path = Data;
209 | sourceTree = "";
210 | };
211 | 17DFCA0B225EB8F200871C7D /* Controller */ = {
212 | isa = PBXGroup;
213 | children = (
214 | 176A2546226E92F90064488F /* Identifier */,
215 | 17DFCA20225ECEAB00871C7D /* Mediator */,
216 | 17DFCA10225EB9BF00871C7D /* Interface */,
217 | );
218 | path = Controller;
219 | sourceTree = "";
220 | };
221 | 17DFCA0C225EB91900871C7D /* Model */ = {
222 | isa = PBXGroup;
223 | children = (
224 | 17DFC9E2225E6D3100871C7D /* Data */,
225 | );
226 | path = Model;
227 | sourceTree = "";
228 | };
229 | 17DFCA0D225EB92900871C7D /* View */ = {
230 | isa = PBXGroup;
231 | children = (
232 | 17DFCA23225ED97B00871C7D /* Hosting */,
233 | 17DFCA0F225EB99500871C7D /* Display */,
234 | 17718EF922A8349D004351DE /* Scrolling */,
235 | 17D4F2782285E37500FDD335 /* Reusable */,
236 | );
237 | path = View;
238 | sourceTree = "";
239 | };
240 | 17DFCA0F225EB99500871C7D /* Display */ = {
241 | isa = PBXGroup;
242 | children = (
243 | 17DFC9FF225EA46400871C7D /* ItemDisplaying.swift */,
244 | 17DFCA1B225ECE2C00871C7D /* DataDisplaying.swift */,
245 | 17D4F2342283720D00FDD335 /* DataDisplayContext.swift */,
246 | );
247 | path = Display;
248 | sourceTree = "";
249 | };
250 | 17DFCA10225EB9BF00871C7D /* Interface */ = {
251 | isa = PBXGroup;
252 | children = (
253 | 17DFCA03225EA58000871C7D /* ItemInterfacing.swift */,
254 | 17DFCA09225EAA7000871C7D /* DataInterfacing.swift */,
255 | );
256 | path = Interface;
257 | sourceTree = "";
258 | };
259 | 17DFCA20225ECEAB00871C7D /* Mediator */ = {
260 | isa = PBXGroup;
261 | children = (
262 | 17DFCA372260270300871C7D /* ItemMediator.swift */,
263 | 17DFCA2B225EDA6D00871C7D /* DataMediator.swift */,
264 | );
265 | path = Mediator;
266 | sourceTree = "";
267 | };
268 | 17DFCA23225ED97B00871C7D /* Hosting */ = {
269 | isa = PBXGroup;
270 | children = (
271 | 17DFCA28225ED9C600871C7D /* HostingView.swift */,
272 | 17718F6322AB2685004351DE /* HostingStrategy.swift */,
273 | 17F29F0922825CB1009F5121 /* Table View */,
274 | 17F29F0A22825CB7009F5121 /* Collection View */,
275 | );
276 | path = Hosting;
277 | sourceTree = "";
278 | };
279 | 17F29F0922825CB1009F5121 /* Table View */ = {
280 | isa = PBXGroup;
281 | children = (
282 | 17DFCA40226113F100871C7D /* HostingTableView.swift */,
283 | 17DFCA25225ED98F00871C7D /* HostingTableViewCell.swift */,
284 | 17D4F2792285E38700FDD335 /* HostingHeaderFooterView.swift */,
285 | );
286 | path = "Table View";
287 | sourceTree = "";
288 | };
289 | 17F29F0A22825CB7009F5121 /* Collection View */ = {
290 | isa = PBXGroup;
291 | children = (
292 | 17F29F0B22825CEE009F5121 /* HostingCollectionView.swift */,
293 | 17F29F0F22825CF9009F5121 /* HostingCollectionViewCell.swift */,
294 | 17D4F27C2285E39400FDD335 /* HostingSupplementaryView.swift */,
295 | );
296 | path = "Collection View";
297 | sourceTree = "";
298 | };
299 | 17F8030D2255947300212525 /* Sources */ = {
300 | isa = PBXGroup;
301 | children = (
302 | 17DFCA0C225EB91900871C7D /* Model */,
303 | 17DFCA0D225EB92900871C7D /* View */,
304 | 17DFCA0B225EB8F200871C7D /* Controller */,
305 | );
306 | path = Sources;
307 | sourceTree = "";
308 | };
309 | /* End PBXGroup section */
310 |
311 | /* Begin PBXHeadersBuildPhase section */
312 | 1772ABB71D188BA0007DC99F /* Headers */ = {
313 | isa = PBXHeadersBuildPhase;
314 | buildActionMask = 2147483647;
315 | files = (
316 | );
317 | runOnlyForDeploymentPostprocessing = 0;
318 | };
319 | 17DFC9EB225E7E9C00871C7D /* Headers */ = {
320 | isa = PBXHeadersBuildPhase;
321 | buildActionMask = 2147483647;
322 | files = (
323 | );
324 | runOnlyForDeploymentPostprocessing = 0;
325 | };
326 | 17F803002255940300212525 /* Headers */ = {
327 | isa = PBXHeadersBuildPhase;
328 | buildActionMask = 2147483647;
329 | files = (
330 | );
331 | runOnlyForDeploymentPostprocessing = 0;
332 | };
333 | /* End PBXHeadersBuildPhase section */
334 |
335 | /* Begin PBXNativeTarget section */
336 | 1772ABB91D188BA0007DC99F /* Model */ = {
337 | isa = PBXNativeTarget;
338 | buildConfigurationList = 1772ABC21D188BA0007DC99F /* Build configuration list for PBXNativeTarget "Model" */;
339 | buildPhases = (
340 | 1772ABB51D188BA0007DC99F /* Sources */,
341 | 1772ABB61D188BA0007DC99F /* Frameworks */,
342 | 1772ABB71D188BA0007DC99F /* Headers */,
343 | 1772ABB81D188BA0007DC99F /* Resources */,
344 | );
345 | buildRules = (
346 | );
347 | dependencies = (
348 | );
349 | name = Model;
350 | productName = Mensa;
351 | productReference = 1772ABBA1D188BA0007DC99F /* Mensa.framework */;
352 | productType = "com.apple.product-type.framework";
353 | };
354 | 17DFC9EF225E7E9C00871C7D /* Controller */ = {
355 | isa = PBXNativeTarget;
356 | buildConfigurationList = 17DFC9F5225E7E9C00871C7D /* Build configuration list for PBXNativeTarget "Controller" */;
357 | buildPhases = (
358 | 17DFC9EB225E7E9C00871C7D /* Headers */,
359 | 17DFC9EC225E7E9C00871C7D /* Sources */,
360 | 17DFC9ED225E7E9C00871C7D /* Frameworks */,
361 | 17DFC9EE225E7E9C00871C7D /* Resources */,
362 | );
363 | buildRules = (
364 | );
365 | dependencies = (
366 | );
367 | name = Controller;
368 | productName = Controller;
369 | productReference = 17DFC9F0225E7E9C00871C7D /* Mensa.framework */;
370 | productType = "com.apple.product-type.framework";
371 | };
372 | 17F803042255940300212525 /* View */ = {
373 | isa = PBXNativeTarget;
374 | buildConfigurationList = 17F8030A2255940300212525 /* Build configuration list for PBXNativeTarget "View" */;
375 | buildPhases = (
376 | 17F803002255940300212525 /* Headers */,
377 | 17F803012255940300212525 /* Sources */,
378 | 17F803022255940300212525 /* Frameworks */,
379 | 17F803032255940300212525 /* Resources */,
380 | );
381 | buildRules = (
382 | );
383 | dependencies = (
384 | );
385 | name = View;
386 | productName = View;
387 | productReference = 17F803052255940300212525 /* Mensa.framework */;
388 | productType = "com.apple.product-type.framework";
389 | };
390 | /* End PBXNativeTarget section */
391 |
392 | /* Begin PBXProject section */
393 | 1772ABB11D188BA0007DC99F /* Project object */ = {
394 | isa = PBXProject;
395 | attributes = {
396 | LastSwiftUpdateCheck = 0800;
397 | LastUpgradeCheck = 1020;
398 | ORGANIZATIONNAME = CultivR;
399 | TargetAttributes = {
400 | 1772ABB91D188BA0007DC99F = {
401 | CreatedOnToolsVersion = 8.0;
402 | DevelopmentTeamName = "Jordan Kay (Personal Team)";
403 | LastSwiftMigration = 1020;
404 | ProvisioningStyle = Automatic;
405 | };
406 | 17DFC9EF225E7E9C00871C7D = {
407 | CreatedOnToolsVersion = 10.2;
408 | DevelopmentTeam = CVQ97C93T5;
409 | ProvisioningStyle = Automatic;
410 | };
411 | 17F803042255940300212525 = {
412 | CreatedOnToolsVersion = 10.2;
413 | DevelopmentTeam = CVQ97C93T5;
414 | ProvisioningStyle = Automatic;
415 | };
416 | };
417 | };
418 | buildConfigurationList = 1772ABB41D188BA0007DC99F /* Build configuration list for PBXProject "Mensa" */;
419 | compatibilityVersion = "Xcode 3.2";
420 | developmentRegion = en;
421 | hasScannedForEncodings = 0;
422 | knownRegions = (
423 | en,
424 | Base,
425 | );
426 | mainGroup = 1772ABB01D188BA0007DC99F;
427 | productRefGroup = 1772ABBB1D188BA0007DC99F /* Products */;
428 | projectDirPath = "";
429 | projectRoot = "";
430 | targets = (
431 | 1772ABB91D188BA0007DC99F /* Model */,
432 | 17F803042255940300212525 /* View */,
433 | 17DFC9EF225E7E9C00871C7D /* Controller */,
434 | );
435 | };
436 | /* End PBXProject section */
437 |
438 | /* Begin PBXResourcesBuildPhase section */
439 | 1772ABB81D188BA0007DC99F /* Resources */ = {
440 | isa = PBXResourcesBuildPhase;
441 | buildActionMask = 2147483647;
442 | files = (
443 | );
444 | runOnlyForDeploymentPostprocessing = 0;
445 | };
446 | 17DFC9EE225E7E9C00871C7D /* Resources */ = {
447 | isa = PBXResourcesBuildPhase;
448 | buildActionMask = 2147483647;
449 | files = (
450 | );
451 | runOnlyForDeploymentPostprocessing = 0;
452 | };
453 | 17F803032255940300212525 /* Resources */ = {
454 | isa = PBXResourcesBuildPhase;
455 | buildActionMask = 2147483647;
456 | files = (
457 | );
458 | runOnlyForDeploymentPostprocessing = 0;
459 | };
460 | /* End PBXResourcesBuildPhase section */
461 |
462 | /* Begin PBXSourcesBuildPhase section */
463 | 1772ABB51D188BA0007DC99F /* Sources */ = {
464 | isa = PBXSourcesBuildPhase;
465 | buildActionMask = 2147483647;
466 | files = (
467 | 17DFC9E4225E6D4200871C7D /* Section.swift in Sources */,
468 | 17DFCA5C22669F7900871C7D /* SectionIndexPath.swift in Sources */,
469 | 172766182255983600C11D4A /* DataSource.swift in Sources */,
470 | 17718F0C22A857F2004351DE /* MutableSingleSectionDataSource.swift in Sources */,
471 | 17700131228B1BDB006EB3FD /* ItemPosition.swift in Sources */,
472 | 17DFC9E6225E6D8200871C7D /* SingleSectionDataSource.swift in Sources */,
473 | 17DFCA5A2266958800871C7D /* Model.swift in Sources */,
474 | 17718F0822A855E9004351DE /* MutableDataSource.swift in Sources */,
475 | );
476 | runOnlyForDeploymentPostprocessing = 0;
477 | };
478 | 17DFC9EC225E7E9C00871C7D /* Sources */ = {
479 | isa = PBXSourcesBuildPhase;
480 | buildActionMask = 2147483647;
481 | files = (
482 | 17F29F1222825CFC009F5121 /* HostingCollectionViewCell.swift in Sources */,
483 | 17F6A92B2266A3C100CBC866 /* HostingView.swift in Sources */,
484 | 17718EFD22A834BE004351DE /* ScrollEvent.swift in Sources */,
485 | 176A254F226E967A0064488F /* ItemTypeVariantIdentifier.swift in Sources */,
486 | 176A2549226E93100064488F /* Identifier.swift in Sources */,
487 | 17F29F0D22825CF0009F5121 /* HostingCollectionView.swift in Sources */,
488 | 17DFCA06225EA9FA00871C7D /* ItemDisplaying.swift in Sources */,
489 | 17DFCA2D225EDA8900871C7D /* DataMediator.swift in Sources */,
490 | 17F6A92C2266A3C100CBC866 /* HostingTableView.swift in Sources */,
491 | 17D4F2362283720D00FDD335 /* DataDisplayContext.swift in Sources */,
492 | 17700133228B1CA5006EB3FD /* ItemPosition.swift in Sources */,
493 | 17D4F2812285E8F200FDD335 /* ReusableView.swift in Sources */,
494 | 17D4F27B2285E38700FDD335 /* HostingHeaderFooterView.swift in Sources */,
495 | 17DFC9FB225E7F3600871C7D /* DataSource.swift in Sources */,
496 | 17DFCA392260272200871C7D /* ItemMediator.swift in Sources */,
497 | 176A254A226E93100064488F /* ItemTypeIdentifier.swift in Sources */,
498 | 17DFCA1F225ECEA100871C7D /* DataDisplaying.swift in Sources */,
499 | 17DFC9F8225E7F2E00871C7D /* Controller.swift in Sources */,
500 | 17718F0D22A857F2004351DE /* MutableSingleSectionDataSource.swift in Sources */,
501 | 17DFCA5D22669FB400871C7D /* SectionIndexPath.swift in Sources */,
502 | 17D4F27E2285E39500FDD335 /* HostingSupplementaryView.swift in Sources */,
503 | 17F6A92D2266A3C100CBC866 /* HostingTableViewCell.swift in Sources */,
504 | 17DFCA442261166100871C7D /* DataInterfacing.swift in Sources */,
505 | 17DFC9FC225E7F3600871C7D /* SingleSectionDataSource.swift in Sources */,
506 | 17718F0A22A8563C004351DE /* MutableDataSource.swift in Sources */,
507 | 17DFC9FA225E7F3600871C7D /* Section.swift in Sources */,
508 | 17718F6522AB2685004351DE /* HostingStrategy.swift in Sources */,
509 | 17DFCA05225EA9B100871C7D /* ItemInterfacing.swift in Sources */,
510 | );
511 | runOnlyForDeploymentPostprocessing = 0;
512 | };
513 | 17F803012255940300212525 /* Sources */ = {
514 | isa = PBXSourcesBuildPhase;
515 | buildActionMask = 2147483647;
516 | files = (
517 | 17F29F0E22825CF1009F5121 /* HostingCollectionView.swift in Sources */,
518 | 17F6A92A2266A3C000CBC866 /* HostingTableViewCell.swift in Sources */,
519 | 17D4F27A2285E38700FDD335 /* HostingHeaderFooterView.swift in Sources */,
520 | 17D4F2802285E8F200FDD335 /* ReusableView.swift in Sources */,
521 | 17DFCA1D225ECE3A00871C7D /* DataDisplaying.swift in Sources */,
522 | 17718F6422AB2685004351DE /* HostingStrategy.swift in Sources */,
523 | 17DFCA02225EA56A00871C7D /* ItemDisplaying.swift in Sources */,
524 | 17D4F27D2285E39500FDD335 /* HostingSupplementaryView.swift in Sources */,
525 | 17718EFC22A834B3004351DE /* ScrollEvent.swift in Sources */,
526 | 17F6A9282266A3C000CBC866 /* HostingView.swift in Sources */,
527 | 17D4F2352283720D00FDD335 /* DataDisplayContext.swift in Sources */,
528 | 17F29F1122825CFC009F5121 /* HostingCollectionViewCell.swift in Sources */,
529 | 17700132228B1C99006EB3FD /* ItemPosition.swift in Sources */,
530 | 17F6A9292266A3C000CBC866 /* HostingTableView.swift in Sources */,
531 | 17F80310225594A300212525 /* View.swift in Sources */,
532 | );
533 | runOnlyForDeploymentPostprocessing = 0;
534 | };
535 | /* End PBXSourcesBuildPhase section */
536 |
537 | /* Begin XCBuildConfiguration section */
538 | 1772ABC01D188BA0007DC99F /* Debug */ = {
539 | isa = XCBuildConfiguration;
540 | buildSettings = {
541 | ALWAYS_SEARCH_USER_PATHS = NO;
542 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
543 | CLANG_ANALYZER_NONNULL = YES;
544 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
545 | CLANG_CXX_LIBRARY = "libc++";
546 | CLANG_ENABLE_MODULES = YES;
547 | CLANG_ENABLE_OBJC_ARC = YES;
548 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
549 | CLANG_WARN_BOOL_CONVERSION = YES;
550 | CLANG_WARN_COMMA = YES;
551 | CLANG_WARN_CONSTANT_CONVERSION = YES;
552 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
553 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
554 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
555 | CLANG_WARN_EMPTY_BODY = YES;
556 | CLANG_WARN_ENUM_CONVERSION = YES;
557 | CLANG_WARN_INFINITE_RECURSION = YES;
558 | CLANG_WARN_INT_CONVERSION = YES;
559 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
560 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
561 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
562 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
563 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
564 | CLANG_WARN_STRICT_PROTOTYPES = YES;
565 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
566 | CLANG_WARN_UNREACHABLE_CODE = YES;
567 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
568 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
569 | COPY_PHASE_STRIP = NO;
570 | CURRENT_PROJECT_VERSION = 1;
571 | DEBUG_INFORMATION_FORMAT = dwarf;
572 | ENABLE_STRICT_OBJC_MSGSEND = YES;
573 | ENABLE_TESTABILITY = YES;
574 | GCC_C_LANGUAGE_STANDARD = gnu99;
575 | GCC_DYNAMIC_NO_PIC = NO;
576 | GCC_NO_COMMON_BLOCKS = YES;
577 | GCC_OPTIMIZATION_LEVEL = 0;
578 | GCC_PREPROCESSOR_DEFINITIONS = (
579 | "DEBUG=1",
580 | "$(inherited)",
581 | );
582 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
583 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
584 | GCC_WARN_UNDECLARED_SELECTOR = YES;
585 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
586 | GCC_WARN_UNUSED_FUNCTION = YES;
587 | GCC_WARN_UNUSED_VARIABLE = YES;
588 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
589 | MTL_ENABLE_DEBUG_INFO = YES;
590 | ONLY_ACTIVE_ARCH = YES;
591 | SDKROOT = iphoneos;
592 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
593 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
594 | TARGETED_DEVICE_FAMILY = "1,2";
595 | VERSIONING_SYSTEM = "apple-generic";
596 | VERSION_INFO_PREFIX = "";
597 | };
598 | name = Debug;
599 | };
600 | 1772ABC11D188BA0007DC99F /* Release */ = {
601 | isa = XCBuildConfiguration;
602 | buildSettings = {
603 | ALWAYS_SEARCH_USER_PATHS = NO;
604 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
605 | CLANG_ANALYZER_NONNULL = YES;
606 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
607 | CLANG_CXX_LIBRARY = "libc++";
608 | CLANG_ENABLE_MODULES = YES;
609 | CLANG_ENABLE_OBJC_ARC = YES;
610 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
611 | CLANG_WARN_BOOL_CONVERSION = YES;
612 | CLANG_WARN_COMMA = YES;
613 | CLANG_WARN_CONSTANT_CONVERSION = YES;
614 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
615 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
616 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
617 | CLANG_WARN_EMPTY_BODY = YES;
618 | CLANG_WARN_ENUM_CONVERSION = YES;
619 | CLANG_WARN_INFINITE_RECURSION = YES;
620 | CLANG_WARN_INT_CONVERSION = YES;
621 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
622 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
623 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
624 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
625 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
626 | CLANG_WARN_STRICT_PROTOTYPES = YES;
627 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
628 | CLANG_WARN_UNREACHABLE_CODE = YES;
629 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
630 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
631 | COPY_PHASE_STRIP = NO;
632 | CURRENT_PROJECT_VERSION = 1;
633 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
634 | ENABLE_NS_ASSERTIONS = NO;
635 | ENABLE_STRICT_OBJC_MSGSEND = YES;
636 | GCC_C_LANGUAGE_STANDARD = gnu99;
637 | GCC_NO_COMMON_BLOCKS = YES;
638 | GCC_OPTIMIZATION_LEVEL = fast;
639 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
640 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
641 | GCC_WARN_UNDECLARED_SELECTOR = YES;
642 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
643 | GCC_WARN_UNUSED_FUNCTION = YES;
644 | GCC_WARN_UNUSED_VARIABLE = YES;
645 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
646 | MTL_ENABLE_DEBUG_INFO = NO;
647 | SDKROOT = iphoneos;
648 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
649 | TARGETED_DEVICE_FAMILY = "1,2";
650 | VALIDATE_PRODUCT = YES;
651 | VERSIONING_SYSTEM = "apple-generic";
652 | VERSION_INFO_PREFIX = "";
653 | };
654 | name = Release;
655 | };
656 | 1772ABC31D188BA0007DC99F /* Debug */ = {
657 | isa = XCBuildConfiguration;
658 | buildSettings = {
659 | CLANG_ENABLE_MODULES = YES;
660 | CODE_SIGN_IDENTITY = "";
661 | DEFINES_MODULE = YES;
662 | DEVELOPMENT_TEAM = "";
663 | DYLIB_COMPATIBILITY_VERSION = 1;
664 | DYLIB_CURRENT_VERSION = 1;
665 | DYLIB_INSTALL_NAME_BASE = "@rpath";
666 | ENABLE_BITCODE = NO;
667 | INFOPLIST_FILE = Mensa/Resources/Info.plist;
668 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
669 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
670 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
671 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
672 | PRODUCT_NAME = Mensa;
673 | SKIP_INSTALL = YES;
674 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
675 | SWIFT_VERSION = 5.0;
676 | };
677 | name = Debug;
678 | };
679 | 1772ABC41D188BA0007DC99F /* Release */ = {
680 | isa = XCBuildConfiguration;
681 | buildSettings = {
682 | CLANG_ENABLE_MODULES = YES;
683 | CODE_SIGN_IDENTITY = "";
684 | DEFINES_MODULE = YES;
685 | DEVELOPMENT_TEAM = "";
686 | DYLIB_COMPATIBILITY_VERSION = 1;
687 | DYLIB_CURRENT_VERSION = 1;
688 | DYLIB_INSTALL_NAME_BASE = "@rpath";
689 | ENABLE_BITCODE = NO;
690 | INFOPLIST_FILE = Mensa/Resources/Info.plist;
691 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
692 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
693 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
694 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
695 | PRODUCT_NAME = Mensa;
696 | SKIP_INSTALL = YES;
697 | SWIFT_OPTIMIZATION_LEVEL = "-O";
698 | SWIFT_VERSION = 5.0;
699 | };
700 | name = Release;
701 | };
702 | 17DFC9F6225E7E9C00871C7D /* Debug */ = {
703 | isa = XCBuildConfiguration;
704 | buildSettings = {
705 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
706 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
707 | CLANG_ENABLE_OBJC_WEAK = YES;
708 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
709 | CODE_SIGN_IDENTITY = "iPhone Developer";
710 | CODE_SIGN_STYLE = Automatic;
711 | DEFINES_MODULE = YES;
712 | DEVELOPMENT_TEAM = CVQ97C93T5;
713 | DYLIB_COMPATIBILITY_VERSION = 1;
714 | DYLIB_CURRENT_VERSION = 1;
715 | DYLIB_INSTALL_NAME_BASE = "@rpath";
716 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
717 | GCC_C_LANGUAGE_STANDARD = gnu11;
718 | INFOPLIST_FILE = "$(SRCROOT)/Mensa/Resources/Info.plist";
719 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
720 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
721 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
722 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
723 | MTL_FAST_MATH = YES;
724 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
725 | PRODUCT_NAME = Mensa;
726 | SKIP_INSTALL = YES;
727 | SWIFT_VERSION = 5.0;
728 | TARGETED_DEVICE_FAMILY = "1,2";
729 | };
730 | name = Debug;
731 | };
732 | 17DFC9F7225E7E9C00871C7D /* Release */ = {
733 | isa = XCBuildConfiguration;
734 | buildSettings = {
735 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
736 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
737 | CLANG_ENABLE_OBJC_WEAK = YES;
738 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
739 | CODE_SIGN_IDENTITY = "iPhone Developer";
740 | CODE_SIGN_STYLE = Automatic;
741 | DEFINES_MODULE = YES;
742 | DEVELOPMENT_TEAM = CVQ97C93T5;
743 | DYLIB_COMPATIBILITY_VERSION = 1;
744 | DYLIB_CURRENT_VERSION = 1;
745 | DYLIB_INSTALL_NAME_BASE = "@rpath";
746 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
747 | GCC_C_LANGUAGE_STANDARD = gnu11;
748 | INFOPLIST_FILE = "$(SRCROOT)/Mensa/Resources/Info.plist";
749 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
750 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
751 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
752 | MTL_FAST_MATH = YES;
753 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
754 | PRODUCT_NAME = Mensa;
755 | SKIP_INSTALL = YES;
756 | SWIFT_VERSION = 5.0;
757 | TARGETED_DEVICE_FAMILY = "1,2";
758 | };
759 | name = Release;
760 | };
761 | 17F8030B2255940300212525 /* Debug */ = {
762 | isa = XCBuildConfiguration;
763 | buildSettings = {
764 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
765 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
766 | CLANG_ENABLE_OBJC_WEAK = YES;
767 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
768 | CODE_SIGN_IDENTITY = "iPhone Developer";
769 | CODE_SIGN_STYLE = Automatic;
770 | DEFINES_MODULE = YES;
771 | DEVELOPMENT_TEAM = CVQ97C93T5;
772 | DYLIB_COMPATIBILITY_VERSION = 1;
773 | DYLIB_CURRENT_VERSION = 1;
774 | DYLIB_INSTALL_NAME_BASE = "@rpath";
775 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
776 | GCC_C_LANGUAGE_STANDARD = gnu11;
777 | INFOPLIST_FILE = "$(SRCROOT)/Mensa/Resources/Info.plist";
778 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
779 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
780 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
781 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
782 | MTL_FAST_MATH = YES;
783 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
784 | PRODUCT_NAME = Mensa;
785 | SKIP_INSTALL = YES;
786 | SWIFT_VERSION = 5.0;
787 | TARGETED_DEVICE_FAMILY = "1,2";
788 | };
789 | name = Debug;
790 | };
791 | 17F8030C2255940300212525 /* Release */ = {
792 | isa = XCBuildConfiguration;
793 | buildSettings = {
794 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
795 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
796 | CLANG_ENABLE_OBJC_WEAK = YES;
797 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
798 | CODE_SIGN_IDENTITY = "iPhone Developer";
799 | CODE_SIGN_STYLE = Automatic;
800 | DEFINES_MODULE = YES;
801 | DEVELOPMENT_TEAM = CVQ97C93T5;
802 | DYLIB_COMPATIBILITY_VERSION = 1;
803 | DYLIB_CURRENT_VERSION = 1;
804 | DYLIB_INSTALL_NAME_BASE = "@rpath";
805 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS";
806 | GCC_C_LANGUAGE_STANDARD = gnu11;
807 | INFOPLIST_FILE = "$(SRCROOT)/Mensa/Resources/Info.plist";
808 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
809 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
810 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
811 | MTL_FAST_MATH = YES;
812 | PRODUCT_BUNDLE_IDENTIFIER = co.cultivr.Mensa;
813 | PRODUCT_NAME = Mensa;
814 | SKIP_INSTALL = YES;
815 | SWIFT_VERSION = 5.0;
816 | TARGETED_DEVICE_FAMILY = "1,2";
817 | };
818 | name = Release;
819 | };
820 | /* End XCBuildConfiguration section */
821 |
822 | /* Begin XCConfigurationList section */
823 | 1772ABB41D188BA0007DC99F /* Build configuration list for PBXProject "Mensa" */ = {
824 | isa = XCConfigurationList;
825 | buildConfigurations = (
826 | 1772ABC01D188BA0007DC99F /* Debug */,
827 | 1772ABC11D188BA0007DC99F /* Release */,
828 | );
829 | defaultConfigurationIsVisible = 0;
830 | defaultConfigurationName = Release;
831 | };
832 | 1772ABC21D188BA0007DC99F /* Build configuration list for PBXNativeTarget "Model" */ = {
833 | isa = XCConfigurationList;
834 | buildConfigurations = (
835 | 1772ABC31D188BA0007DC99F /* Debug */,
836 | 1772ABC41D188BA0007DC99F /* Release */,
837 | );
838 | defaultConfigurationIsVisible = 0;
839 | defaultConfigurationName = Release;
840 | };
841 | 17DFC9F5225E7E9C00871C7D /* Build configuration list for PBXNativeTarget "Controller" */ = {
842 | isa = XCConfigurationList;
843 | buildConfigurations = (
844 | 17DFC9F6225E7E9C00871C7D /* Debug */,
845 | 17DFC9F7225E7E9C00871C7D /* Release */,
846 | );
847 | defaultConfigurationIsVisible = 0;
848 | defaultConfigurationName = Release;
849 | };
850 | 17F8030A2255940300212525 /* Build configuration list for PBXNativeTarget "View" */ = {
851 | isa = XCConfigurationList;
852 | buildConfigurations = (
853 | 17F8030B2255940300212525 /* Debug */,
854 | 17F8030C2255940300212525 /* Release */,
855 | );
856 | defaultConfigurationIsVisible = 0;
857 | defaultConfigurationName = Release;
858 | };
859 | /* End XCConfigurationList section */
860 | };
861 | rootObject = 1772ABB11D188BA0007DC99F /* Project object */;
862 | }
863 |
--------------------------------------------------------------------------------