(type: T.Type, nibName name: String, bundle bundleOrNil: Bundle?, withOwner ownerOrNil: Any?, options optionsOrNil: [UINib.OptionsKey: Any]? = nil) -> T? {
47 |
48 | for any in self.init(nibName: name, bundle: bundleOrNil).instantiate(withOwner: ownerOrNil, options: optionsOrNil) {
49 | if let obj = any as? T {
50 | return obj
51 | }
52 | }
53 | return nil
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UIApplicationSupportsIndirectInputEvents
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Sample/ViewController/MyPostViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MyPostViewController.swift
3 | // Sample
4 | //
5 | // Created by 田中厳貴 on 2021/01/26.
6 | //
7 |
8 | import UIKit
9 | import TopContentPager
10 |
11 | final class MyPostViewController: UIViewController, ContentTableBody {
12 | enum Const {
13 | static let margin: CGFloat = 2
14 | static let itemSpace: CGFloat = 1
15 | }
16 |
17 | var pagerItem: PagerItem = .text(.init(title: "投稿"))
18 | var scrollView: UIScrollView!
19 | @IBOutlet weak var collectionView: UICollectionView! {
20 | didSet {
21 | scrollView = collectionView
22 | }
23 | }
24 |
25 | static func create() -> Self {
26 | Storyboard.instantiate(self)
27 | }
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 | collectionView.dataSource = self
32 | setup()
33 | }
34 |
35 | private func setup() {
36 | collectionView.register(UINib(nibName: "MyPostCollectionCell", bundle: nil), forCellWithReuseIdentifier: "MyPostCollectionCell")
37 | let layout = UICollectionViewFlowLayout()
38 | let length = self.view.frame.width / 3 - ((Const.margin * 2 + Const.itemSpace * 2) / 2)
39 | layout.itemSize = CGSize(width: length, height: length)
40 | layout.sectionInset = UIEdgeInsets(top: Const.margin, left: Const.margin, bottom: Const.margin, right: Const.margin)
41 | layout.minimumInteritemSpacing = Const.itemSpace
42 | layout.minimumLineSpacing = Const.itemSpace * 2
43 | collectionView.collectionViewLayout = layout
44 | }
45 |
46 | override func viewDidAppear(_ animated: Bool) {
47 | super.viewDidAppear(animated)
48 | collectionView.reloadData()
49 | }
50 | }
51 |
52 | extension MyPostViewController: UICollectionViewDataSource {
53 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
54 | MockData.postList.count
55 | }
56 |
57 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
58 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyPostCollectionCell", for: indexPath) as! MyPostCollectionCell
59 | cell.prepare(image: MockData.postList[indexPath.row])
60 | return cell
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Sample/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // Sample
4 | //
5 | // Created by 田中厳貴 on 2021/01/08.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/TopContentPager/TopContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TopContentView.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/01/26.
6 | //
7 |
8 | import UIKit
9 |
10 | protocol TopContentViewDelegate: AnyObject {
11 | func needsReload()
12 | }
13 |
14 | public protocol TopContentViewDataSource: AnyObject {
15 | func topContentViewHeight(_ view: TopContentView) -> CGFloat?
16 | }
17 |
18 | open class TopContentView: UIView {
19 |
20 | open var isHideTabView: Bool {
21 | false
22 | }
23 |
24 | public weak var dataSource: TopContentViewDataSource?
25 | public var tabView: PagerItemsView?
26 |
27 | weak var delegate: TopContentViewDelegate?
28 | var tabViewHeight: CGFloat {
29 | tabView?.options.itemHeight ?? 0
30 | }
31 | var estimateHeight: CGFloat {
32 | if let height = dataSource?.topContentViewHeight(self) {
33 | return height
34 | } else {
35 | return self.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize, withHorizontalFittingPriority: .fittingSizeLevel, verticalFittingPriority: .defaultLow).height
36 | }
37 | }
38 |
39 | private var tabViewHeightConstraint: NSLayoutConstraint?
40 |
41 | open override func awakeFromNib() {
42 | super.awakeFromNib()
43 | if !isHideTabView {
44 | tabView = .init()
45 | setupTab()
46 | }
47 | }
48 |
49 | public func updateTab(options: UpdatePagerOptions) {
50 | tabView?.update(pagerOptions: options)
51 | tabViewHeightConstraint?.constant = tabViewHeight
52 | updateLayout()
53 | }
54 |
55 | public func updateLayout() {
56 | UIView.animate(withDuration: 0) {
57 | self.removeFromSuperview()
58 | self.layoutIfNeeded()
59 | self.delegate?.needsReload()
60 | }
61 | }
62 |
63 | private func setupTab() {
64 | guard let tabView = tabView else { return }
65 | tabView.update(pagerOptions: .init())
66 | tabView.autoresizingMask = .flexibleWidth
67 | tabView.translatesAutoresizingMaskIntoConstraints = false
68 | self.addSubview(tabView)
69 | tabViewHeightConstraint = tabView.heightAnchor.constraint(equalToConstant: tabViewHeight)
70 | NSLayoutConstraint.activate([
71 | tabView.leadingAnchor.constraint(equalTo: leadingAnchor),
72 | tabView.trailingAnchor.constraint(equalTo: trailingAnchor),
73 | tabView.bottomAnchor.constraint(equalTo: bottomAnchor),
74 | tabViewHeightConstraint!
75 | ])
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Sample/Cell/MyPostCollectionCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/TopContentPager/View/PagerOptions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PagerOptions.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/01/08.
6 | //
7 |
8 | import UIKit
9 |
10 | final public class PagerOptions {
11 | public var itemHeight: CGFloat = 44
12 | public var indicatorHeight: CGFloat = 2
13 | public var indicatorColor: UIColor = UIColor.black
14 | public var activeBackgroundColor: UIColor = UIColor.clear
15 | public var backgroundColor: UIColor = UIColor.white
16 | public var lineColor: UIColor = UIColor.white
17 | public var deactiveLabelColor: UIColor = UIColor.gray
18 | public var activeLabelColor: UIColor = UIColor.black
19 | public var indicatorSideSpace: CGFloat = 0
20 |
21 | init() {
22 |
23 | }
24 |
25 | init(itemHeight: CGFloat = 44,
26 | indicatorHeight: CGFloat = 2,
27 | indicatorColor: UIColor = UIColor.black,
28 | activeBackgroundColor: UIColor = UIColor.clear,
29 | backgroundColor: UIColor = UIColor.white,
30 | lineColor: UIColor = UIColor.white,
31 | deactiveLabelColor: UIColor = UIColor.gray,
32 | activeLabelColor: UIColor = UIColor.black,
33 | indicatorSideSpace: CGFloat = 0) {
34 | self.itemHeight = itemHeight
35 | self.indicatorHeight = indicatorHeight
36 | self.indicatorColor = indicatorColor
37 | self.activeBackgroundColor = activeBackgroundColor
38 | self.backgroundColor = backgroundColor
39 | self.lineColor = lineColor
40 | self.deactiveLabelColor = deactiveLabelColor
41 | self.activeLabelColor = activeLabelColor
42 | self.indicatorSideSpace = indicatorSideSpace
43 | }
44 | }
45 |
46 | final public class UpdatePagerOptions {
47 | public var itemHeight: CGFloat?
48 | public var indicatorHeight: CGFloat?
49 | public var indicatorColor: UIColor?
50 | public var activeBackgroundColor: UIColor?
51 | public var backgroundColor: UIColor?
52 | public var lineColor: UIColor?
53 | public var deactiveLabelColor: UIColor?
54 | public var activeLabelColor: UIColor?
55 | public var indicatorSideSpace: CGFloat?
56 |
57 | public init() { }
58 |
59 | public init(itemHeight: CGFloat? = nil,
60 | indicatorHeight: CGFloat? = nil,
61 | indicatorColor: UIColor? = nil,
62 | activeBackgroundColor: UIColor? = nil,
63 | backgroundColor: UIColor? = nil,
64 | lineColor: UIColor? = nil,
65 | deactiveLabelColor: UIColor? = nil,
66 | activeLabelColor: UIColor? = nil,
67 | indicatorSideSpace: CGFloat? = nil) {
68 | self.itemHeight = itemHeight
69 | self.indicatorHeight = indicatorHeight
70 | self.indicatorColor = indicatorColor
71 | self.activeBackgroundColor = activeBackgroundColor
72 | self.backgroundColor = backgroundColor
73 | self.lineColor = lineColor
74 | self.deactiveLabelColor = deactiveLabelColor
75 | self.activeLabelColor = activeLabelColor
76 | self.indicatorSideSpace = indicatorSideSpace
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Sample/ViewController/TimelineViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Sample/ViewController/NotificationViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Sample/ViewController/MyPostViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Sample/Cell/NotificationTableCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/TopContentPager/View/DefaultPagerItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultPagerItemView.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/02/10.
6 | //
7 |
8 | import UIKit
9 |
10 | final public class DefaultPagerItemView: UIView, PagerItemView {
11 | private var backView = UIView()
12 | private var titleLabel = UILabel()
13 | private var badgeView = UIView()
14 | private var stackView = UIStackView()
15 | private var imageView = UIImageView()
16 |
17 | public var activeColor: UIColor = UIColor.black
18 | public var deactiveColor: UIColor = UIColor.gray
19 | public var activeBackgroundColor: UIColor = UIColor.clear
20 |
21 | private var imageViewHeight: NSLayoutConstraint?
22 | private var imageViewWidth: NSLayoutConstraint?
23 |
24 | public override init(frame: CGRect) {
25 | super.init(frame: frame)
26 | setupView()
27 | }
28 |
29 | required init?(coder: NSCoder) {
30 | fatalError("init(coder:) has not been implemented")
31 | }
32 |
33 | private func setupView() {
34 | backView.translatesAutoresizingMaskIntoConstraints = false
35 | addSubview(backView)
36 | NSLayoutConstraint.activate([
37 | backView.topAnchor.constraint(equalTo: topAnchor),
38 | backView.bottomAnchor.constraint(equalTo: bottomAnchor),
39 | backView.trailingAnchor.constraint(equalTo: trailingAnchor),
40 | backView.leadingAnchor.constraint(equalTo: leadingAnchor)
41 | ])
42 |
43 | stackView.translatesAutoresizingMaskIntoConstraints = false
44 | stackView.axis = .horizontal
45 | stackView.alignment = .center
46 | stackView.distribution = .fill
47 | stackView.spacing = 4
48 | addSubview(stackView)
49 | let stackViewTrailing = stackView.trailingAnchor.constraint(equalTo: trailingAnchor)
50 | let stackViewLeading = stackView.leadingAnchor.constraint(equalTo: leadingAnchor)
51 |
52 | stackViewTrailing.priority = .defaultLow
53 | stackViewLeading.priority = .defaultLow
54 |
55 | NSLayoutConstraint.activate([
56 | stackView.topAnchor.constraint(equalTo: topAnchor),
57 | stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
58 | stackView.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor),
59 | stackView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor),
60 | stackView.centerXAnchor.constraint(equalTo: centerXAnchor),
61 | stackViewTrailing,
62 | stackViewLeading
63 | ])
64 |
65 | titleLabel.translatesAutoresizingMaskIntoConstraints = false
66 | titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
67 | imageView.translatesAutoresizingMaskIntoConstraints = false
68 | imageViewHeight = imageView.heightAnchor.constraint(equalToConstant: 24)
69 | imageViewWidth = imageView.widthAnchor.constraint(equalToConstant: 24)
70 |
71 | NSLayoutConstraint.activate([
72 | imageViewHeight!,
73 | imageViewWidth!
74 | ])
75 | stackView.addArrangedSubview(imageView)
76 | stackView.addArrangedSubview(titleLabel)
77 |
78 | badgeView.translatesAutoresizingMaskIntoConstraints = false
79 | addSubview(badgeView)
80 | NSLayoutConstraint.activate([
81 | badgeView.widthAnchor.constraint(equalToConstant: 10),
82 | badgeView.heightAnchor.constraint(equalToConstant: 10),
83 | badgeView.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 3),
84 | badgeView.bottomAnchor.constraint(equalTo: titleLabel.topAnchor, constant: 3)
85 | ])
86 | }
87 |
88 |
89 | private lazy var setupLayout: Void = {
90 | titleLabel.font = UIFont.boldSystemFont(ofSize: 13)
91 | titleLabel.textColor = UIColor.black
92 | badgeView.isHidden = true
93 | badgeView.layer.cornerRadius = badgeView.frame.height / 2
94 | badgeView.clipsToBounds = true
95 | badgeView.backgroundColor = UIColor.red
96 | }()
97 |
98 | public override func layoutSubviews() {
99 | super.layoutSubviews()
100 | _ = setupLayout
101 | }
102 |
103 | public var isSelected: Bool = false {
104 | didSet {
105 | if isSelected {
106 | titleLabel.textColor = activeColor
107 | imageView.tintColor = activeColor
108 | backView.backgroundColor = activeBackgroundColor
109 | } else {
110 | titleLabel.textColor = deactiveColor
111 | imageView.tintColor = deactiveColor
112 | backView.backgroundColor = .clear
113 | }
114 | }
115 | }
116 |
117 | public func configure(with res: PagerItem) {
118 | switch res {
119 | case .text(let textItem):
120 | self.titleLabel.isHidden = false
121 | self.imageView.isHidden = true
122 | self.titleLabel.text = textItem.title
123 | self.titleLabel.font = textItem.font
124 | case .image(let imageItem):
125 | self.titleLabel.isHidden = true
126 | self.imageView.isHidden = false
127 | self.imageView.image = imageItem.image?.withRenderingMode(.alwaysTemplate)
128 | self.imageViewHeight?.constant = imageItem.size.height
129 | self.imageViewWidth?.constant = imageItem.size.width
130 | self.imageView.layer.cornerRadius = imageItem.cornerRadius
131 | self.imageView.clipsToBounds = true
132 | case .textAndImage(let textItem, let imageItem):
133 | self.titleLabel.isHidden = false
134 | self.imageView.isHidden = false
135 | self.titleLabel.text = textItem.title
136 | self.titleLabel.font = textItem.font
137 | self.imageView.image = imageItem.image?.withRenderingMode(.alwaysTemplate)
138 | self.imageViewHeight?.constant = imageItem.size.height
139 | self.imageViewWidth?.constant = imageItem.size.width
140 | self.imageView.layer.cornerRadius = imageItem.cornerRadius
141 | self.imageView.clipsToBounds = true
142 | case .custom(_):
143 | break
144 | }
145 | }
146 |
147 | public func badge(isHidden: Bool) {
148 | self.badgeView.isHidden = isHidden
149 | }
150 | }
151 |
152 |
--------------------------------------------------------------------------------
/TopContentPager/ContentTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WishDetailInformationViewController.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/01/08.
6 | //
7 |
8 | import UIKit
9 |
10 | public protocol ContentTableViewDelegate: class {
11 | func didEndDragging(viewController: ContentTableViewController, willDecelerate decelerate: Bool)
12 | func didEndDecelerationg(viewController: ContentTableViewController)
13 | func didScroll(viewController: ContentTableViewController)
14 | }
15 |
16 | public final class ContentTableViewController: UIViewController {
17 |
18 | public var tableView = ContentInnerTableView()
19 |
20 | private var observation: NSKeyValueObservation?
21 | private var refreshControl = UIRefreshControl()
22 | weak var delegate: ContentTableViewDelegate?
23 | public private(set) var viewController: ContentTableBody!
24 | lazy var setupContentHeight: Void = {
25 | observation = nil
26 | observation = viewController.scrollView.observe(\.contentSize, options: [.new, .old, .prior]) { [weak self] ( _, contentSize) in
27 | if let newValue = contentSize.newValue {
28 | self?.bodyContentHeight = newValue.height
29 | }
30 | self?.tableView.reloadData()
31 | }
32 | }()
33 | public private(set) var topView: TopContentView!
34 | private var bodyContentHeight: CGFloat = 0
35 |
36 | public struct Input {
37 | let topView: TopContentView
38 | let viewController: ContentTableBody
39 | }
40 |
41 | public static func create(with input: Input) -> Self {
42 | let vc = Self.init()
43 | vc.viewController = input.viewController
44 | vc.topView = input.topView
45 | return vc
46 | }
47 |
48 | public override func viewDidLoad() {
49 | super.viewDidLoad()
50 | setupView()
51 | setup()
52 | }
53 |
54 | private func setupView() {
55 | tableView.translatesAutoresizingMaskIntoConstraints = false
56 | view.addSubview(tableView)
57 | NSLayoutConstraint.activate([
58 | tableView.topAnchor.constraint(equalTo: view.topAnchor),
59 | tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
60 | tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
61 | tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
62 | ])
63 | }
64 |
65 | private func setup() {
66 | tableView.registerClass(classType: ContentTopCell.self)
67 | tableView.registerClass(classType: ContentBodyCell.self)
68 | tableView.separatorColor = .clear
69 | tableView.dataSource = self
70 | tableView.delegate = self
71 | tableView.contentInsetAdjustmentBehavior = .never
72 | tableView.refreshControl = viewController.refresh(sender: refreshControl, contentViewController: self) ? refreshControl : nil
73 | refreshControl.addTarget(self, action: #selector(refresh(sender:)), for: .valueChanged)
74 |
75 | addChild(viewController)
76 | viewController.didMove(toParent: self)
77 | }
78 |
79 | @objc func refresh(sender: UIRefreshControl) {
80 | viewController.refresh(sender: sender, contentViewController: self)
81 | }
82 | }
83 |
84 | extension ContentTableViewController: UIScrollViewDelegate{
85 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
86 | delegate?.didEndDragging(viewController: self, willDecelerate: decelerate)
87 | }
88 |
89 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
90 | delegate?.didEndDecelerationg(viewController: self)
91 | }
92 |
93 | public func scrollViewDidScroll(_ scrollView: UIScrollView) {
94 | delegate?.didScroll(viewController: self)
95 | }
96 | }
97 |
98 | extension ContentTableViewController: UITableViewDataSource {
99 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
100 | 2
101 | }
102 |
103 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
104 | if indexPath.row == 0 {
105 | return tableView.dequeueReusableCell(classType: ContentTopCell.self, for: indexPath)
106 | } else {
107 | let cell = tableView.dequeueReusableCell(classType: ContentBodyCell.self, for: indexPath)
108 | if let bodyVC = viewController {
109 | cell.prepare(viewController: bodyVC)
110 | }
111 | return cell
112 | }
113 | }
114 |
115 |
116 | }
117 |
118 | extension ContentTableViewController: UITableViewDelegate {
119 | public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
120 | if cell is ContentBodyCell {
121 | _ = setupContentHeight
122 | }
123 | }
124 |
125 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
126 | if indexPath.row == 0 {
127 | return topView.estimateHeight
128 | } else {
129 | return bodyContentHeight
130 | }
131 | }
132 | public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
133 | if indexPath.row == 0 {
134 | return topView.estimateHeight
135 | } else {
136 | return bodyContentHeight
137 | }
138 | }
139 | }
140 |
141 | public class ContentInnerTableView: UITableView {
142 | public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
143 | func findScrollView(targetView: UIView?) -> UIView? {
144 | guard let targetView = targetView else { return nil }
145 | if let _ = targetView as? UIScrollView {
146 | return targetView
147 | } else {
148 | return findScrollView(targetView: targetView.superview)
149 | }
150 | }
151 | if let scrollView = findScrollView(targetView: superview) as? UIScrollView {
152 | if let index = indexPathForRow(at: point), let _ = cellForRow(at: index) as? ContentTopCell {
153 | scrollView.isScrollEnabled = false
154 | } else {
155 | scrollView.isScrollEnabled = true
156 | }
157 | }
158 | return super.hitTest(point, with: event)
159 | }
160 | }
161 |
162 |
163 |
--------------------------------------------------------------------------------
/Sample/Cell/TimelineTableCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | # Overview
19 |
20 |
21 | ## What is `TopContentPager` ?
22 | `TopContentPager` is framework you can make page like Instagram's MyPage simply.
23 |
24 | Specifically, This is UIPageViewController with common scrollable headerView and PageSection fixed at the top in all pages.
25 |
26 | A big feature of TopContentPager is that there is a common header that can be scrolled to the top.
27 |
28 | It is very difficult to implement such an implementation using ordinary UIPageViewController and UITableView.
29 | Because the top header also needs to be scrolled along with the UITableView.
30 |
31 | Also, because the header at the top is common, if you scroll to the top on any page, you need to scroll to the top on all other pages.
32 | There are many other complicated parts regarding scrolling, but I will omit them here.
33 | See the `Logic` section for more details.
34 |
35 | `TopContentPager` makes it easy to create such pages without having to worry about these difficult issues.
36 |
37 |
38 |
39 | # Usage
40 | 1. ***Make Base Class***
41 |
42 | First, you can make base class extended `TopContentPagerViewController` and add `TopContentPagerDataSource` to that.
43 |
44 | Then, you must add `setupWillLoadDataSource()` function and bind dataSource in the function.
45 | ```swift
46 | class CustomTopContentPagerViewController: TopContentPagerViewController {
47 |
48 | override func setupWillLoadDataSource() {
49 | super.setupWillLoadDataSource()
50 | dataSource = self
51 | }
52 |
53 | override func viewDidLoad() {
54 | super.viewDidLoad()
55 | }
56 | }
57 |
58 | extension CustomTopContentPagerViewController: TopContentPagerDataSource {
59 | func topContentPagerViewControllerTopContentView(_ viewController: TopContentPagerViewController) -> TopContentView {
60 | // return common HeaderView in all pages.
61 | TopView()
62 | }
63 |
64 | func topContentPagerViewControllerViewControllers(_ viewController: TopContentPagerViewController) -> [ContentTableBody] {
65 | // return ViewControllers for each page.
66 | [Page1ViewController(), Page2ViewController(), Page3ViewController()]
67 | }
68 | }
69 | ```
70 | 2. ***Make Content Page***
71 |
72 | Second, please add `TopContentTableBody` to every ViewController to use them as page.
73 |
74 | You can set pagerItem. (`PagerItem` has types `.text`, `.image`, `.textAndImage`, `.custom`)
75 |
76 | So, need to set tableView(or collectionView) to scrollView.
77 | ```swift
78 | class Page1ViewController: UIViewController, ContentTableBody {
79 |
80 | var pagerItem: PagerItem = .text(.init(title: "ページ1"))
81 | var scrollView: UIScrollView!
82 | @IBOutlet weak var tableView: UITableView! {
83 | didSet {
84 | scrollView = tableView
85 | }
86 | }
87 | }
88 | ```
89 | 3. ***Make TopView***
90 |
91 | Finally, make TopView extended `TopContentView`.
92 |
93 | ```swift
94 | class TopView: TopContentView {
95 | // write your custom code
96 | }
97 | ```
98 |
99 | That's all. you can use `TopContentViewController`.
100 | If you want to customize, you read properties section and sample code.
101 |
102 | # Logic
103 | ## View Hierarchy
104 | ```
105 | TopContentViewController.View
106 | ├ ScrollView
107 | | ├ ScrollContentView
108 | | └ ContentTableViewController.View
109 | | └ ContentInnerTableView
110 | | ├ ContentTopCell
111 | | | └ (TopContentView) *When you scroll vertically.
112 | | └ ContentBodyCell
113 | | └ YourPageViewController.View extended ContentTableBody
114 | └ EscapeView
115 | └ (TopContentView) *When you scroll horizontally.
116 | ```
117 |
118 |
119 |
120 |
121 | ## Fix Scrollable Header View Logic
122 | See the gif image below for the logic of scrolling.
123 |
124 | Sorry, `UIView.TopContentProtocol` in the image is old.
125 | Now, you can use `TopContentView`.
126 |
127 |
128 |
129 |
130 |
131 | # Sample
132 | you can get Sample Code.
133 | It's in the `Sample` folder in this repository.
134 |
135 | # Properties and functions
136 | ## TopContentPagerViewController
137 | | property | access | description |
138 | |:-:|:-:|:-:|
139 | | selectedIndex | get, set | current page index |
140 | | dataSource | get, set | dataSource for topview and pageViewControllers |
141 | | delegate | get, set | see `TopContentPagerDelegate`. it is able to make TopMargin on TopView. |
142 | | viewControllers | get | innner ViewControllers with TableView |
143 | | selectedViewController | get | current page ViewController |
144 | | tabHeight | get | PagerItemsView's Height |
145 | | headerHeight | get | TopView's Height |
146 | | topMargin | get | TopMarginHeight by delegate |
147 |
148 | ## TopContentView
149 | | property | access | description |
150 | |:-:|:-:|:-:|
151 | | isHideTabView | get, override | flag to hide pagerItemsView |
152 | | tabView | get, set | PagerItemsView |
153 | | dataSource | get, set | see `TopContentViewDataSource`. you can set TopViewHeight if you don't want to use autolayout. |
154 | | tabViewHeight | get | PagerItemsView's Height |
155 | | estimateHeight | get | TopView's Height |
156 |
157 | | function | description |
158 | |:-:|:-:|
159 | | updateTab(options: UpdatePagerOptions) | customize PagerItemsView. see `UpdatePagerOptions` properties in code. |
160 | | updateLayout() | if you update TopView autolayout, you have to call this method. |
161 |
162 | ## PagerItem
163 | | case | description |
164 | |:-:|:-:|
165 | | text | you can set page title text. (text and font) |
166 | | image | you can set page title image. (image, size, and cornerRaius) |
167 | | textAndImage | you can set page title text on the right side of the image |
168 | | custom | you can set custom view for page title. you have to make custom view with `PageItemView` protocol. |
169 |
170 |
171 |
172 | # Installation
173 | ## CocoaPods
174 | TopContentPager is available through [CocoaPods](https://cocoapods.org). To install
175 | it, simply add the following line to your Podfile:
176 |
177 | ```ruby
178 | pod "TopContentPager"
179 | ```
180 |
181 | # Requirements
182 |
183 | - Swift 5 or greater
184 | - iOS 11.0 or greater
185 |
--------------------------------------------------------------------------------
/TopContentPager/View/PagerItemsView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PagerItemsView.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/01/08.
6 | //
7 |
8 | import UIKit
9 |
10 | public enum PagerItem {
11 | case text(TextItem)
12 | case image(ImageItem)
13 | case textAndImage(text: TextItem, image: ImageItem)
14 | case custom(PagerItemView)
15 |
16 | public struct TextItem {
17 | let title: String
18 | let font: UIFont
19 |
20 | public init(title: String, font: UIFont = UIFont.boldSystemFont(ofSize: 13)) {
21 | self.title = title
22 | self.font = font
23 | }
24 | }
25 |
26 | public struct ImageItem {
27 | let image: UIImage?
28 | let size: CGSize
29 | let cornerRadius: CGFloat
30 |
31 | public init(image: UIImage?, size: CGSize = CGSize(width: 24, height: 24), cornerRadius: CGFloat = 0) {
32 | self.image = image
33 | self.size = size
34 | self.cornerRadius = cornerRadius
35 | }
36 | }
37 |
38 |
39 | }
40 |
41 |
42 |
43 | final public class PagerItemsView: UIView {
44 |
45 | private var indicatorHeight: CGFloat = 2.0
46 | private var indicatorMinWidth: CGFloat = 0
47 | private var itemViewHeight: CGFloat = 20.0
48 | private var lineHeight: CGFloat = 2.0
49 | private var indicatorSideSpace: CGFloat = 0
50 |
51 | public var items: [PagerItem] = []
52 | public var itemViews: [PagerItemView] = []
53 | public private(set) var options: PagerOptions = .init()
54 |
55 | private var indicator: UIView!
56 | private var frontView: UIView!
57 | private var lineView: UIView!
58 | private var maskLayer: CALayer!
59 |
60 | private var indicatorWidth: CGFloat {
61 | self.frame.size.width / max(CGFloat(self.items.count), 1)
62 | }
63 |
64 | override init(frame: CGRect) {
65 | super.init(frame: frame)
66 | self.prepare()
67 | }
68 |
69 | required public init?(coder aDecoder: NSCoder) {
70 | fatalError("init(coder:) has not been implemented")
71 | }
72 |
73 | public func update(pagerOptions: UpdatePagerOptions) {
74 | options.itemHeight = pagerOptions.itemHeight ?? options.itemHeight
75 | options.indicatorHeight = pagerOptions.indicatorHeight ?? options.indicatorHeight
76 | options.indicatorColor = pagerOptions.indicatorColor ?? options.indicatorColor
77 | options.activeBackgroundColor = pagerOptions.activeBackgroundColor ?? options.activeBackgroundColor
78 | options.backgroundColor = pagerOptions.backgroundColor ?? options.backgroundColor
79 | options.lineColor = pagerOptions.lineColor ?? options.lineColor
80 | options.deactiveLabelColor = pagerOptions.deactiveLabelColor ?? options.deactiveLabelColor
81 | options.activeLabelColor = pagerOptions.activeLabelColor ?? options.activeLabelColor
82 | options.indicatorSideSpace = pagerOptions.indicatorSideSpace ?? options.indicatorSideSpace
83 | updateView()
84 | }
85 |
86 | func updateView() {
87 | self.frame.size.height = options.itemHeight
88 | self.itemViewHeight = options.itemHeight
89 | self.indicatorHeight = options.indicatorHeight
90 | self.lineHeight = options.indicatorHeight
91 | self.backgroundColor = options.backgroundColor
92 | self.indicatorSideSpace = options.indicatorSideSpace
93 | self.lineView.backgroundColor = options.lineColor
94 | self.indicator.backgroundColor = options.indicatorColor
95 | itemViews.forEach { itemView in
96 | itemView.activeColor = options.activeLabelColor
97 | itemView.deactiveColor = options.deactiveLabelColor
98 | itemView.activeBackgroundColor = options.activeBackgroundColor
99 | }
100 | }
101 |
102 | func addItem(item: PagerItem) {
103 | self.items.append(item)
104 | switch item {
105 | case .text, .image, .textAndImage:
106 | let itemView = DefaultPagerItemView(frame: CGRect(x: 0, y: 0, width: self.indicatorMinWidth, height: self.bounds.height))
107 | itemView.configure(with: item)
108 | self.itemViews.append(itemView)
109 | self.addSubview(itemView)
110 | case .custom(let itemView):
111 | itemView.frame = CGRect(x: 0, y: 0, width: self.indicatorMinWidth, height: self.bounds.height)
112 | self.itemViews.append(itemView)
113 | self.addSubview(itemView)
114 | }
115 |
116 | self.setNeedsLayout()
117 | updateView()
118 | }
119 |
120 | func adjustIndicator() {
121 | self.indicator.frame.size.width = self.indicatorWidth - (self.indicatorSideSpace * 2)
122 | }
123 |
124 | func adjustSelected(page: Int) {
125 | self.itemViews.forEach {
126 | $0.isSelected = false
127 | }
128 | self.itemViews[safe: page]?.isSelected = true
129 | UIView.animate(withDuration: 0.1, delay: 0, options: .beginFromCurrentState, animations: {
130 | self.indicator.frame.origin.x = (CGFloat(page) * self.indicatorWidth) + self.indicatorSideSpace
131 | }, completion: nil)
132 | }
133 |
134 | public func updatebadge(index: Int, isHidden: Bool) {
135 | self.itemViews[safe: index]?.badge(isHidden: isHidden)
136 | }
137 |
138 | override public func layoutSubviews() {
139 | super.layoutSubviews()
140 |
141 | for (i, view) in self.itemViews.enumerated() {
142 | let itemMaxWidth: CGFloat = self.frame.size.width / max(CGFloat(self.items.count), 1)
143 | view.frame = CGRect(x: itemMaxWidth * CGFloat(i), y: 0, width: self.indicatorWidth, height: itemViewHeight - lineHeight)
144 | }
145 |
146 | self.frontView.frame = self.bounds
147 |
148 | self.indicator.frame = CGRect(
149 | x: 0, y: self.frame.size.height - self.indicatorHeight,
150 | width: self.indicatorWidth, height: self.indicatorHeight
151 | )
152 | self.lineView.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.width, height: lineHeight)
153 | self.maskLayer.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.width, height: lineHeight)
154 | self.adjustIndicator()
155 | }
156 | }
157 |
158 | private extension PagerItemsView {
159 |
160 | func prepare() {
161 | self.frontView = UIView(frame: self.bounds)
162 | self.addSubview(self.frontView)
163 |
164 | self.lineView = UIView(frame: CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.width, height: lineHeight))
165 | self.addSubview(self.lineView)
166 |
167 | self.indicator = UIView(frame:
168 | CGRect(
169 | x: 0, y: self.frame.size.height - self.indicatorHeight,
170 | width: self.indicatorWidth, height: self.indicatorHeight
171 | )
172 | )
173 | self.addSubview(self.indicator)
174 |
175 | self.maskLayer = UIView(frame: CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.width, height: lineHeight)).layer
176 | self.frontView.layer.mask = self.maskLayer
177 | }
178 | }
179 |
180 | extension Array {
181 | public subscript(safe index: Int) -> Element? {
182 | guard index >= 0, index < endIndex else { return nil }
183 | return self[index]
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/TopContentPager/TopContentPagerViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TopContentPagerViewController.swift
3 | // TopContentPager
4 | //
5 | // Created by 田中厳貴 on 2021/01/08.
6 | //
7 |
8 | import UIKit
9 |
10 | public protocol TopContentPagerDataSource: AnyObject {
11 | func topContentPagerViewControllerTopContentView(_ viewController: TopContentPagerViewController) -> TopContentView
12 | func topContentPagerViewControllerViewControllers(_ viewController: TopContentPagerViewController) -> [ContentTableBody]
13 | }
14 |
15 | @objc public protocol TopContentPagerDelegate: AnyObject {
16 | @objc optional func topContentPagerViewControllerTabTopMargin(_ viewController: TopContentPagerViewController) -> CGFloat
17 | }
18 |
19 | class EscapeView: UIView { }
20 |
21 | open class TopContentPagerViewController: UIViewController, UIGestureRecognizerDelegate {
22 |
23 | public weak var dataSource: TopContentPagerDataSource?
24 | public weak var delegate: TopContentPagerDelegate?
25 | public var selectedViewController: ContentTableViewController {
26 | viewControllers[selectedIndex]
27 | }
28 | public var selectedIndex: Int = 0 {
29 | didSet {
30 | contentOffsetX = scrollView.contentOffset.x
31 | addContentViewToEscapeView()
32 | topView.tabView?.adjustSelected(page: selectedIndex)
33 | UIView.animate(withDuration: 0.25, animations: {
34 | self.scrollView.setContentOffset(CGPoint(x: self.scrollView.bounds.size.width * CGFloat(self.selectedIndex), y: 0), animated: false)
35 | }) { _ in
36 | self.contentOffsetX = self.scrollView.contentOffset.x
37 | if let constant = self.escapeViewTopConstraint?.constant, -(self.topView.frame.height - self.tabHeight) < constant {
38 | self.addContentViewToCell()
39 | }
40 | }
41 | }
42 | }
43 |
44 | public private(set) var viewControllers: [ContentTableViewController] = []
45 | public private(set) var tabHeight: CGFloat!
46 | public private(set) var headerHeight: CGFloat!
47 | public private(set) var safeAreaBar = UIView()
48 | public var topMargin: CGFloat {
49 | delegate?.topContentPagerViewControllerTabTopMargin?(self) ?? 0
50 | }
51 |
52 | private var topView: TopContentView!
53 | private let scrollView = UIScrollView()
54 | private let scrollContainerView = UIView()
55 | private let escapeView = EscapeView()
56 | private var escapeViewTopConstraint: NSLayoutConstraint?
57 | private var escapeViewHeightConstraint: NSLayoutConstraint?
58 | private var containerViews: [UIView] = []
59 | private var tabBarTitles: [PagerItem] = []
60 | private var contentOffsetX: CGFloat = 0
61 | private lazy var setupLayout: Void = {
62 | tabBarTitles.forEach { topView.tabView?.addItem(item: $0) }
63 | selectedIndex = 0
64 | topView.tabView?.adjustSelected(page: selectedIndex)
65 | topView.tabView?.update(pagerOptions: .init())
66 | topView.isUserInteractionEnabled = true
67 | let tabBarTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapTab(_:)))
68 | tabBarTapRecognizer.delegate = self
69 | topView.tabView?.addGestureRecognizer(tabBarTapRecognizer)
70 | }()
71 |
72 | open override func viewDidLoad() {
73 | super.viewDidLoad()
74 | view.backgroundColor = .white
75 | setupWillLoadDataSource()
76 | guard let dataSource = dataSource, !dataSource.topContentPagerViewControllerViewControllers(self).isEmpty else {
77 | return
78 | }
79 | loadDataSource(dataSource: dataSource)
80 | setup()
81 | viewControllers.forEach { vc in
82 | vc.delegate = self
83 | }
84 | }
85 |
86 | open override func viewDidLayoutSubviews() {
87 | super.viewWillLayoutSubviews()
88 | guard let dataSource = dataSource, !dataSource.topContentPagerViewControllerViewControllers(self).isEmpty else {
89 | return
90 | }
91 | _ = setupLayout
92 | }
93 |
94 | open func setupWillLoadDataSource() { }
95 |
96 | public func updateHeader() {
97 | escapeViewHeightConstraint?.constant = topView.estimateHeight
98 | escapeView.layoutIfNeeded()
99 | addContentViewToEscapeView()
100 | viewControllers.forEach { $0.tableView.reloadData() }
101 | tabHeight = topView.tabViewHeight + topMargin
102 | headerHeight = topView.estimateHeight
103 | topView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: headerHeight)
104 | addContentViewToCell()
105 | escapeViewHeightConstraint?.constant = topView.estimateHeight
106 | escapeView.layoutIfNeeded()
107 | }
108 |
109 | private func loadDataSource(dataSource: TopContentPagerDataSource) {
110 | topView = dataSource.topContentPagerViewControllerTopContentView(self)
111 | topView.delegate = self
112 | topView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: topView.estimateHeight)
113 | tabHeight = topView.tabViewHeight + topMargin
114 | headerHeight = topView.estimateHeight
115 | let bodyViewControllers = dataSource.topContentPagerViewControllerViewControllers(self)
116 | tabBarTitles = bodyViewControllers.map { $0.pagerItem }
117 | bodyViewControllers.forEach { item in
118 | let contentVC = ContentTableViewController.create(with: .init(topView: topView, viewController: item))
119 | viewControllers.append(contentVC)
120 | }
121 | }
122 |
123 | private func setup() {
124 | scrollView.delegate = self
125 | scrollView.isPagingEnabled = true
126 | scrollView.scrollsToTop = false
127 | scrollView.isDirectionalLockEnabled = true
128 | scrollView.showsHorizontalScrollIndicator = false
129 | scrollView.showsVerticalScrollIndicator = false
130 | scrollView.translatesAutoresizingMaskIntoConstraints = false
131 | scrollView.alwaysBounceVertical = false
132 | scrollView.isScrollEnabled = false
133 | view.addSubview(scrollView)
134 | NSLayoutConstraint.activate([
135 | scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
136 | scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
137 | scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
138 | scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor)
139 | ])
140 |
141 | scrollContainerView.translatesAutoresizingMaskIntoConstraints = false
142 | scrollView.addSubview(scrollContainerView)
143 | NSLayoutConstraint.activate([
144 | scrollContainerView.topAnchor.constraint(equalTo: scrollView.topAnchor),
145 | scrollContainerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
146 | scrollContainerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
147 | scrollContainerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
148 | scrollContainerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
149 | scrollContainerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: CGFloat(viewControllers.count))
150 | ])
151 |
152 | viewControllers.enumerated().forEach { index, vc in
153 | vc.view.translatesAutoresizingMaskIntoConstraints = false
154 | scrollContainerView.addSubview(vc.view)
155 | var constraints: [NSLayoutConstraint] = []
156 | switch index {
157 | case 0:
158 | constraints.append(vc.view.leadingAnchor.constraint(equalTo: scrollContainerView.leadingAnchor))
159 | case viewControllers.count - 1:
160 | guard let previousVC = viewControllers[safe: index - 1] else { return }
161 | constraints.append(contentsOf: [
162 | vc.view.trailingAnchor.constraint(equalTo: scrollContainerView.trailingAnchor),
163 | vc.view.leadingAnchor.constraint(equalTo: previousVC.view.trailingAnchor)
164 | ])
165 | default:
166 | guard let previousVC = viewControllers[safe: index - 1] else { return }
167 | constraints.append(vc.view.leadingAnchor.constraint(equalTo: previousVC.view.trailingAnchor))
168 | }
169 | constraints.append(contentsOf: [
170 | vc.view.topAnchor.constraint(equalTo: scrollContainerView.topAnchor),
171 | vc.view.bottomAnchor.constraint(equalTo: scrollContainerView.bottomAnchor),
172 | vc.view.widthAnchor.constraint(equalToConstant: view.frame.width)
173 | ])
174 | addChild(vc)
175 | vc.didMove(toParent: self)
176 | NSLayoutConstraint.activate(constraints)
177 | }
178 |
179 | escapeView.translatesAutoresizingMaskIntoConstraints = false
180 | escapeView.isUserInteractionEnabled = false
181 | escapeView.backgroundColor = .clear
182 | view.addSubview(escapeView)
183 | escapeViewTopConstraint = escapeView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
184 | escapeViewHeightConstraint = escapeView.heightAnchor.constraint(equalToConstant: headerHeight)
185 | NSLayoutConstraint.activate([
186 | escapeViewTopConstraint!,
187 | escapeView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
188 | escapeView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
189 | escapeViewHeightConstraint!
190 | ])
191 |
192 | safeAreaBar.translatesAutoresizingMaskIntoConstraints = false
193 | safeAreaBar.isUserInteractionEnabled = false
194 | safeAreaBar.backgroundColor = .white
195 | safeAreaBar.clipsToBounds = true
196 | view.addSubview(safeAreaBar)
197 |
198 | NSLayoutConstraint.activate([
199 | safeAreaBar.topAnchor.constraint(equalTo: view.topAnchor),
200 | safeAreaBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
201 | safeAreaBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
202 | safeAreaBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
203 | ])
204 | }
205 |
206 | @objc private func tapTab(_ sender: UITapGestureRecognizer) {
207 | guard let tabView = topView.tabView else { return }
208 | let position = sender.location(in: self.topView.tabView)
209 | if position.y < tabView.frame.size.height - tabView.options.itemHeight {
210 | return
211 | }
212 |
213 | let index = Int(floor(position.x / (tabView.frame.size.width / max(CGFloat(tabView.items.count), 1))))
214 | self.selectedIndex = index
215 | }
216 |
217 | private func addContentViewToCell() {
218 | if topView.superview != escapeView { return }
219 | escapeView.isUserInteractionEnabled = false
220 |
221 | let cells = selectedViewController.tableView.visibleCells.filter { $0.isKind(of: ContentTopCell.self) }
222 | if let cell = cells.first as? ContentTopCell {
223 | cell.addSubview(topView)
224 | }
225 | }
226 |
227 | private func addContentViewToEscapeView() {
228 | if topView.superview == escapeView { return }
229 | escapeView.isUserInteractionEnabled = true
230 | escapeView.addSubview(topView)
231 |
232 | let topConstant = max(0, min(topView.frame.height - tabHeight, selectedViewController.tableView.contentOffset.y))
233 | escapeViewTopConstraint?.constant = -topConstant
234 | escapeView.layoutIfNeeded()
235 | }
236 |
237 | private func tableViewsScroll() {
238 | let viewControllers = self.viewControllers.filter({ !($0 == selectedViewController) })
239 | let contentHeight = topView.frame.height - tabHeight
240 | viewControllers.forEach { vc in
241 | var contentOffset: CGPoint
242 | if selectedViewController.tableView.contentOffset.y >= contentHeight {
243 | contentOffset = vc.tableView.contentOffset.y >= contentHeight ? vc.tableView.contentOffset : CGPoint(x: 0, y: contentHeight)
244 | } else {
245 | contentOffset = selectedViewController.tableView.contentOffset
246 | }
247 | vc.tableView.setContentOffset(contentOffset, animated: false)
248 | }
249 | }
250 | }
251 |
252 | extension TopContentPagerViewController: UIScrollViewDelegate {
253 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
254 | contentOffsetX = scrollView.contentOffset.x
255 | if let constant = escapeViewTopConstraint?.constant, !decelerate && -(topView.frame.height - tabHeight) < constant {
256 | addContentViewToCell()
257 | }
258 | }
259 |
260 | public func scrollViewDidScroll(_ scrollView: UIScrollView) {
261 | if scrollView.contentOffset.x != contentOffsetX {
262 | scrollView.contentOffset.y = 0
263 | }
264 | }
265 |
266 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
267 | contentOffsetX = scrollView.contentOffset.x
268 | addContentViewToEscapeView()
269 | }
270 |
271 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
272 | let index = Int(scrollView.contentOffset.x / scrollView.bounds.size.width)
273 | selectedIndex = index
274 | }
275 | }
276 |
277 | extension TopContentPagerViewController: ContentTableViewDelegate {
278 |
279 | public func didEndDragging(viewController: ContentTableViewController, willDecelerate decelerate: Bool) {
280 | guard !decelerate, viewController == self.selectedViewController else { return }
281 | self.tableViewsScroll()
282 | }
283 |
284 | public func didEndDecelerationg(viewController: ContentTableViewController) {
285 | guard viewController == self.selectedViewController else { return }
286 | self.tableViewsScroll()
287 | }
288 |
289 | public func didScroll(viewController: ContentTableViewController) {
290 | guard viewController == self.selectedViewController else { return }
291 | if selectedViewController.tableView.contentOffset.y > self.topView.frame.height - self.tabHeight {
292 | self.addContentViewToEscapeView()
293 | } else {
294 | self.addContentViewToCell()
295 | }
296 | }
297 | }
298 |
299 | extension TopContentPagerViewController: TopContentViewDelegate {
300 | func needsReload() {
301 | updateHeader()
302 | }
303 | }
304 |
--------------------------------------------------------------------------------
/Sample/View/TopView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/TopContentPager.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8435A4BF25BFFA1C00EEDA77 /* TopContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8435A4BE25BFFA1C00EEDA77 /* TopContentView.swift */; };
11 | 8435A54225C061E400EEDA77 /* MyPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8435A54125C061E400EEDA77 /* MyPostViewController.swift */; };
12 | 8435A54925C061F600EEDA77 /* MyPostViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8435A54825C061F600EEDA77 /* MyPostViewController.storyboard */; };
13 | 8435A55025C0664E00EEDA77 /* MyPostCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8435A54F25C0664E00EEDA77 /* MyPostCollectionCell.swift */; };
14 | 8435A55725C0665A00EEDA77 /* MyPostCollectionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8435A55625C0665A00EEDA77 /* MyPostCollectionCell.xib */; };
15 | 843FD85625AE8EBF00AD615F /* NSObject+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD85525AE8EBF00AD615F /* NSObject+Name.swift */; };
16 | 843FD85D25AE8EEF00AD615F /* UITableView+Register.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD85C25AE8EEF00AD615F /* UITableView+Register.swift */; };
17 | 843FD88525AEA08200AD615F /* TimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD88425AEA08200AD615F /* TimelineViewController.swift */; };
18 | 843FD88C25AEA08E00AD615F /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD88B25AEA08E00AD615F /* NotificationViewController.swift */; };
19 | 843FD89325AEA09A00AD615F /* TimelineViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 843FD89225AEA09A00AD615F /* TimelineViewController.storyboard */; };
20 | 843FD8A625AEA0B600AD615F /* NotificationViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 843FD8A525AEA0B600AD615F /* NotificationViewController.storyboard */; };
21 | 843FD8AD25AEA21E00AD615F /* TopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD8AC25AEA21E00AD615F /* TopView.swift */; };
22 | 843FD8C225AEAC4C00AD615F /* Storyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD8C125AEAC4C00AD615F /* Storyboard.swift */; };
23 | 843FD8CE25AEC11A00AD615F /* NSObject+NibLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FD8CD25AEC11A00AD615F /* NSObject+NibLoading.swift */; };
24 | 843FDA0625B0969100AD615F /* CustomTopContentPagerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FDA0525B0969100AD615F /* CustomTopContentPagerViewController.swift */; };
25 | 84BB333525A85EEF0056A35F /* TopContentPager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84BB332B25A85EEF0056A35F /* TopContentPager.framework */; };
26 | 84BB333A25A85EEF0056A35F /* TopContentPagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB333925A85EEF0056A35F /* TopContentPagerTests.swift */; };
27 | 84BB333C25A85EEF0056A35F /* TopContentPager.h in Headers */ = {isa = PBXBuildFile; fileRef = 84BB332E25A85EEF0056A35F /* TopContentPager.h */; settings = {ATTRIBUTES = (Public, ); }; };
28 | 84BB338E25A85FBC0056A35F /* ContentBodyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB337D25A85FBC0056A35F /* ContentBodyCell.swift */; };
29 | 84BB339025A85FBC0056A35F /* ContentTopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB337F25A85FBC0056A35F /* ContentTopCell.swift */; };
30 | 84BB339525A85FBC0056A35F /* ContentTableBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB338525A85FBC0056A35F /* ContentTableBody.swift */; };
31 | 84BB339725A85FBC0056A35F /* ContentTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB338725A85FBC0056A35F /* ContentTableViewController.swift */; };
32 | 84BB339925A85FBC0056A35F /* TopContentPagerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB338925A85FBC0056A35F /* TopContentPagerViewController.swift */; };
33 | 84BB33A525A8655A0056A35F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33A425A8655A0056A35F /* AppDelegate.swift */; };
34 | 84BB33A725A8655A0056A35F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33A625A8655A0056A35F /* SceneDelegate.swift */; };
35 | 84BB33A925A8655A0056A35F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33A825A8655A0056A35F /* ViewController.swift */; };
36 | 84BB33AC25A8655A0056A35F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84BB33AA25A8655A0056A35F /* Main.storyboard */; };
37 | 84BB33AE25A8655B0056A35F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84BB33AD25A8655B0056A35F /* Assets.xcassets */; };
38 | 84BB33B125A8655B0056A35F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84BB33AF25A8655B0056A35F /* LaunchScreen.storyboard */; };
39 | 84BB33BC25A8655B0056A35F /* SampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33BB25A8655B0056A35F /* SampleTests.swift */; };
40 | 84BB33C725A8655B0056A35F /* SampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33C625A8655B0056A35F /* SampleUITests.swift */; };
41 | 84BB33D925A86B450056A35F /* PagerItemsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33D825A86B450056A35F /* PagerItemsView.swift */; };
42 | 84BB33E525A86B870056A35F /* PagerOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33E425A86B870056A35F /* PagerOptions.swift */; };
43 | 84BB33F125A872ED0056A35F /* PagerItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84BB33F025A872ED0056A35F /* PagerItemView.swift */; };
44 | 84C8D31A25C15B0B005CDC11 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C8D31925C15B0B005CDC11 /* MockData.swift */; };
45 | 84D77DD725C0762C0035CA1D /* TopView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84D77DD625C0762C0035CA1D /* TopView.xib */; };
46 | 84D77DED25C088210035CA1D /* TimelineTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D77DEC25C088210035CA1D /* TimelineTableCell.swift */; };
47 | 84D77DF425C0882D0035CA1D /* TimelineTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84D77DF325C0882D0035CA1D /* TimelineTableCell.xib */; };
48 | 84D77DFB25C149840035CA1D /* NotificationTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D77DFA25C149840035CA1D /* NotificationTableCell.swift */; };
49 | 84D77E0225C149910035CA1D /* NotificationTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84D77E0125C149910035CA1D /* NotificationTableCell.xib */; };
50 | 84DC4E9925D3A5C500BA8ACB /* DefaultPagerItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DC4E9825D3A5C500BA8ACB /* DefaultPagerItemView.swift */; };
51 | /* End PBXBuildFile section */
52 |
53 | /* Begin PBXContainerItemProxy section */
54 | 84BB333625A85EEF0056A35F /* PBXContainerItemProxy */ = {
55 | isa = PBXContainerItemProxy;
56 | containerPortal = 84BB332225A85EEF0056A35F /* Project object */;
57 | proxyType = 1;
58 | remoteGlobalIDString = 84BB332A25A85EEF0056A35F;
59 | remoteInfo = TopContentPager;
60 | };
61 | 84BB33B825A8655B0056A35F /* PBXContainerItemProxy */ = {
62 | isa = PBXContainerItemProxy;
63 | containerPortal = 84BB332225A85EEF0056A35F /* Project object */;
64 | proxyType = 1;
65 | remoteGlobalIDString = 84BB33A125A8655A0056A35F;
66 | remoteInfo = Sample;
67 | };
68 | 84BB33C325A8655B0056A35F /* PBXContainerItemProxy */ = {
69 | isa = PBXContainerItemProxy;
70 | containerPortal = 84BB332225A85EEF0056A35F /* Project object */;
71 | proxyType = 1;
72 | remoteGlobalIDString = 84BB33A125A8655A0056A35F;
73 | remoteInfo = Sample;
74 | };
75 | /* End PBXContainerItemProxy section */
76 |
77 | /* Begin PBXFileReference section */
78 | 8435A4BE25BFFA1C00EEDA77 /* TopContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopContentView.swift; sourceTree = ""; };
79 | 8435A54125C061E400EEDA77 /* MyPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPostViewController.swift; sourceTree = ""; };
80 | 8435A54825C061F600EEDA77 /* MyPostViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MyPostViewController.storyboard; sourceTree = ""; };
81 | 8435A54F25C0664E00EEDA77 /* MyPostCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPostCollectionCell.swift; sourceTree = ""; };
82 | 8435A55625C0665A00EEDA77 /* MyPostCollectionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyPostCollectionCell.xib; sourceTree = ""; };
83 | 843FD85525AE8EBF00AD615F /* NSObject+Name.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+Name.swift"; sourceTree = ""; };
84 | 843FD85C25AE8EEF00AD615F /* UITableView+Register.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+Register.swift"; sourceTree = ""; };
85 | 843FD88425AEA08200AD615F /* TimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewController.swift; sourceTree = ""; };
86 | 843FD88B25AEA08E00AD615F /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; };
87 | 843FD89225AEA09A00AD615F /* TimelineViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = TimelineViewController.storyboard; sourceTree = ""; };
88 | 843FD8A525AEA0B600AD615F /* NotificationViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NotificationViewController.storyboard; sourceTree = ""; };
89 | 843FD8AC25AEA21E00AD615F /* TopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopView.swift; sourceTree = ""; };
90 | 843FD8C125AEAC4C00AD615F /* Storyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboard.swift; sourceTree = ""; };
91 | 843FD8CD25AEC11A00AD615F /* NSObject+NibLoading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+NibLoading.swift"; sourceTree = ""; };
92 | 843FDA0525B0969100AD615F /* CustomTopContentPagerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTopContentPagerViewController.swift; sourceTree = ""; };
93 | 84BB332B25A85EEF0056A35F /* TopContentPager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TopContentPager.framework; sourceTree = BUILT_PRODUCTS_DIR; };
94 | 84BB332E25A85EEF0056A35F /* TopContentPager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TopContentPager.h; sourceTree = ""; };
95 | 84BB332F25A85EEF0056A35F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
96 | 84BB333425A85EEF0056A35F /* TopContentPagerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TopContentPagerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
97 | 84BB333925A85EEF0056A35F /* TopContentPagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopContentPagerTests.swift; sourceTree = ""; };
98 | 84BB333B25A85EEF0056A35F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
99 | 84BB337D25A85FBC0056A35F /* ContentBodyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentBodyCell.swift; sourceTree = ""; };
100 | 84BB337F25A85FBC0056A35F /* ContentTopCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTopCell.swift; sourceTree = ""; };
101 | 84BB338525A85FBC0056A35F /* ContentTableBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTableBody.swift; sourceTree = ""; };
102 | 84BB338725A85FBC0056A35F /* ContentTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTableViewController.swift; sourceTree = ""; };
103 | 84BB338925A85FBC0056A35F /* TopContentPagerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopContentPagerViewController.swift; sourceTree = ""; };
104 | 84BB33A225A8655A0056A35F /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
105 | 84BB33A425A8655A0056A35F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
106 | 84BB33A625A8655A0056A35F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
107 | 84BB33A825A8655A0056A35F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
108 | 84BB33AB25A8655A0056A35F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
109 | 84BB33AD25A8655B0056A35F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
110 | 84BB33B025A8655B0056A35F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
111 | 84BB33B225A8655B0056A35F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
112 | 84BB33B725A8655B0056A35F /* SampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
113 | 84BB33BB25A8655B0056A35F /* SampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleTests.swift; sourceTree = ""; };
114 | 84BB33BD25A8655B0056A35F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
115 | 84BB33C225A8655B0056A35F /* SampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
116 | 84BB33C625A8655B0056A35F /* SampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleUITests.swift; sourceTree = ""; };
117 | 84BB33C825A8655B0056A35F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
118 | 84BB33D825A86B450056A35F /* PagerItemsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagerItemsView.swift; sourceTree = ""; };
119 | 84BB33E425A86B870056A35F /* PagerOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagerOptions.swift; sourceTree = ""; };
120 | 84BB33F025A872ED0056A35F /* PagerItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PagerItemView.swift; sourceTree = ""; };
121 | 84C8D31925C15B0B005CDC11 /* MockData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockData.swift; sourceTree = ""; };
122 | 84D77DD625C0762C0035CA1D /* TopView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TopView.xib; sourceTree = ""; };
123 | 84D77DEC25C088210035CA1D /* TimelineTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableCell.swift; sourceTree = ""; };
124 | 84D77DF325C0882D0035CA1D /* TimelineTableCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TimelineTableCell.xib; sourceTree = ""; };
125 | 84D77DFA25C149840035CA1D /* NotificationTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTableCell.swift; sourceTree = ""; };
126 | 84D77E0125C149910035CA1D /* NotificationTableCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NotificationTableCell.xib; sourceTree = ""; };
127 | 84DC4E9825D3A5C500BA8ACB /* DefaultPagerItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultPagerItemView.swift; sourceTree = ""; };
128 | /* End PBXFileReference section */
129 |
130 | /* Begin PBXFrameworksBuildPhase section */
131 | 84BB332825A85EEF0056A35F /* Frameworks */ = {
132 | isa = PBXFrameworksBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | 84BB333125A85EEF0056A35F /* Frameworks */ = {
139 | isa = PBXFrameworksBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | 84BB333525A85EEF0056A35F /* TopContentPager.framework in Frameworks */,
143 | );
144 | runOnlyForDeploymentPostprocessing = 0;
145 | };
146 | 84BB339F25A8655A0056A35F /* Frameworks */ = {
147 | isa = PBXFrameworksBuildPhase;
148 | buildActionMask = 2147483647;
149 | files = (
150 | );
151 | runOnlyForDeploymentPostprocessing = 0;
152 | };
153 | 84BB33B425A8655B0056A35F /* Frameworks */ = {
154 | isa = PBXFrameworksBuildPhase;
155 | buildActionMask = 2147483647;
156 | files = (
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | 84BB33BF25A8655B0056A35F /* Frameworks */ = {
161 | isa = PBXFrameworksBuildPhase;
162 | buildActionMask = 2147483647;
163 | files = (
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXFrameworksBuildPhase section */
168 |
169 | /* Begin PBXGroup section */
170 | 843FD87925AE9F6300AD615F /* Utilitie */ = {
171 | isa = PBXGroup;
172 | children = (
173 | 843FD85525AE8EBF00AD615F /* NSObject+Name.swift */,
174 | 843FD85C25AE8EEF00AD615F /* UITableView+Register.swift */,
175 | );
176 | path = Utilitie;
177 | sourceTree = "";
178 | };
179 | 84BB332125A85EEF0056A35F = {
180 | isa = PBXGroup;
181 | children = (
182 | 84BB332D25A85EEF0056A35F /* TopContentPager */,
183 | 84BB333825A85EEF0056A35F /* TopContentPagerTests */,
184 | 84BB33A325A8655A0056A35F /* Sample */,
185 | 84BB33BA25A8655B0056A35F /* SampleTests */,
186 | 84BB33C525A8655B0056A35F /* SampleUITests */,
187 | 84BB332C25A85EEF0056A35F /* Products */,
188 | );
189 | sourceTree = "";
190 | };
191 | 84BB332C25A85EEF0056A35F /* Products */ = {
192 | isa = PBXGroup;
193 | children = (
194 | 84BB332B25A85EEF0056A35F /* TopContentPager.framework */,
195 | 84BB333425A85EEF0056A35F /* TopContentPagerTests.xctest */,
196 | 84BB33A225A8655A0056A35F /* Sample.app */,
197 | 84BB33B725A8655B0056A35F /* SampleTests.xctest */,
198 | 84BB33C225A8655B0056A35F /* SampleUITests.xctest */,
199 | );
200 | name = Products;
201 | sourceTree = "";
202 | };
203 | 84BB332D25A85EEF0056A35F /* TopContentPager */ = {
204 | isa = PBXGroup;
205 | children = (
206 | 843FD87925AE9F6300AD615F /* Utilitie */,
207 | 84BB33D725A86B360056A35F /* View */,
208 | 84BB337B25A85FBC0056A35F /* Cell */,
209 | 84BB338525A85FBC0056A35F /* ContentTableBody.swift */,
210 | 84BB338725A85FBC0056A35F /* ContentTableViewController.swift */,
211 | 8435A4BE25BFFA1C00EEDA77 /* TopContentView.swift */,
212 | 84BB338925A85FBC0056A35F /* TopContentPagerViewController.swift */,
213 | 84BB332E25A85EEF0056A35F /* TopContentPager.h */,
214 | 84BB332F25A85EEF0056A35F /* Info.plist */,
215 | );
216 | path = TopContentPager;
217 | sourceTree = "";
218 | };
219 | 84BB333825A85EEF0056A35F /* TopContentPagerTests */ = {
220 | isa = PBXGroup;
221 | children = (
222 | 84BB333925A85EEF0056A35F /* TopContentPagerTests.swift */,
223 | 84BB333B25A85EEF0056A35F /* Info.plist */,
224 | );
225 | path = TopContentPagerTests;
226 | sourceTree = "";
227 | };
228 | 84BB337B25A85FBC0056A35F /* Cell */ = {
229 | isa = PBXGroup;
230 | children = (
231 | 84BB337D25A85FBC0056A35F /* ContentBodyCell.swift */,
232 | 84BB337F25A85FBC0056A35F /* ContentTopCell.swift */,
233 | );
234 | path = Cell;
235 | sourceTree = "";
236 | };
237 | 84BB33A325A8655A0056A35F /* Sample */ = {
238 | isa = PBXGroup;
239 | children = (
240 | 84BB33A425A8655A0056A35F /* AppDelegate.swift */,
241 | 84BB33A625A8655A0056A35F /* SceneDelegate.swift */,
242 | 84C8D36C25C4FE2C005CDC11 /* ViewController */,
243 | 84C8D37225C4FE68005CDC11 /* Cell */,
244 | 84C8D37825C4FE8C005CDC11 /* View */,
245 | 84C8D38425C4FEBC005CDC11 /* Entity */,
246 | 84C8D37E25C4FEA3005CDC11 /* Utility */,
247 | 84BB33AD25A8655B0056A35F /* Assets.xcassets */,
248 | 84BB33AF25A8655B0056A35F /* LaunchScreen.storyboard */,
249 | 84BB33B225A8655B0056A35F /* Info.plist */,
250 | );
251 | path = Sample;
252 | sourceTree = "";
253 | };
254 | 84BB33BA25A8655B0056A35F /* SampleTests */ = {
255 | isa = PBXGroup;
256 | children = (
257 | 84BB33BB25A8655B0056A35F /* SampleTests.swift */,
258 | 84BB33BD25A8655B0056A35F /* Info.plist */,
259 | );
260 | path = SampleTests;
261 | sourceTree = "";
262 | };
263 | 84BB33C525A8655B0056A35F /* SampleUITests */ = {
264 | isa = PBXGroup;
265 | children = (
266 | 84BB33C625A8655B0056A35F /* SampleUITests.swift */,
267 | 84BB33C825A8655B0056A35F /* Info.plist */,
268 | );
269 | path = SampleUITests;
270 | sourceTree = "";
271 | };
272 | 84BB33D725A86B360056A35F /* View */ = {
273 | isa = PBXGroup;
274 | children = (
275 | 84BB33D825A86B450056A35F /* PagerItemsView.swift */,
276 | 84BB33F025A872ED0056A35F /* PagerItemView.swift */,
277 | 84DC4E9825D3A5C500BA8ACB /* DefaultPagerItemView.swift */,
278 | 84BB33E425A86B870056A35F /* PagerOptions.swift */,
279 | );
280 | path = View;
281 | sourceTree = "";
282 | };
283 | 84C8D36C25C4FE2C005CDC11 /* ViewController */ = {
284 | isa = PBXGroup;
285 | children = (
286 | 84BB33A825A8655A0056A35F /* ViewController.swift */,
287 | 84BB33AA25A8655A0056A35F /* Main.storyboard */,
288 | 843FDA0525B0969100AD615F /* CustomTopContentPagerViewController.swift */,
289 | 8435A54125C061E400EEDA77 /* MyPostViewController.swift */,
290 | 8435A54825C061F600EEDA77 /* MyPostViewController.storyboard */,
291 | 843FD88425AEA08200AD615F /* TimelineViewController.swift */,
292 | 843FD89225AEA09A00AD615F /* TimelineViewController.storyboard */,
293 | 843FD88B25AEA08E00AD615F /* NotificationViewController.swift */,
294 | 843FD8A525AEA0B600AD615F /* NotificationViewController.storyboard */,
295 | );
296 | path = ViewController;
297 | sourceTree = "";
298 | };
299 | 84C8D37225C4FE68005CDC11 /* Cell */ = {
300 | isa = PBXGroup;
301 | children = (
302 | 84D77DEC25C088210035CA1D /* TimelineTableCell.swift */,
303 | 84D77DF325C0882D0035CA1D /* TimelineTableCell.xib */,
304 | 84D77DFA25C149840035CA1D /* NotificationTableCell.swift */,
305 | 84D77E0125C149910035CA1D /* NotificationTableCell.xib */,
306 | 8435A54F25C0664E00EEDA77 /* MyPostCollectionCell.swift */,
307 | 8435A55625C0665A00EEDA77 /* MyPostCollectionCell.xib */,
308 | );
309 | path = Cell;
310 | sourceTree = "";
311 | };
312 | 84C8D37825C4FE8C005CDC11 /* View */ = {
313 | isa = PBXGroup;
314 | children = (
315 | 843FD8AC25AEA21E00AD615F /* TopView.swift */,
316 | 84D77DD625C0762C0035CA1D /* TopView.xib */,
317 | );
318 | path = View;
319 | sourceTree = "";
320 | };
321 | 84C8D37E25C4FEA3005CDC11 /* Utility */ = {
322 | isa = PBXGroup;
323 | children = (
324 | 843FD8C125AEAC4C00AD615F /* Storyboard.swift */,
325 | 843FD8CD25AEC11A00AD615F /* NSObject+NibLoading.swift */,
326 | );
327 | path = Utility;
328 | sourceTree = "";
329 | };
330 | 84C8D38425C4FEBC005CDC11 /* Entity */ = {
331 | isa = PBXGroup;
332 | children = (
333 | 84C8D31925C15B0B005CDC11 /* MockData.swift */,
334 | );
335 | path = Entity;
336 | sourceTree = "";
337 | };
338 | /* End PBXGroup section */
339 |
340 | /* Begin PBXHeadersBuildPhase section */
341 | 84BB332625A85EEF0056A35F /* Headers */ = {
342 | isa = PBXHeadersBuildPhase;
343 | buildActionMask = 2147483647;
344 | files = (
345 | 84BB333C25A85EEF0056A35F /* TopContentPager.h in Headers */,
346 | );
347 | runOnlyForDeploymentPostprocessing = 0;
348 | };
349 | /* End PBXHeadersBuildPhase section */
350 |
351 | /* Begin PBXNativeTarget section */
352 | 84BB332A25A85EEF0056A35F /* TopContentPager */ = {
353 | isa = PBXNativeTarget;
354 | buildConfigurationList = 84BB333F25A85EEF0056A35F /* Build configuration list for PBXNativeTarget "TopContentPager" */;
355 | buildPhases = (
356 | 84BB332625A85EEF0056A35F /* Headers */,
357 | 84BB332725A85EEF0056A35F /* Sources */,
358 | 84BB332825A85EEF0056A35F /* Frameworks */,
359 | 84BB332925A85EEF0056A35F /* Resources */,
360 | );
361 | buildRules = (
362 | );
363 | dependencies = (
364 | );
365 | name = TopContentPager;
366 | productName = TopContentPager;
367 | productReference = 84BB332B25A85EEF0056A35F /* TopContentPager.framework */;
368 | productType = "com.apple.product-type.framework";
369 | };
370 | 84BB333325A85EEF0056A35F /* TopContentPagerTests */ = {
371 | isa = PBXNativeTarget;
372 | buildConfigurationList = 84BB334225A85EEF0056A35F /* Build configuration list for PBXNativeTarget "TopContentPagerTests" */;
373 | buildPhases = (
374 | 84BB333025A85EEF0056A35F /* Sources */,
375 | 84BB333125A85EEF0056A35F /* Frameworks */,
376 | 84BB333225A85EEF0056A35F /* Resources */,
377 | );
378 | buildRules = (
379 | );
380 | dependencies = (
381 | 84BB333725A85EEF0056A35F /* PBXTargetDependency */,
382 | );
383 | name = TopContentPagerTests;
384 | productName = TopContentPagerTests;
385 | productReference = 84BB333425A85EEF0056A35F /* TopContentPagerTests.xctest */;
386 | productType = "com.apple.product-type.bundle.unit-test";
387 | };
388 | 84BB33A125A8655A0056A35F /* Sample */ = {
389 | isa = PBXNativeTarget;
390 | buildConfigurationList = 84BB33C925A8655B0056A35F /* Build configuration list for PBXNativeTarget "Sample" */;
391 | buildPhases = (
392 | 84BB339E25A8655A0056A35F /* Sources */,
393 | 84BB339F25A8655A0056A35F /* Frameworks */,
394 | 84BB33A025A8655A0056A35F /* Resources */,
395 | );
396 | buildRules = (
397 | );
398 | dependencies = (
399 | );
400 | name = Sample;
401 | productName = Sample;
402 | productReference = 84BB33A225A8655A0056A35F /* Sample.app */;
403 | productType = "com.apple.product-type.application";
404 | };
405 | 84BB33B625A8655B0056A35F /* SampleTests */ = {
406 | isa = PBXNativeTarget;
407 | buildConfigurationList = 84BB33CC25A8655B0056A35F /* Build configuration list for PBXNativeTarget "SampleTests" */;
408 | buildPhases = (
409 | 84BB33B325A8655B0056A35F /* Sources */,
410 | 84BB33B425A8655B0056A35F /* Frameworks */,
411 | 84BB33B525A8655B0056A35F /* Resources */,
412 | );
413 | buildRules = (
414 | );
415 | dependencies = (
416 | 84BB33B925A8655B0056A35F /* PBXTargetDependency */,
417 | );
418 | name = SampleTests;
419 | productName = SampleTests;
420 | productReference = 84BB33B725A8655B0056A35F /* SampleTests.xctest */;
421 | productType = "com.apple.product-type.bundle.unit-test";
422 | };
423 | 84BB33C125A8655B0056A35F /* SampleUITests */ = {
424 | isa = PBXNativeTarget;
425 | buildConfigurationList = 84BB33CF25A8655B0056A35F /* Build configuration list for PBXNativeTarget "SampleUITests" */;
426 | buildPhases = (
427 | 84BB33BE25A8655B0056A35F /* Sources */,
428 | 84BB33BF25A8655B0056A35F /* Frameworks */,
429 | 84BB33C025A8655B0056A35F /* Resources */,
430 | );
431 | buildRules = (
432 | );
433 | dependencies = (
434 | 84BB33C425A8655B0056A35F /* PBXTargetDependency */,
435 | );
436 | name = SampleUITests;
437 | productName = SampleUITests;
438 | productReference = 84BB33C225A8655B0056A35F /* SampleUITests.xctest */;
439 | productType = "com.apple.product-type.bundle.ui-testing";
440 | };
441 | /* End PBXNativeTarget section */
442 |
443 | /* Begin PBXProject section */
444 | 84BB332225A85EEF0056A35F /* Project object */ = {
445 | isa = PBXProject;
446 | attributes = {
447 | LastSwiftUpdateCheck = 1230;
448 | LastUpgradeCheck = 1230;
449 | TargetAttributes = {
450 | 84BB332A25A85EEF0056A35F = {
451 | CreatedOnToolsVersion = 12.3;
452 | LastSwiftMigration = 1230;
453 | };
454 | 84BB333325A85EEF0056A35F = {
455 | CreatedOnToolsVersion = 12.3;
456 | };
457 | 84BB33A125A8655A0056A35F = {
458 | CreatedOnToolsVersion = 12.3;
459 | };
460 | 84BB33B625A8655B0056A35F = {
461 | CreatedOnToolsVersion = 12.3;
462 | TestTargetID = 84BB33A125A8655A0056A35F;
463 | };
464 | 84BB33C125A8655B0056A35F = {
465 | CreatedOnToolsVersion = 12.3;
466 | TestTargetID = 84BB33A125A8655A0056A35F;
467 | };
468 | };
469 | };
470 | buildConfigurationList = 84BB332525A85EEF0056A35F /* Build configuration list for PBXProject "TopContentPager" */;
471 | compatibilityVersion = "Xcode 9.3";
472 | developmentRegion = en;
473 | hasScannedForEncodings = 0;
474 | knownRegions = (
475 | en,
476 | Base,
477 | );
478 | mainGroup = 84BB332125A85EEF0056A35F;
479 | productRefGroup = 84BB332C25A85EEF0056A35F /* Products */;
480 | projectDirPath = "";
481 | projectRoot = "";
482 | targets = (
483 | 84BB332A25A85EEF0056A35F /* TopContentPager */,
484 | 84BB333325A85EEF0056A35F /* TopContentPagerTests */,
485 | 84BB33A125A8655A0056A35F /* Sample */,
486 | 84BB33B625A8655B0056A35F /* SampleTests */,
487 | 84BB33C125A8655B0056A35F /* SampleUITests */,
488 | );
489 | };
490 | /* End PBXProject section */
491 |
492 | /* Begin PBXResourcesBuildPhase section */
493 | 84BB332925A85EEF0056A35F /* Resources */ = {
494 | isa = PBXResourcesBuildPhase;
495 | buildActionMask = 2147483647;
496 | files = (
497 | );
498 | runOnlyForDeploymentPostprocessing = 0;
499 | };
500 | 84BB333225A85EEF0056A35F /* Resources */ = {
501 | isa = PBXResourcesBuildPhase;
502 | buildActionMask = 2147483647;
503 | files = (
504 | );
505 | runOnlyForDeploymentPostprocessing = 0;
506 | };
507 | 84BB33A025A8655A0056A35F /* Resources */ = {
508 | isa = PBXResourcesBuildPhase;
509 | buildActionMask = 2147483647;
510 | files = (
511 | 84BB33B125A8655B0056A35F /* LaunchScreen.storyboard in Resources */,
512 | 84BB33AE25A8655B0056A35F /* Assets.xcassets in Resources */,
513 | 84D77DD725C0762C0035CA1D /* TopView.xib in Resources */,
514 | 843FD89325AEA09A00AD615F /* TimelineViewController.storyboard in Resources */,
515 | 8435A55725C0665A00EEDA77 /* MyPostCollectionCell.xib in Resources */,
516 | 84D77E0225C149910035CA1D /* NotificationTableCell.xib in Resources */,
517 | 8435A54925C061F600EEDA77 /* MyPostViewController.storyboard in Resources */,
518 | 843FD8A625AEA0B600AD615F /* NotificationViewController.storyboard in Resources */,
519 | 84D77DF425C0882D0035CA1D /* TimelineTableCell.xib in Resources */,
520 | 84BB33AC25A8655A0056A35F /* Main.storyboard in Resources */,
521 | );
522 | runOnlyForDeploymentPostprocessing = 0;
523 | };
524 | 84BB33B525A8655B0056A35F /* Resources */ = {
525 | isa = PBXResourcesBuildPhase;
526 | buildActionMask = 2147483647;
527 | files = (
528 | );
529 | runOnlyForDeploymentPostprocessing = 0;
530 | };
531 | 84BB33C025A8655B0056A35F /* Resources */ = {
532 | isa = PBXResourcesBuildPhase;
533 | buildActionMask = 2147483647;
534 | files = (
535 | );
536 | runOnlyForDeploymentPostprocessing = 0;
537 | };
538 | /* End PBXResourcesBuildPhase section */
539 |
540 | /* Begin PBXSourcesBuildPhase section */
541 | 84BB332725A85EEF0056A35F /* Sources */ = {
542 | isa = PBXSourcesBuildPhase;
543 | buildActionMask = 2147483647;
544 | files = (
545 | 8435A4BF25BFFA1C00EEDA77 /* TopContentView.swift in Sources */,
546 | 84BB339525A85FBC0056A35F /* ContentTableBody.swift in Sources */,
547 | 843FD85625AE8EBF00AD615F /* NSObject+Name.swift in Sources */,
548 | 84BB339725A85FBC0056A35F /* ContentTableViewController.swift in Sources */,
549 | 84BB33F125A872ED0056A35F /* PagerItemView.swift in Sources */,
550 | 843FD85D25AE8EEF00AD615F /* UITableView+Register.swift in Sources */,
551 | 84BB338E25A85FBC0056A35F /* ContentBodyCell.swift in Sources */,
552 | 84DC4E9925D3A5C500BA8ACB /* DefaultPagerItemView.swift in Sources */,
553 | 84BB33E525A86B870056A35F /* PagerOptions.swift in Sources */,
554 | 84BB33D925A86B450056A35F /* PagerItemsView.swift in Sources */,
555 | 84BB339925A85FBC0056A35F /* TopContentPagerViewController.swift in Sources */,
556 | 84BB339025A85FBC0056A35F /* ContentTopCell.swift in Sources */,
557 | );
558 | runOnlyForDeploymentPostprocessing = 0;
559 | };
560 | 84BB333025A85EEF0056A35F /* Sources */ = {
561 | isa = PBXSourcesBuildPhase;
562 | buildActionMask = 2147483647;
563 | files = (
564 | 84BB333A25A85EEF0056A35F /* TopContentPagerTests.swift in Sources */,
565 | );
566 | runOnlyForDeploymentPostprocessing = 0;
567 | };
568 | 84BB339E25A8655A0056A35F /* Sources */ = {
569 | isa = PBXSourcesBuildPhase;
570 | buildActionMask = 2147483647;
571 | files = (
572 | 843FD88C25AEA08E00AD615F /* NotificationViewController.swift in Sources */,
573 | 8435A55025C0664E00EEDA77 /* MyPostCollectionCell.swift in Sources */,
574 | 84BB33A925A8655A0056A35F /* ViewController.swift in Sources */,
575 | 843FD88525AEA08200AD615F /* TimelineViewController.swift in Sources */,
576 | 8435A54225C061E400EEDA77 /* MyPostViewController.swift in Sources */,
577 | 84C8D31A25C15B0B005CDC11 /* MockData.swift in Sources */,
578 | 843FD8C225AEAC4C00AD615F /* Storyboard.swift in Sources */,
579 | 84BB33A525A8655A0056A35F /* AppDelegate.swift in Sources */,
580 | 843FD8AD25AEA21E00AD615F /* TopView.swift in Sources */,
581 | 843FDA0625B0969100AD615F /* CustomTopContentPagerViewController.swift in Sources */,
582 | 84D77DED25C088210035CA1D /* TimelineTableCell.swift in Sources */,
583 | 84D77DFB25C149840035CA1D /* NotificationTableCell.swift in Sources */,
584 | 843FD8CE25AEC11A00AD615F /* NSObject+NibLoading.swift in Sources */,
585 | 84BB33A725A8655A0056A35F /* SceneDelegate.swift in Sources */,
586 | );
587 | runOnlyForDeploymentPostprocessing = 0;
588 | };
589 | 84BB33B325A8655B0056A35F /* Sources */ = {
590 | isa = PBXSourcesBuildPhase;
591 | buildActionMask = 2147483647;
592 | files = (
593 | 84BB33BC25A8655B0056A35F /* SampleTests.swift in Sources */,
594 | );
595 | runOnlyForDeploymentPostprocessing = 0;
596 | };
597 | 84BB33BE25A8655B0056A35F /* Sources */ = {
598 | isa = PBXSourcesBuildPhase;
599 | buildActionMask = 2147483647;
600 | files = (
601 | 84BB33C725A8655B0056A35F /* SampleUITests.swift in Sources */,
602 | );
603 | runOnlyForDeploymentPostprocessing = 0;
604 | };
605 | /* End PBXSourcesBuildPhase section */
606 |
607 | /* Begin PBXTargetDependency section */
608 | 84BB333725A85EEF0056A35F /* PBXTargetDependency */ = {
609 | isa = PBXTargetDependency;
610 | target = 84BB332A25A85EEF0056A35F /* TopContentPager */;
611 | targetProxy = 84BB333625A85EEF0056A35F /* PBXContainerItemProxy */;
612 | };
613 | 84BB33B925A8655B0056A35F /* PBXTargetDependency */ = {
614 | isa = PBXTargetDependency;
615 | target = 84BB33A125A8655A0056A35F /* Sample */;
616 | targetProxy = 84BB33B825A8655B0056A35F /* PBXContainerItemProxy */;
617 | };
618 | 84BB33C425A8655B0056A35F /* PBXTargetDependency */ = {
619 | isa = PBXTargetDependency;
620 | target = 84BB33A125A8655A0056A35F /* Sample */;
621 | targetProxy = 84BB33C325A8655B0056A35F /* PBXContainerItemProxy */;
622 | };
623 | /* End PBXTargetDependency section */
624 |
625 | /* Begin PBXVariantGroup section */
626 | 84BB33AA25A8655A0056A35F /* Main.storyboard */ = {
627 | isa = PBXVariantGroup;
628 | children = (
629 | 84BB33AB25A8655A0056A35F /* Base */,
630 | );
631 | name = Main.storyboard;
632 | sourceTree = "";
633 | };
634 | 84BB33AF25A8655B0056A35F /* LaunchScreen.storyboard */ = {
635 | isa = PBXVariantGroup;
636 | children = (
637 | 84BB33B025A8655B0056A35F /* Base */,
638 | );
639 | name = LaunchScreen.storyboard;
640 | sourceTree = "";
641 | };
642 | /* End PBXVariantGroup section */
643 |
644 | /* Begin XCBuildConfiguration section */
645 | 84BB333D25A85EEF0056A35F /* Debug */ = {
646 | isa = XCBuildConfiguration;
647 | buildSettings = {
648 | ALWAYS_SEARCH_USER_PATHS = NO;
649 | CLANG_ANALYZER_NONNULL = YES;
650 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
651 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
652 | CLANG_CXX_LIBRARY = "libc++";
653 | CLANG_ENABLE_MODULES = YES;
654 | CLANG_ENABLE_OBJC_ARC = YES;
655 | CLANG_ENABLE_OBJC_WEAK = YES;
656 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
657 | CLANG_WARN_BOOL_CONVERSION = YES;
658 | CLANG_WARN_COMMA = YES;
659 | CLANG_WARN_CONSTANT_CONVERSION = YES;
660 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
661 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
662 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
663 | CLANG_WARN_EMPTY_BODY = YES;
664 | CLANG_WARN_ENUM_CONVERSION = YES;
665 | CLANG_WARN_INFINITE_RECURSION = YES;
666 | CLANG_WARN_INT_CONVERSION = YES;
667 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
668 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
669 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
670 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
671 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
672 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
673 | CLANG_WARN_STRICT_PROTOTYPES = YES;
674 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
675 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
676 | CLANG_WARN_UNREACHABLE_CODE = YES;
677 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
678 | COPY_PHASE_STRIP = NO;
679 | CURRENT_PROJECT_VERSION = 1;
680 | DEBUG_INFORMATION_FORMAT = dwarf;
681 | ENABLE_STRICT_OBJC_MSGSEND = YES;
682 | ENABLE_TESTABILITY = YES;
683 | GCC_C_LANGUAGE_STANDARD = gnu11;
684 | GCC_DYNAMIC_NO_PIC = NO;
685 | GCC_NO_COMMON_BLOCKS = YES;
686 | GCC_OPTIMIZATION_LEVEL = 0;
687 | GCC_PREPROCESSOR_DEFINITIONS = (
688 | "DEBUG=1",
689 | "$(inherited)",
690 | );
691 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
692 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
693 | GCC_WARN_UNDECLARED_SELECTOR = YES;
694 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
695 | GCC_WARN_UNUSED_FUNCTION = YES;
696 | GCC_WARN_UNUSED_VARIABLE = YES;
697 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
698 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
699 | MTL_FAST_MATH = YES;
700 | ONLY_ACTIVE_ARCH = YES;
701 | SDKROOT = iphoneos;
702 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
703 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
704 | VERSIONING_SYSTEM = "apple-generic";
705 | VERSION_INFO_PREFIX = "";
706 | };
707 | name = Debug;
708 | };
709 | 84BB333E25A85EEF0056A35F /* Release */ = {
710 | isa = XCBuildConfiguration;
711 | buildSettings = {
712 | ALWAYS_SEARCH_USER_PATHS = NO;
713 | CLANG_ANALYZER_NONNULL = YES;
714 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
715 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
716 | CLANG_CXX_LIBRARY = "libc++";
717 | CLANG_ENABLE_MODULES = YES;
718 | CLANG_ENABLE_OBJC_ARC = YES;
719 | CLANG_ENABLE_OBJC_WEAK = YES;
720 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
721 | CLANG_WARN_BOOL_CONVERSION = YES;
722 | CLANG_WARN_COMMA = YES;
723 | CLANG_WARN_CONSTANT_CONVERSION = YES;
724 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
725 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
726 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
727 | CLANG_WARN_EMPTY_BODY = YES;
728 | CLANG_WARN_ENUM_CONVERSION = YES;
729 | CLANG_WARN_INFINITE_RECURSION = YES;
730 | CLANG_WARN_INT_CONVERSION = YES;
731 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
732 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
733 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
734 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
735 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
736 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
737 | CLANG_WARN_STRICT_PROTOTYPES = YES;
738 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
739 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
740 | CLANG_WARN_UNREACHABLE_CODE = YES;
741 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
742 | COPY_PHASE_STRIP = NO;
743 | CURRENT_PROJECT_VERSION = 1;
744 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
745 | ENABLE_NS_ASSERTIONS = NO;
746 | ENABLE_STRICT_OBJC_MSGSEND = YES;
747 | GCC_C_LANGUAGE_STANDARD = gnu11;
748 | GCC_NO_COMMON_BLOCKS = YES;
749 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
750 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
751 | GCC_WARN_UNDECLARED_SELECTOR = YES;
752 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
753 | GCC_WARN_UNUSED_FUNCTION = YES;
754 | GCC_WARN_UNUSED_VARIABLE = YES;
755 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
756 | MTL_ENABLE_DEBUG_INFO = NO;
757 | MTL_FAST_MATH = YES;
758 | SDKROOT = iphoneos;
759 | SWIFT_COMPILATION_MODE = wholemodule;
760 | SWIFT_OPTIMIZATION_LEVEL = "-O";
761 | VALIDATE_PRODUCT = YES;
762 | VERSIONING_SYSTEM = "apple-generic";
763 | VERSION_INFO_PREFIX = "";
764 | };
765 | name = Release;
766 | };
767 | 84BB334025A85EEF0056A35F /* Debug */ = {
768 | isa = XCBuildConfiguration;
769 | buildSettings = {
770 | CLANG_ENABLE_MODULES = YES;
771 | CODE_SIGN_STYLE = Automatic;
772 | DEFINES_MODULE = YES;
773 | DEVELOPMENT_TEAM = MH79AD8W2K;
774 | DYLIB_COMPATIBILITY_VERSION = 1;
775 | DYLIB_CURRENT_VERSION = 1;
776 | DYLIB_INSTALL_NAME_BASE = "@rpath";
777 | INFOPLIST_FILE = TopContentPager/Info.plist;
778 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
779 | LD_RUNPATH_SEARCH_PATHS = (
780 | "$(inherited)",
781 | "@executable_path/Frameworks",
782 | "@loader_path/Frameworks",
783 | );
784 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.TopContentPager";
785 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
786 | SKIP_INSTALL = YES;
787 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
788 | SWIFT_VERSION = 5.0;
789 | TARGETED_DEVICE_FAMILY = "1,2";
790 | };
791 | name = Debug;
792 | };
793 | 84BB334125A85EEF0056A35F /* Release */ = {
794 | isa = XCBuildConfiguration;
795 | buildSettings = {
796 | CLANG_ENABLE_MODULES = YES;
797 | CODE_SIGN_STYLE = Automatic;
798 | DEFINES_MODULE = YES;
799 | DEVELOPMENT_TEAM = MH79AD8W2K;
800 | DYLIB_COMPATIBILITY_VERSION = 1;
801 | DYLIB_CURRENT_VERSION = 1;
802 | DYLIB_INSTALL_NAME_BASE = "@rpath";
803 | INFOPLIST_FILE = TopContentPager/Info.plist;
804 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
805 | LD_RUNPATH_SEARCH_PATHS = (
806 | "$(inherited)",
807 | "@executable_path/Frameworks",
808 | "@loader_path/Frameworks",
809 | );
810 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.TopContentPager";
811 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
812 | SKIP_INSTALL = YES;
813 | SWIFT_VERSION = 5.0;
814 | TARGETED_DEVICE_FAMILY = "1,2";
815 | };
816 | name = Release;
817 | };
818 | 84BB334325A85EEF0056A35F /* Debug */ = {
819 | isa = XCBuildConfiguration;
820 | buildSettings = {
821 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
822 | CODE_SIGN_STYLE = Automatic;
823 | DEVELOPMENT_TEAM = MH79AD8W2K;
824 | INFOPLIST_FILE = TopContentPagerTests/Info.plist;
825 | LD_RUNPATH_SEARCH_PATHS = (
826 | "$(inherited)",
827 | "@executable_path/Frameworks",
828 | "@loader_path/Frameworks",
829 | );
830 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.TopContentPagerTests";
831 | PRODUCT_NAME = "$(TARGET_NAME)";
832 | SWIFT_VERSION = 5.0;
833 | TARGETED_DEVICE_FAMILY = "1,2";
834 | };
835 | name = Debug;
836 | };
837 | 84BB334425A85EEF0056A35F /* Release */ = {
838 | isa = XCBuildConfiguration;
839 | buildSettings = {
840 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
841 | CODE_SIGN_STYLE = Automatic;
842 | DEVELOPMENT_TEAM = MH79AD8W2K;
843 | INFOPLIST_FILE = TopContentPagerTests/Info.plist;
844 | LD_RUNPATH_SEARCH_PATHS = (
845 | "$(inherited)",
846 | "@executable_path/Frameworks",
847 | "@loader_path/Frameworks",
848 | );
849 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.TopContentPagerTests";
850 | PRODUCT_NAME = "$(TARGET_NAME)";
851 | SWIFT_VERSION = 5.0;
852 | TARGETED_DEVICE_FAMILY = "1,2";
853 | };
854 | name = Release;
855 | };
856 | 84BB33CA25A8655B0056A35F /* Debug */ = {
857 | isa = XCBuildConfiguration;
858 | buildSettings = {
859 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
860 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
861 | CODE_SIGN_STYLE = Automatic;
862 | DEVELOPMENT_TEAM = MH79AD8W2K;
863 | INFOPLIST_FILE = Sample/Info.plist;
864 | LD_RUNPATH_SEARCH_PATHS = (
865 | "$(inherited)",
866 | "@executable_path/Frameworks",
867 | );
868 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.Sample";
869 | PRODUCT_NAME = "$(TARGET_NAME)";
870 | SWIFT_VERSION = 5.0;
871 | TARGETED_DEVICE_FAMILY = "1,2";
872 | };
873 | name = Debug;
874 | };
875 | 84BB33CB25A8655B0056A35F /* Release */ = {
876 | isa = XCBuildConfiguration;
877 | buildSettings = {
878 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
879 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
880 | CODE_SIGN_STYLE = Automatic;
881 | DEVELOPMENT_TEAM = MH79AD8W2K;
882 | INFOPLIST_FILE = Sample/Info.plist;
883 | LD_RUNPATH_SEARCH_PATHS = (
884 | "$(inherited)",
885 | "@executable_path/Frameworks",
886 | );
887 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.Sample";
888 | PRODUCT_NAME = "$(TARGET_NAME)";
889 | SWIFT_VERSION = 5.0;
890 | TARGETED_DEVICE_FAMILY = "1,2";
891 | };
892 | name = Release;
893 | };
894 | 84BB33CD25A8655B0056A35F /* Debug */ = {
895 | isa = XCBuildConfiguration;
896 | buildSettings = {
897 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
898 | BUNDLE_LOADER = "$(TEST_HOST)";
899 | CODE_SIGN_STYLE = Automatic;
900 | DEVELOPMENT_TEAM = MH79AD8W2K;
901 | INFOPLIST_FILE = SampleTests/Info.plist;
902 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
903 | LD_RUNPATH_SEARCH_PATHS = (
904 | "$(inherited)",
905 | "@executable_path/Frameworks",
906 | "@loader_path/Frameworks",
907 | );
908 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.SampleTests";
909 | PRODUCT_NAME = "$(TARGET_NAME)";
910 | SWIFT_VERSION = 5.0;
911 | TARGETED_DEVICE_FAMILY = "1,2";
912 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample";
913 | };
914 | name = Debug;
915 | };
916 | 84BB33CE25A8655B0056A35F /* Release */ = {
917 | isa = XCBuildConfiguration;
918 | buildSettings = {
919 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
920 | BUNDLE_LOADER = "$(TEST_HOST)";
921 | CODE_SIGN_STYLE = Automatic;
922 | DEVELOPMENT_TEAM = MH79AD8W2K;
923 | INFOPLIST_FILE = SampleTests/Info.plist;
924 | IPHONEOS_DEPLOYMENT_TARGET = 14.3;
925 | LD_RUNPATH_SEARCH_PATHS = (
926 | "$(inherited)",
927 | "@executable_path/Frameworks",
928 | "@loader_path/Frameworks",
929 | );
930 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.SampleTests";
931 | PRODUCT_NAME = "$(TARGET_NAME)";
932 | SWIFT_VERSION = 5.0;
933 | TARGETED_DEVICE_FAMILY = "1,2";
934 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Sample.app/Sample";
935 | };
936 | name = Release;
937 | };
938 | 84BB33D025A8655B0056A35F /* Debug */ = {
939 | isa = XCBuildConfiguration;
940 | buildSettings = {
941 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
942 | CODE_SIGN_STYLE = Automatic;
943 | DEVELOPMENT_TEAM = MH79AD8W2K;
944 | INFOPLIST_FILE = SampleUITests/Info.plist;
945 | LD_RUNPATH_SEARCH_PATHS = (
946 | "$(inherited)",
947 | "@executable_path/Frameworks",
948 | "@loader_path/Frameworks",
949 | );
950 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.SampleUITests";
951 | PRODUCT_NAME = "$(TARGET_NAME)";
952 | SWIFT_VERSION = 5.0;
953 | TARGETED_DEVICE_FAMILY = "1,2";
954 | TEST_TARGET_NAME = Sample;
955 | };
956 | name = Debug;
957 | };
958 | 84BB33D125A8655B0056A35F /* Release */ = {
959 | isa = XCBuildConfiguration;
960 | buildSettings = {
961 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
962 | CODE_SIGN_STYLE = Automatic;
963 | DEVELOPMENT_TEAM = MH79AD8W2K;
964 | INFOPLIST_FILE = SampleUITests/Info.plist;
965 | LD_RUNPATH_SEARCH_PATHS = (
966 | "$(inherited)",
967 | "@executable_path/Frameworks",
968 | "@loader_path/Frameworks",
969 | );
970 | PRODUCT_BUNDLE_IDENTIFIER = "tanaka-itsuki.SampleUITests";
971 | PRODUCT_NAME = "$(TARGET_NAME)";
972 | SWIFT_VERSION = 5.0;
973 | TARGETED_DEVICE_FAMILY = "1,2";
974 | TEST_TARGET_NAME = Sample;
975 | };
976 | name = Release;
977 | };
978 | /* End XCBuildConfiguration section */
979 |
980 | /* Begin XCConfigurationList section */
981 | 84BB332525A85EEF0056A35F /* Build configuration list for PBXProject "TopContentPager" */ = {
982 | isa = XCConfigurationList;
983 | buildConfigurations = (
984 | 84BB333D25A85EEF0056A35F /* Debug */,
985 | 84BB333E25A85EEF0056A35F /* Release */,
986 | );
987 | defaultConfigurationIsVisible = 0;
988 | defaultConfigurationName = Release;
989 | };
990 | 84BB333F25A85EEF0056A35F /* Build configuration list for PBXNativeTarget "TopContentPager" */ = {
991 | isa = XCConfigurationList;
992 | buildConfigurations = (
993 | 84BB334025A85EEF0056A35F /* Debug */,
994 | 84BB334125A85EEF0056A35F /* Release */,
995 | );
996 | defaultConfigurationIsVisible = 0;
997 | defaultConfigurationName = Release;
998 | };
999 | 84BB334225A85EEF0056A35F /* Build configuration list for PBXNativeTarget "TopContentPagerTests" */ = {
1000 | isa = XCConfigurationList;
1001 | buildConfigurations = (
1002 | 84BB334325A85EEF0056A35F /* Debug */,
1003 | 84BB334425A85EEF0056A35F /* Release */,
1004 | );
1005 | defaultConfigurationIsVisible = 0;
1006 | defaultConfigurationName = Release;
1007 | };
1008 | 84BB33C925A8655B0056A35F /* Build configuration list for PBXNativeTarget "Sample" */ = {
1009 | isa = XCConfigurationList;
1010 | buildConfigurations = (
1011 | 84BB33CA25A8655B0056A35F /* Debug */,
1012 | 84BB33CB25A8655B0056A35F /* Release */,
1013 | );
1014 | defaultConfigurationIsVisible = 0;
1015 | defaultConfigurationName = Release;
1016 | };
1017 | 84BB33CC25A8655B0056A35F /* Build configuration list for PBXNativeTarget "SampleTests" */ = {
1018 | isa = XCConfigurationList;
1019 | buildConfigurations = (
1020 | 84BB33CD25A8655B0056A35F /* Debug */,
1021 | 84BB33CE25A8655B0056A35F /* Release */,
1022 | );
1023 | defaultConfigurationIsVisible = 0;
1024 | defaultConfigurationName = Release;
1025 | };
1026 | 84BB33CF25A8655B0056A35F /* Build configuration list for PBXNativeTarget "SampleUITests" */ = {
1027 | isa = XCConfigurationList;
1028 | buildConfigurations = (
1029 | 84BB33D025A8655B0056A35F /* Debug */,
1030 | 84BB33D125A8655B0056A35F /* Release */,
1031 | );
1032 | defaultConfigurationIsVisible = 0;
1033 | defaultConfigurationName = Release;
1034 | };
1035 | /* End XCConfigurationList section */
1036 | };
1037 | rootObject = 84BB332225A85EEF0056A35F /* Project object */;
1038 | }
1039 |
--------------------------------------------------------------------------------