├── Aquaman-Demo
├── en.lproj
│ └── LaunchScreen.strings
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── TheFlashViewController.swift
├── Info.plist
├── HeaderView.swift
├── Base.lproj
│ └── LaunchScreen.storyboard
├── ViewController.swift
├── WonderWomanViewController.swift
├── AppDelegate.swift
├── BatmanViewController.swift
├── SupermanViewController.swift
├── PageViewController.swift
└── Main.storyboard
├── demo.gif
├── Aquaman
├── .DS_Store
├── Aquaman.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Aquaman.xcscheme
│ └── project.pbxproj
└── Aquaman
│ ├── Info.plist
│ ├── AquamanChildViewController.swift
│ ├── Aquaman.h
│ ├── AquamanContainView.swift
│ ├── UIViewController+Additional.swift
│ ├── NSCache+Additional.swift
│ ├── UIScrollView+Additional.swift
│ ├── AquaMainScrollView.swift
│ ├── AquamanProtocol.swift
│ ├── AquamanPageViewController+Additional.swift
│ └── AquamanPageViewController.swift
├── Tests
├── LinuxMain.swift
└── AquamanTests
│ ├── XCTestManifests.swift
│ └── AquamanTests.swift
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── Aquaman-Demo.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
├── xcshareddata
│ └── xcschemes
│ │ └── Aquaman-Demo.xcscheme
└── project.pbxproj
├── Aquaman.xcworkspace
├── xcshareddata
│ ├── WorkspaceSettings.xcsettings
│ ├── IDEWorkspaceChecks.plist
│ └── swiftpm
│ │ └── Package.resolved
└── contents.xcworkspacedata
├── Podfile
├── Podfile.lock
├── Package.swift
├── Aquaman.podspec
├── Aquaman-DemoUITests
├── Info.plist
└── Aquaman_DemoUITests.swift
├── LICENSE
├── .gitignore
├── README-EN.md
└── README.md
/Aquaman-Demo/en.lproj/LaunchScreen.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bawn/Aquaman/HEAD/demo.gif
--------------------------------------------------------------------------------
/Aquaman/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bawn/Aquaman/HEAD/Aquaman/.DS_Store
--------------------------------------------------------------------------------
/Aquaman-Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import AquamanTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += AquamanTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Aquaman-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/AquamanTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(AquamanTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Aquaman.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Aquaman.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Aquaman.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Aquaman-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | platform :ios, '9.0'
3 | inhibit_all_warnings!
4 | workspace 'Aquaman'
5 |
6 | target 'Aquaman-Demo' do
7 | project './Aquaman-Demo'
8 | use_frameworks!
9 |
10 | pod 'SnapKit', '4.2.0'
11 | pod 'MJRefresh'
12 | # pod 'Trident'
13 | # pod 'Reveal-SDK', '22', :configurations => ['Debug']
14 | # Pods for Aquaman-Demo
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/Aquaman-Demo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Aquaman",
6 | "repositoryURL": "https://github.com/bugkingK/Aquaman",
7 | "state": {
8 | "branch": null,
9 | "revision": "40080956650a1aa783093f11cfb15f781d6ca432",
10 | "version": "0.1.2"
11 | }
12 | }
13 | ]
14 | },
15 | "version": 1
16 | }
17 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - MJRefresh (3.5.0)
3 | - SnapKit (4.2.0)
4 |
5 | DEPENDENCIES:
6 | - MJRefresh
7 | - SnapKit (= 4.2.0)
8 |
9 | SPEC REPOS:
10 | https://cdn.cocoapods.org/:
11 | - MJRefresh
12 | - SnapKit
13 |
14 | SPEC CHECKSUMS:
15 | MJRefresh: 6afc955813966afb08305477dd7a0d9ad5e79a16
16 | SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a
17 |
18 | PODFILE CHECKSUM: 6ecab50b368fd719f75735e4d61e03b42a41166e
19 |
20 | COCOAPODS: 1.9.3
21 |
--------------------------------------------------------------------------------
/Tests/AquamanTests/AquamanTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import Aquaman
3 |
4 | final class AquamanTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertEqual(Aquaman().text, "Hello, World!")
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "Aquaman",
8 | platforms: [.iOS(.v9)],
9 | products: [
10 | .library(
11 | name: "Aquaman",
12 | targets: ["Aquaman"]),
13 | ],
14 | targets: [
15 | .target(
16 | name: "Aquaman",
17 | path: "./Aquaman/Aquaman")
18 | ]
19 | )
20 |
--------------------------------------------------------------------------------
/Aquaman-Demo/TheFlashViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TheFlashViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2019/9/5.
6 | // Copyright © 2019 bawn. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Aquaman
11 |
12 | class TheFlashViewController: UIViewController, AquamanChildViewController {
13 |
14 | @IBOutlet weak var scrollView: UIScrollView!
15 |
16 | func aquamanChildScrollView() -> UIScrollView {
17 | return scrollView
18 | }
19 |
20 | override func viewDidLoad() {
21 | super.viewDidLoad()
22 | scrollView.contentInset = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 0)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Aquaman.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "Aquaman"
4 | s.version = "0.1.2"
5 | s.summary = "An easy solution to nested scrolling"
6 | s.homepage = "https://github.com/bawn/Aquaman"
7 | s.license = { :type => "MIT", :file => "LICENSE" }
8 | s.authors = { "bawn" => "lc5491137@gmail.com" }
9 | s.swift_version = "4.2"
10 | s.source = { :git => "https://github.com/bawn/Aquaman.git", :tag => s.version.to_s }
11 | s.platform = :ios, '9.0'
12 | s.requires_arc = true
13 | s.public_header_files = "Aquaman/Aquaman/Aquaman.h"
14 | s.source_files = ["Aquaman/Aquaman/*.swift", "Aquaman/Aquaman/Aquaman.h"]
15 | end
--------------------------------------------------------------------------------
/Aquaman.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Aquaman",
6 | "repositoryURL": "https://github.com/bawn/Aquaman.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "f97de875fac31cabfcd8125047069b40665aa160",
10 | "version": "0.1.3"
11 | }
12 | },
13 | {
14 | "package": "Trident",
15 | "repositoryURL": "https://github.com/bawn/Trident.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "2eed75e69815da6fc28b05c91cd642bca1c40610",
19 | "version": "0.7.0"
20 | }
21 | }
22 | ]
23 | },
24 | "version": 1
25 | }
26 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Aquaman-DemoUITests/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 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Bawn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquamanChildViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquamanChildViewController.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2019/1/7.
6 | // Copyright © 2019 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | public protocol AquamanChildViewController where Self: UIViewController {
30 | func aquamanChildScrollView() -> UIScrollView
31 | }
32 |
--------------------------------------------------------------------------------
/Aquaman-DemoUITests/Aquaman_DemoUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Aquaman_DemoUITests.swift
3 | // Aquaman-DemoUITests
4 | //
5 | // Created by bawn on 2019/12/27.
6 | // Copyright © 2019 bawn. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class Aquaman_DemoUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 |
16 | // In UI tests it is usually best to stop immediately when a failure occurs.
17 | continueAfterFailure = false
18 |
19 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
20 | }
21 |
22 | override func tearDown() {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | }
25 |
26 | func testExample() {
27 | // UI tests must launch the application that they test.
28 | let app = XCUIApplication()
29 | app.launch()
30 |
31 | // Use recording to get started writing UI tests.
32 | // Use XCTAssert and related functions to verify your tests produce the correct results.
33 | }
34 |
35 | func testLaunchPerformance() {
36 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
37 | // This measures how long it takes to launch your application.
38 | measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
39 | XCUIApplication().launch()
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Aquaman-Demo/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 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Aquaman-Demo/HeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HeaderView.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2018/12/26.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | class HeaderView: UIView {
29 |
30 | override init(frame: CGRect) {
31 | super.init(frame: frame)
32 | backgroundColor = .cyan
33 | }
34 |
35 | required init?(coder aDecoder: NSCoder) {
36 | super.init(coder: aDecoder)
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/Aquaman.h:
--------------------------------------------------------------------------------
1 | //
2 | // Aquaman.h
3 | // Aquaman
4 | //
5 | // Created by bawn on 2019/1/7.
6 | // Copyright © 2019 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | #import
27 |
28 | //! Project version number for Aquaman.
29 | FOUNDATION_EXPORT double AquamanVersionNumber;
30 |
31 | //! Project version string for Aquaman.
32 | FOUNDATION_EXPORT const unsigned char AquamanVersionString[];
33 |
34 | // In this header, you should import all the public headers of your framework using statements like #import
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 | *.xcuserstate
9 |
10 | ## Various settings
11 | *.pbxuser
12 | !default.pbxuser
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata/
20 |
21 | ## Other
22 | *.moved-aside
23 | *.xccheckout
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 | *.dSYM.zip
30 | *.dSYM
31 |
32 | ## Playgrounds
33 | timeline.xctimeline
34 | playground.xcworkspace
35 |
36 | # Swift Package Manager
37 | #
38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
39 | # Packages/
40 | # Package.pins
41 | # Package.resolved
42 | .build/
43 |
44 | # CocoaPods
45 | #
46 | # We recommend against adding the Pods directory to your .gitignore. However
47 | # you should judge for yourself, the pros and cons are mentioned at:
48 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
49 | #
50 | Pods/
51 |
52 | # Carthage
53 | #
54 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
55 | # Carthage/Checkouts
56 |
57 | Carthage/Build
58 |
59 | # fastlane
60 | #
61 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
62 | # screenshots whenever they are needed.
63 | # For more information about the recommended setup visit:
64 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
65 |
66 | fastlane/report.xml
67 | fastlane/Preview.html
68 | fastlane/screenshots/**/*.png
69 | fastlane/test_output
70 | .DS_Store
71 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquamanContainView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquamanContainView.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/12.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | class AquamanContainView: UIView {
29 | weak var viewController: (UIViewController & AquamanChildViewController)?
30 | var isEmpty: Bool {
31 | return subviews.isEmpty
32 | }
33 |
34 | func displayingIn(view: UIView, containView: UIView) -> Bool {
35 | let convertedFrame = containView.convert(frame, to: view)
36 | return view.frame.intersects(convertedFrame)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Aquaman-Demo/Base.lproj/LaunchScreen.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 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/UIViewController+Additional.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+Additional.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/12.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | extension UIViewController {
30 |
31 | public var amPageViewContoller: AquamanPageViewController? {
32 | return parent as? AquamanPageViewController
33 | }
34 |
35 | func clearFromParent() {
36 | willMove(toParent: nil)
37 | beginAppearanceTransition(false, animated: false)
38 | view.removeFromSuperview()
39 | endAppearanceTransition()
40 | removeFromParent()
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/NSCache+Additional.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSCache+Additional.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/12.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | extension NSCache where KeyType == NSString, ObjectType == UIViewController {
30 |
31 | subscript(index: Int) -> UIViewController? {
32 | get {
33 | return object(forKey: "\(index)" as NSString)
34 | }
35 | set {
36 | guard let newValue = newValue
37 | , self[index] != newValue else {
38 | return
39 | }
40 | setObject(newValue, forKey: "\(index)" as NSString)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Aquaman-Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Aquaman-Demo/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2019/1/11.
6 | // Copyright © 2019 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | class ViewController: UITableViewController {
29 |
30 | override func viewDidLoad() {
31 | super.viewDidLoad()
32 | }
33 |
34 | override func viewWillAppear(_ animated: Bool) {
35 | super.viewWillAppear(animated)
36 | navigationController?.setNavigationBarHidden(false, animated: animated)
37 | }
38 |
39 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
40 | guard let pageViewController = segue.destination as? PageViewController
41 | , let cell = sender as? UITableViewCell
42 | , let indexPath = tableView.indexPath(for: cell) else {
43 | return
44 | }
45 | pageViewController.indexPath = indexPath
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/UIScrollView+Additional.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIScrollView+Additional.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/12.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 |
30 | private struct AssociatedKeys {
31 | static var AMIsCanScroll = "AMIsCanScroll"
32 | static var AMOriginOffset = "AMOriginOffset"
33 | }
34 |
35 | extension UIScrollView {
36 | internal var am_isCanScroll: Bool {
37 | get {
38 | return (objc_getAssociatedObject(self, &AssociatedKeys.AMIsCanScroll) as? Bool) ?? false
39 | }
40 | set {
41 | objc_setAssociatedObject(self, &AssociatedKeys.AMIsCanScroll, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
42 | }
43 | }
44 |
45 | internal var am_originOffset: CGPoint? {
46 | get {
47 | return objc_getAssociatedObject(self, &AssociatedKeys.AMOriginOffset) as? CGPoint
48 | }
49 | set {
50 | guard am_originOffset == nil else {
51 | return
52 | }
53 | objc_setAssociatedObject(self, &AssociatedKeys.AMOriginOffset, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Aquaman-Demo/WonderWomanViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WonderWomanViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2018/12/10.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 | import Aquaman
28 |
29 | class WonderWomanViewController: UIViewController, AquamanChildViewController {
30 |
31 | @IBOutlet weak var tableView: UITableView!
32 | override func viewDidLoad() {
33 | super.viewDidLoad()
34 | }
35 |
36 | func aquamanChildScrollView() -> UIScrollView {
37 | return tableView
38 | }
39 | }
40 |
41 | extension WonderWomanViewController: UITableViewDelegate, UITableViewDataSource {
42 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
43 | return 40
44 | }
45 |
46 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
47 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
48 | cell.textLabel?.text = "\(type(of: self))" + "-" + "\(indexPath.row)"
49 | return cell
50 | }
51 |
52 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
53 | navigationController?.popViewController(animated: true)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquaMainScrollView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquaScrollView.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/7.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | public class AquaMainScrollView: UIScrollView, UIGestureRecognizerDelegate {
29 | var headerViewHeight: CGFloat = 0.0
30 | var menuViewHeight: CGFloat = 0.0
31 |
32 | public override init(frame: CGRect) {
33 | super.init(frame: .zero)
34 | scrollsToTop = true
35 | backgroundColor = .white
36 | showsHorizontalScrollIndicator = false
37 | showsVerticalScrollIndicator = false
38 | translatesAutoresizingMaskIntoConstraints = false
39 | }
40 |
41 | required init?(coder: NSCoder) {
42 | super.init(coder: coder)
43 | }
44 |
45 | public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
46 |
47 | guard let scrollView = gestureRecognizer.view as? UIScrollView else {
48 | return false
49 | }
50 |
51 | let offsetY = headerViewHeight + menuViewHeight
52 | let contentSize = scrollView.contentSize
53 | let targetRect = CGRect(x: 0,
54 | y: offsetY - UIApplication.shared.statusBarFrame.height,
55 | width: contentSize.width,
56 | height: contentSize.height - offsetY)
57 |
58 | let currentPoint = gestureRecognizer.location(in: self)
59 | return targetRect.contains(currentPoint)
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman.xcodeproj/xcshareddata/xcschemes/Aquaman.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Aquaman-Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2019/1/7.
6 | // Copyright © 2019 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | @UIApplicationMain
29 | class AppDelegate: UIResponder, UIApplicationDelegate {
30 |
31 | var window: UIWindow?
32 |
33 |
34 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
35 | // Override point for customization after application launch.
36 | return true
37 | }
38 |
39 | func applicationWillResignActive(_ application: UIApplication) {
40 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
41 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
42 | }
43 |
44 | func applicationDidEnterBackground(_ application: UIApplication) {
45 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
47 | }
48 |
49 | func applicationWillEnterForeground(_ application: UIApplication) {
50 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
51 | }
52 |
53 | func applicationDidBecomeActive(_ application: UIApplication) {
54 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
55 | }
56 |
57 | func applicationWillTerminate(_ application: UIApplication) {
58 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
59 | }
60 |
61 |
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/Aquaman-Demo/BatmanViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BatmanViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2018/12/28.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 | import Aquaman
28 |
29 | class BatmanViewController: UIViewController, AquamanChildViewController {
30 | @IBOutlet weak var collectionView: UICollectionView!
31 |
32 | override func viewDidLoad() {
33 | super.viewDidLoad()
34 |
35 | collectionView.alwaysBounceVertical = true
36 | }
37 |
38 | func aquamanChildScrollView() -> UIScrollView {
39 | return collectionView
40 | }
41 |
42 | }
43 |
44 | extension BatmanViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
45 |
46 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
47 | return 4
48 | }
49 |
50 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
51 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
52 | return cell
53 | }
54 |
55 |
56 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
57 | return 12
58 | }
59 |
60 |
61 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
62 | return 12
63 | }
64 |
65 |
66 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
67 | return UIEdgeInsets(top: 24, left: 12, bottom: 12, right: 12)
68 | }
69 |
70 |
71 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
72 | let width = floor((collectionView.bounds.width - 12.0 * 3.0) * 0.5)
73 | return CGSize(width: width, height: width)
74 | }
75 |
76 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
77 | navigationController?.popViewController(animated: true)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Aquaman-Demo/SupermanViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SupermanViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2018/12/8.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 | import Aquaman
28 |
29 | class SupermanViewController: UIViewController, AquamanChildViewController {
30 | @IBOutlet weak var tableView: UITableView!
31 |
32 | override func viewDidLoad() {
33 | super.viewDidLoad()
34 |
35 | tableView.contentInset = UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0)
36 | }
37 |
38 | func aquamanChildScrollView() -> UIScrollView {
39 | return tableView
40 | }
41 | }
42 |
43 |
44 | extension SupermanViewController: UITableViewDelegate, UITableViewDataSource {
45 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
46 | return 20
47 | }
48 |
49 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
50 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
51 | if indexPath.row == 0 {
52 | cell.textLabel?.text = "Update head view height"
53 | } else if indexPath.row == 1 {
54 | cell.textLabel?.text = "Set select"
55 | } else {
56 | cell.textLabel?.text = "Title"
57 | }
58 | return cell
59 | }
60 |
61 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
62 | tableView.deselectRow(at: indexPath, animated: true)
63 |
64 | guard let pageViewController = parent as? PageViewController else {
65 | return
66 | }
67 |
68 | if indexPath.row == 0 {
69 |
70 | tableView.isUserInteractionEnabled = false
71 | var array = [250, 80, 150, 0]
72 | let headerViewHeight = pageViewController.headerViewHeight
73 | array.removeAll(where: {$0 == Int(headerViewHeight)})
74 | pageViewController.headerViewHeight = CGFloat(array.randomElement()!)
75 |
76 | pageViewController.updateHeaderViewHeight(animated: true,
77 | duration: 0.25) { (finish) in
78 | tableView.isUserInteractionEnabled = true
79 | }
80 | } else if indexPath.row == 1 {
81 |
82 | pageViewController.setSelect(index: pageViewController.currentIndex + 1,
83 | animation: [true, false].randomElement()!)
84 | } else {
85 | navigationController?.popViewController(animated: true)
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Aquaman-Demo.xcodeproj/xcshareddata/xcschemes/Aquaman-Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
64 |
70 |
71 |
72 |
73 |
79 |
81 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/README-EN.md:
--------------------------------------------------------------------------------
1 | # Aquaman
2 |
3 | 
4 | 
5 | 
6 | [](https://www.apple.com/nl/ios/)
7 | [](https://developer.apple.com/swift/)
8 |
9 | A pure-Swift library for nested display of horizontal and vertical scrolling views.
10 |
11 | 
12 |
13 | ## Requirements
14 |
15 | - iOS 9.0+
16 | - Swift 4.2+
17 | - Xcode 10+
18 |
19 |
20 |
21 | ## Installation
22 |
23 | #### [CocoaPods](http://cocoapods.org/) (recommended)
24 |
25 | ```
26 | use_frameworks!
27 |
28 | pod 'Aquaman'
29 | ```
30 |
31 | ## Usage
32 |
33 | First make sure to import the framework:
34 |
35 | ```
36 | import Aquaman
37 | ```
38 |
39 | Basically, we just need to provide the list of child view controllers to show. Then call some necessary methods.
40 |
41 | Let's see the steps to do this:
42 |
43 | #### Create a AquamanPageViewController subclass
44 |
45 | ```swift
46 | import Aquaman
47 |
48 | class PageViewController: AquamanPageViewController {
49 | // ...
50 | }
51 | ```
52 |
53 | #### Provide the view controllers that will appear embedded into the AquamanPageViewController
54 |
55 | ```swift
56 | override func numberOfViewControllers(in pageController: AquamanPageViewController) -> Int {
57 | return count
58 | }
59 |
60 | override func pageController(_ pageController: AquamanPageViewController, viewControllerAt index: Int) -> (UIViewController & AquamanChildViewController) {
61 | // ...
62 | return viewController
63 | }
64 |
65 | ```
66 |
67 | Every UIViewController that will appear within the AquamanPageViewController should conform to `AquamanChildViewController` by implementing `func aquamanChildScrollView() -> UIScrollView`
68 |
69 | ```swift
70 | import Aquaman
71 | class ChildViewController: UIViewController, AquamanChildViewController {
72 |
73 | @IBOutlet weak var tableView: UITableView!
74 | func aquamanChildScrollView() -> UIScrollView {
75 | return tableView
76 | }
77 | // ...
78 | }
79 | ```
80 |
81 |
82 |
83 | #### Provide the headerView and headerView height
84 |
85 | ```swift
86 | override func headerViewFor(_ pageController: AquamanPageViewController) -> UIView {
87 | return HeaderView()
88 | }
89 |
90 | override func headerViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
91 | return headerViewHeight
92 | }
93 | ```
94 |
95 | #### Provide the menuView and menuView height
96 |
97 | ```swift
98 | override func menuViewFor(_ pageController: AquamanPageViewController) -> UIView {
99 | return menuView
100 | }
101 |
102 | override func menuViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
103 | return menuViewHeight
104 | }
105 | ```
106 |
107 | #### Update menuView's layout when content scroll view did scroll and check state when viewController did end isplay
108 |
109 | ```swift
110 | override func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidScroll scrollView: UIScrollView) {
111 | menuView.updateLayout(scrollView)
112 | }
113 |
114 | override func pageController(_ pageController: AquamanPageViewController, didDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
115 | menuView.checkState(animation: true)
116 | }
117 | ```
118 |
119 |
120 |
121 | ## Examples
122 |
123 | Follow these 4 steps to run Example project:
124 |
125 | 1. Clone Aquaman repository
126 | 2. Run the `pod install` command
127 | 3. Open Aquaman workspace
128 | 4. Run the Aquaman-Demo project.
129 |
130 | ### License
131 |
132 | Aquaman is released under the MIT license. See LICENSE for details.
133 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Aquaman
2 |
3 | 
4 | 
5 | 
6 | [](https://www.apple.com/nl/ios/)
7 | [](https://developer.apple.com/swift/)
8 |
9 | 类似于淘票票首页,抖音、简书个人主页的嵌套滚动库
10 |
11 | 
12 |
13 | ## Requirements
14 |
15 | - iOS 9.0+
16 | - Swift 4.2+
17 | - Xcode 10+
18 |
19 |
20 |
21 | ## Installation
22 |
23 | #### [CocoaPods](http://cocoapods.org/)
24 |
25 | ```
26 | use_frameworks!
27 |
28 | pod 'Aquaman'
29 | ```
30 |
31 | #### Swift Package Manager
32 | Add the following dependency to your Package.swift manifest:
33 |
34 | ```
35 | .package(url: "https://github.com/bawn/Aquaman.git", .branch("master")),
36 | ```
37 |
38 | ## Usage
39 |
40 | [English documentation](https://github.com/bawn/Aquaman/blob/master/README-EN.md)
41 |
42 | 首先需要导入 Aquaman
43 |
44 | ```
45 | import Aquaman
46 | ```
47 |
48 |
49 |
50 | #### 创建 AquamanPageViewController 子类
51 |
52 | ```swift
53 | import Aquaman
54 |
55 | class PageViewController: AquamanPageViewController {
56 | // ...
57 | }
58 | ```
59 |
60 | #### 重写以下协议方法以提供 viewController 和相应的数量
61 |
62 | ```swift
63 | override func numberOfViewControllers(in pageController: AquamanPageViewController) -> Int {
64 | return count
65 | }
66 |
67 | override func pageController(_ pageController: AquamanPageViewController, viewControllerAt index: Int) -> (UIViewController & AquamanChildViewController) {
68 | // ...
69 | return viewController
70 | }
71 |
72 | ```
73 |
74 | 注意: 所提供的 viewController 必须都遵守 `AquamanChildViewController` 协议,并实现 `func aquamanChildScrollView() -> UIScrollView` 方法
75 |
76 | ```swift
77 | import Aquaman
78 | class ChildViewController: UIViewController, AquamanChildViewController {
79 |
80 | @IBOutlet weak var tableView: UITableView!
81 | func aquamanChildScrollView() -> UIScrollView {
82 | return tableView
83 | }
84 | // ...
85 | }
86 | ```
87 |
88 |
89 |
90 | #### 重写以下协议方法以提供 headerView 及其高度
91 |
92 | ```swift
93 | override func headerViewFor(_ pageController: AquamanPageViewController) -> UIView {
94 | return HeaderView()
95 | }
96 |
97 | override func headerViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
98 | return headerViewHeight
99 | }
100 | ```
101 |
102 | #### 重写以下协议方法以提供 menuView 及其高度
103 |
104 | ```swift
105 | override func menuViewFor(_ pageController: AquamanPageViewController) -> UIView {
106 | return menuView
107 | }
108 |
109 | override func menuViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
110 | return menuViewHeight
111 | }
112 | ```
113 |
114 | Aquaman 采用的是 menuView 和主体功能分离的设计,以满足 menuView 有时候需要深度定制的需求,所以 menuView 需要开发者自己实现,当然这里也提供了现成的 menuView 库:[Trident](https://github.com/bawn/Trident)
115 |
116 | #### 更新 menuView 的布局
117 |
118 | ```swift
119 | override func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidScroll scrollView: UIScrollView) {
120 | menuView.updateLayout(scrollView)
121 | }
122 |
123 | override func pageController(_ pageController: AquamanPageViewController, didDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
124 | menuView.checkState(animation: true)
125 | }
126 | ```
127 |
128 | 由于 menuView 和 pageController 不存在强关联关系,所以在滚动的时候需要更新 menuView 布局,在显示相应的 viewController 的时候需要检查 menuView 的状态,具体参考 demo
129 |
130 | ## Examples
131 |
132 | Follow these 4 steps to run Example project:
133 |
134 | 1. Clone Aquaman repository
135 | 2. Run the `pod install` command
136 | 3. Open Aquaman workspace
137 | 4. Run the Aquaman-Demo project.
138 |
139 | ### License
140 |
141 | Aquaman is released under the MIT license. See LICENSE for details.
142 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquamanProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquamanProtocol.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/7.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | protocol AMPageControllerDataSource: class {
30 |
31 | func pageController(_ pageController: AquamanPageViewController, viewControllerAt index: Int) -> (UIViewController & AquamanChildViewController)
32 | func numberOfViewControllers(in pageController: AquamanPageViewController) -> Int
33 | func headerViewFor(_ pageController: AquamanPageViewController) -> UIView
34 | func headerViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat
35 | func menuViewFor(_ pageController: AquamanPageViewController) -> UIView
36 | func menuViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat
37 | func menuViewPinHeightFor(_ pageController: AquamanPageViewController) -> CGFloat
38 |
39 | /// The index of the controller displayed by default. You should have menview ready before setting this value
40 | ///
41 | /// - Parameter pageController: AquamanPageViewController
42 | /// - Returns: Int
43 | func originIndexFor(_ pageController: AquamanPageViewController) -> Int
44 | }
45 |
46 | protocol AMPageControllerDelegate: class {
47 |
48 | /// Any offset changes in pageController's mainScrollView
49 | ///
50 | /// - Parameters:
51 | /// - pageController: AquamanPageViewController
52 | /// - scrollView: mainScrollView
53 | func pageController(_ pageController: AquamanPageViewController, mainScrollViewDidScroll scrollView: UIScrollView)
54 |
55 |
56 | /// Method call when contentScrollView did end scroll
57 | ///
58 | /// - Parameters:
59 | /// - pageController: AquamanPageViewController
60 | /// - scrollView: contentScrollView
61 | func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidEndScroll scrollView: UIScrollView)
62 |
63 |
64 | /// Any offset changes in pageController's contentScrollView
65 | ///
66 | /// - Parameters:
67 | /// - pageController: AquamanPageViewController
68 | /// - scrollView: contentScrollView
69 | func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidScroll scrollView: UIScrollView)
70 |
71 | /// Method call when viewController will cache
72 | ///
73 | /// - Parameters:
74 | /// - pageController: AquamanPageViewController
75 | /// - viewController: target viewController
76 | /// - index: target viewController's index
77 | func pageController(_ pageController: AquamanPageViewController, willCache viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int)
78 |
79 |
80 | /// Method call when viewController will display
81 | ///
82 | /// - Parameters:
83 | /// - pageController: AquamanPageViewController
84 | /// - viewController: target viewController
85 | /// - index: target viewController's index
86 | func pageController(_ pageController: AquamanPageViewController, willDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int)
87 |
88 |
89 | /// Method call when viewController did display
90 | ///
91 | /// - Parameters:
92 | /// - pageController: AquamanPageViewController
93 | /// - viewController: target viewController
94 | /// - index: target viewController's index
95 | func pageController(_ pageController: AquamanPageViewController, didDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int)
96 |
97 |
98 | /// Method call when menuView is adsorption
99 | ///
100 | /// - Parameters:
101 | /// - pageController: AquamanPageViewController
102 | /// - isAdsorption: is adsorption
103 | func pageController(_ pageController: AquamanPageViewController, menuView isAdsorption: Bool)
104 |
105 |
106 | /// Asks the delegate for the margins to apply to content.
107 | /// - Parameter pageController: AquamanPageViewController
108 | func contentInsetFor(_ pageController: AquamanPageViewController) -> UIEdgeInsets
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquamanPageViewController+Additional.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquamanPageViewController.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/7.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 | import UIKit
28 |
29 | extension AquamanPageViewController {
30 | public func updateHeaderViewHeight(animated: Bool = false,
31 | duration: TimeInterval = 0.25,
32 | completion: ((Bool) -> Void)? = nil) {
33 |
34 | headerViewHeight = headerViewHeightFor(self)
35 | sillValue = headerViewHeight - menuViewPinHeight
36 |
37 | mainScrollView.headerViewHeight = headerViewHeight
38 | headerViewConstraint?.constant = headerViewHeight
39 |
40 | var manualHandel = false
41 | if mainScrollView.contentOffset.y < sillValue {
42 | currentChildScrollView?.contentOffset = currentChildScrollView?.am_originOffset ?? .zero
43 | currentChildScrollView?.am_isCanScroll = false
44 | mainScrollView.am_isCanScroll = true
45 | manualHandel = true
46 | } else if mainScrollView.contentOffset.y == sillValue {
47 | mainScrollView.am_isCanScroll = false
48 | manualHandel = true
49 | }
50 | let isAdsorption = (headerViewHeight <= 0.0) ? true : !mainScrollView.am_isCanScroll
51 | if animated {
52 | UIView.animate(withDuration: duration, animations: {
53 | self.mainScrollView.layoutIfNeeded()
54 | if manualHandel {
55 | self.pageController(self, menuView: isAdsorption)
56 | }
57 | }) { (finish) in
58 | completion?(finish)
59 | }
60 | } else {
61 | self.pageController(self, menuView: isAdsorption)
62 | completion?(true)
63 | }
64 | }
65 |
66 | public func setSelect(index: Int, animation: Bool) {
67 | let offset = CGPoint(x: contentScrollView.bounds.width * CGFloat(index),
68 | y: contentScrollView.contentOffset.y)
69 | contentScrollView.setContentOffset(offset, animated: animation)
70 | if animation == false {
71 | contentScrollViewDidEndScroll(contentScrollView)
72 | }
73 | }
74 |
75 | public func scrollToTop(_ animation: Bool) {
76 | currentChildScrollView?.setContentOffset(currentChildScrollView?.am_originOffset ?? .zero, animated: true)
77 | mainScrollView.am_isCanScroll = true
78 | mainScrollView.setContentOffset(.zero, animated: animation)
79 | }
80 |
81 | public func reloadData() {
82 | mainScrollView.isUserInteractionEnabled = false
83 | clear()
84 | obtainDataSource()
85 | updateOriginContent()
86 | setupDataSource()
87 | view.layoutIfNeeded()
88 | if originIndex > 0 {
89 | setSelect(index: originIndex, animation: false)
90 | } else {
91 | showChildViewContoller(at: originIndex)
92 | didDisplayViewController(at: originIndex)
93 | }
94 | mainScrollView.isUserInteractionEnabled = true
95 | }
96 | }
97 |
98 |
99 | extension AquamanPageViewController: UIScrollViewDelegate {
100 |
101 | public func scrollViewDidScroll(_ scrollView: UIScrollView) {
102 |
103 | if scrollView == mainScrollView {
104 | pageController(self, mainScrollViewDidScroll: scrollView)
105 | let offsetY = scrollView.contentOffset.y
106 | if offsetY >= sillValue {
107 | scrollView.contentOffset = CGPoint(x: 0, y: sillValue)
108 | currentChildScrollView?.am_isCanScroll = true
109 | scrollView.am_isCanScroll = false
110 | pageController(self, menuView: !scrollView.am_isCanScroll)
111 | } else {
112 |
113 | if scrollView.am_isCanScroll == false {
114 | pageController(self, menuView: true)
115 | scrollView.contentOffset = CGPoint(x: 0, y: sillValue)
116 | } else {
117 | pageController(self, menuView: false)
118 | }
119 | }
120 | } else {
121 | pageController(self, contentScrollViewDidScroll: scrollView)
122 | layoutChildViewControlls()
123 | }
124 | }
125 |
126 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
127 | if scrollView == contentScrollView {
128 | mainScrollView.isScrollEnabled = false
129 | }
130 | }
131 |
132 |
133 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
134 | if scrollView == contentScrollView {
135 | mainScrollView.isScrollEnabled = true
136 | if decelerate == false {
137 | contentScrollViewDidEndScroll(contentScrollView)
138 | }
139 | }
140 | }
141 |
142 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
143 | if scrollView == contentScrollView {
144 | contentScrollViewDidEndScroll(contentScrollView)
145 | }
146 | }
147 |
148 |
149 | public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
150 | if scrollView == contentScrollView {
151 | contentScrollViewDidEndScroll(contentScrollView)
152 | }
153 | }
154 |
155 | public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
156 | guard scrollView == mainScrollView else {
157 | return false
158 | }
159 | currentChildScrollView?.setContentOffset(currentChildScrollView?.am_originOffset ?? .zero, animated: true)
160 | return true
161 | }
162 |
163 | }
164 |
165 | extension AquamanPageViewController {
166 | internal func childScrollViewDidScroll(_ scrollView: UIScrollView) {
167 | if scrollView.am_isCanScroll == false {
168 | scrollView.contentOffset = scrollView.am_originOffset ?? .zero
169 | }
170 | let offsetY = scrollView.contentOffset.y
171 | if offsetY <= (scrollView.am_originOffset ?? .zero).y {
172 | scrollView.contentOffset = scrollView.am_originOffset ?? .zero
173 | scrollView.am_isCanScroll = false
174 | mainScrollView.am_isCanScroll = true
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/Aquaman-Demo/PageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PageViewController.swift
3 | // Aquaman-Demo
4 | //
5 | // Created by bawn on 2018/12/8.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 | import MJRefresh
28 | import Aquaman
29 | import Trident
30 |
31 | class PageViewController: AquamanPageViewController {
32 |
33 | var indexPath = IndexPath(row: 0, section: 0)
34 | lazy var menuView: TridentMenuView = {
35 | let view = TridentMenuView(parts:
36 | .normalTextColor(UIColor.gray),
37 | .selectedTextColor(UIColor.blue),
38 | .normalTextFont(UIFont.systemFont(ofSize: 15.0)),
39 | .selectedTextFont(UIFont.systemFont(ofSize: 15.0, weight: .medium)),
40 | .switchStyle(.line),
41 | .sliderStyle(
42 | SliderViewStyle(parts:
43 | .backgroundColor(.blue),
44 | .height(3.0),
45 | .cornerRadius(1.5),
46 | .position(.bottom),
47 | .extraWidth(indexPath.row == 0 ? -10.0 : 4.0),
48 | .shape(indexPath.row == 0 ? .line : .triangle)
49 | )
50 | ),
51 | .bottomLineStyle(
52 | BottomLineViewStyle(parts:
53 | .hidden(indexPath.row == 0 ? false : true)
54 | )
55 | )
56 | )
57 | view.delegate = self
58 | return view
59 | }()
60 |
61 | private let headerView = HeaderView()
62 | private lazy var count = indexPath.row == 0 ? 3 : 0
63 | var headerViewHeight: CGFloat = 200.0
64 | private var menuViewHeight: CGFloat = 54.0
65 |
66 | override func viewDidLoad() {
67 | super.viewDidLoad()
68 |
69 | menuView.contentInset = UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 24)
70 | mainScrollView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(updateData))
71 | switch indexPath.row {
72 | case 0:
73 | menuView.titles = ["Superman", "Batman", "Wonder Woman"]
74 | case 1:
75 | headerView.isHidden = true
76 | menuView.isHidden = true
77 | mainScrollView.mj_header?.beginRefreshing()
78 | default:
79 | break
80 | }
81 | }
82 |
83 | @objc func updateData() {
84 | DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
85 | self.headerView.isHidden = false
86 | self.menuView.isHidden = false
87 | self.menuView.titles = ["Superman", "Batman", "Wonder Woman", "The Flash"]
88 | self.count = self.menuView.titles.count
89 | self.headerViewHeight = 120.0
90 | self.menuViewHeight = 54.0
91 | self.reloadData()
92 | if self.mainScrollView.mj_header?.isRefreshing ?? false {
93 | self.mainScrollView.mj_header?.endRefreshing()
94 | }
95 | }
96 | }
97 |
98 | override func viewWillAppear(_ animated: Bool) {
99 | super.viewWillAppear(animated)
100 | switch indexPath.row {
101 | case 0:
102 | navigationController?.setNavigationBarHidden(true, animated: animated)
103 | default:
104 | break
105 | }
106 | }
107 |
108 | override func headerViewFor(_ pageController: AquamanPageViewController) -> UIView {
109 | return headerView
110 | }
111 |
112 | override func headerViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
113 | return headerViewHeight
114 | }
115 |
116 | override func numberOfViewControllers(in pageController: AquamanPageViewController) -> Int {
117 | return count
118 | }
119 |
120 | override func pageController(_ pageController: AquamanPageViewController, viewControllerAt index: Int) -> (UIViewController & AquamanChildViewController) {
121 | let storyboard = UIStoryboard(name: "Main", bundle: nil)
122 | if index == 0 {
123 | return storyboard.instantiateViewController(withIdentifier: "SupermanViewController") as! SupermanViewController
124 | } else if index == 1 {
125 | return storyboard.instantiateViewController(withIdentifier: "BatmanViewController") as! BatmanViewController
126 | } else if index == 2 {
127 | return storyboard.instantiateViewController(withIdentifier: "WonderWomanViewController") as! WonderWomanViewController
128 | } else {
129 | return storyboard.instantiateViewController(withIdentifier: "TheFlashViewController") as! TheFlashViewController
130 | }
131 | }
132 |
133 | // 默认显示的 ViewController 的 index
134 | override func originIndexFor(_ pageController: AquamanPageViewController) -> Int {
135 | switch indexPath.row {
136 | case 0:
137 | return 0
138 | case 1:
139 | return 1
140 | default:
141 | return 0
142 | }
143 | }
144 |
145 | override func menuViewFor(_ pageController: AquamanPageViewController) -> UIView {
146 | return menuView
147 | }
148 |
149 | override func menuViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
150 | return menuViewHeight
151 | }
152 |
153 | override func menuViewPinHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
154 | return 0.0
155 | }
156 |
157 |
158 | override func pageController(_ pageController: AquamanPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) {
159 |
160 | }
161 |
162 | override func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidScroll scrollView: UIScrollView) {
163 | menuView.updateLayout(scrollView)
164 | }
165 |
166 | override func pageController(_ pageController: AquamanPageViewController,
167 | contentScrollViewDidEndScroll scrollView: UIScrollView) {
168 |
169 | }
170 |
171 | override func pageController(_ pageController: AquamanPageViewController, menuView isAdsorption: Bool) {
172 | menuView.backgroundColor = isAdsorption ? .red : .white
173 | }
174 |
175 |
176 | override func pageController(_ pageController: AquamanPageViewController, willDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
177 | }
178 |
179 | override func pageController(_ pageController: AquamanPageViewController, didDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
180 | menuView.checkState(animation: true)
181 | }
182 |
183 | override func contentInsetFor(_ pageController: AquamanPageViewController) -> UIEdgeInsets {
184 | switch indexPath.row {
185 | case 0:
186 | return UIEdgeInsets(top: -UIApplication.shared.statusBarFrame.height, left: 0, bottom: 0, right: 0)
187 | case 1:
188 | return .zero
189 | default:
190 | return .zero
191 | }
192 | }
193 | }
194 |
195 |
196 | extension PageViewController: TridentMenuViewDelegate {
197 | func menuView(_ menuView: TridentMenuView, didSelectedItemAt index: Int) {
198 | guard index < count else {
199 | return
200 | }
201 | switch indexPath.row {
202 | case 0:
203 | setSelect(index: index, animation: true)
204 | case 1:
205 | setSelect(index: index, animation: false)
206 | default:
207 | break
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0748581C6F98F9B286749D5B /* libPods-Aquaman.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 17D7F62C8EA97B4F4AA45B89 /* libPods-Aquaman.a */; };
11 | DF0DDABC21E35C440086663E /* Aquaman.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0DDABA21E35C440086663E /* Aquaman.h */; settings = {ATTRIBUTES = (Public, ); }; };
12 | DF744C3C239F4F1F003A8EB4 /* AquamanProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF744C3B239F4F1F003A8EB4 /* AquamanProtocol.swift */; };
13 | DF7F9F0C21E37969000F4317 /* UIViewController+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0521E37968000F4317 /* UIViewController+Additional.swift */; };
14 | DF7F9F0D21E37969000F4317 /* UIScrollView+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0621E37968000F4317 /* UIScrollView+Additional.swift */; };
15 | DF7F9F0E21E37969000F4317 /* AquamanContainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0721E37968000F4317 /* AquamanContainView.swift */; };
16 | DF7F9F0F21E37969000F4317 /* AquaMainScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0821E37968000F4317 /* AquaMainScrollView.swift */; };
17 | DF7F9F1021E37969000F4317 /* AquamanChildViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */; };
18 | DF7F9F1121E37969000F4317 /* NSCache+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0A21E37968000F4317 /* NSCache+Additional.swift */; };
19 | DF7F9F1221E37969000F4317 /* AquamanPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */; };
20 | DFFEA09D24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXFileReference section */
24 | 17D7F62C8EA97B4F4AA45B89 /* libPods-Aquaman.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Aquaman.a"; sourceTree = BUILT_PRODUCTS_DIR; };
25 | 4E2ADF93CCF5BBBB14110499 /* Pods-Aquaman.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aquaman.debug.xcconfig"; path = "Target Support Files/Pods-Aquaman/Pods-Aquaman.debug.xcconfig"; sourceTree = ""; };
26 | 6DFF8C1B0CD3525BDCE645C5 /* Pods-Aquaman.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aquaman.release.xcconfig"; path = "Target Support Files/Pods-Aquaman/Pods-Aquaman.release.xcconfig"; sourceTree = ""; };
27 | DF0DDAB721E35C440086663E /* Aquaman.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Aquaman.framework; sourceTree = BUILT_PRODUCTS_DIR; };
28 | DF0DDABA21E35C440086663E /* Aquaman.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Aquaman.h; sourceTree = ""; };
29 | DF0DDABB21E35C440086663E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
30 | DF744C3B239F4F1F003A8EB4 /* AquamanProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanProtocol.swift; sourceTree = ""; };
31 | DF7F9F0521E37968000F4317 /* UIViewController+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Additional.swift"; sourceTree = ""; };
32 | DF7F9F0621E37968000F4317 /* UIScrollView+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScrollView+Additional.swift"; sourceTree = ""; };
33 | DF7F9F0721E37968000F4317 /* AquamanContainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanContainView.swift; sourceTree = ""; };
34 | DF7F9F0821E37968000F4317 /* AquaMainScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquaMainScrollView.swift; sourceTree = ""; };
35 | DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanChildViewController.swift; sourceTree = ""; };
36 | DF7F9F0A21E37968000F4317 /* NSCache+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCache+Additional.swift"; sourceTree = ""; };
37 | DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanPageViewController.swift; sourceTree = ""; };
38 | DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AquamanPageViewController+Additional.swift"; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | DF0DDAB421E35C440086663E /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | 0748581C6F98F9B286749D5B /* libPods-Aquaman.a in Frameworks */,
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | /* End PBXFrameworksBuildPhase section */
51 |
52 | /* Begin PBXGroup section */
53 | 514AF2F5FB7701F6EF65FBCA /* Frameworks */ = {
54 | isa = PBXGroup;
55 | children = (
56 | 17D7F62C8EA97B4F4AA45B89 /* libPods-Aquaman.a */,
57 | );
58 | name = Frameworks;
59 | sourceTree = "";
60 | };
61 | 8EE780A59AD49E1E96C3E14B /* Pods */ = {
62 | isa = PBXGroup;
63 | children = (
64 | 4E2ADF93CCF5BBBB14110499 /* Pods-Aquaman.debug.xcconfig */,
65 | 6DFF8C1B0CD3525BDCE645C5 /* Pods-Aquaman.release.xcconfig */,
66 | );
67 | name = Pods;
68 | path = ../Pods;
69 | sourceTree = "";
70 | };
71 | DF0DDAAD21E35C440086663E = {
72 | isa = PBXGroup;
73 | children = (
74 | DF0DDAB921E35C440086663E /* Aquaman */,
75 | DF0DDAB821E35C440086663E /* Products */,
76 | 8EE780A59AD49E1E96C3E14B /* Pods */,
77 | 514AF2F5FB7701F6EF65FBCA /* Frameworks */,
78 | );
79 | sourceTree = "";
80 | };
81 | DF0DDAB821E35C440086663E /* Products */ = {
82 | isa = PBXGroup;
83 | children = (
84 | DF0DDAB721E35C440086663E /* Aquaman.framework */,
85 | );
86 | name = Products;
87 | sourceTree = "";
88 | };
89 | DF0DDAB921E35C440086663E /* Aquaman */ = {
90 | isa = PBXGroup;
91 | children = (
92 | DF0DDABA21E35C440086663E /* Aquaman.h */,
93 | DF744C3B239F4F1F003A8EB4 /* AquamanProtocol.swift */,
94 | DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */,
95 | DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */,
96 | DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */,
97 | DF7F9F0821E37968000F4317 /* AquaMainScrollView.swift */,
98 | DF7F9F0721E37968000F4317 /* AquamanContainView.swift */,
99 | DF7F9F0A21E37968000F4317 /* NSCache+Additional.swift */,
100 | DF7F9F0621E37968000F4317 /* UIScrollView+Additional.swift */,
101 | DF7F9F0521E37968000F4317 /* UIViewController+Additional.swift */,
102 | DF0DDABB21E35C440086663E /* Info.plist */,
103 | );
104 | path = Aquaman;
105 | sourceTree = "";
106 | };
107 | /* End PBXGroup section */
108 |
109 | /* Begin PBXHeadersBuildPhase section */
110 | DF0DDAB221E35C440086663E /* Headers */ = {
111 | isa = PBXHeadersBuildPhase;
112 | buildActionMask = 2147483647;
113 | files = (
114 | DF0DDABC21E35C440086663E /* Aquaman.h in Headers */,
115 | );
116 | runOnlyForDeploymentPostprocessing = 0;
117 | };
118 | /* End PBXHeadersBuildPhase section */
119 |
120 | /* Begin PBXNativeTarget section */
121 | DF0DDAB621E35C440086663E /* Aquaman */ = {
122 | isa = PBXNativeTarget;
123 | buildConfigurationList = DF0DDABF21E35C440086663E /* Build configuration list for PBXNativeTarget "Aquaman" */;
124 | buildPhases = (
125 | 12A91B9C704D6696F36D03EA /* [CP] Check Pods Manifest.lock */,
126 | DF0DDAB221E35C440086663E /* Headers */,
127 | DF0DDAB321E35C440086663E /* Sources */,
128 | DF0DDAB421E35C440086663E /* Frameworks */,
129 | DF0DDAB521E35C440086663E /* Resources */,
130 | );
131 | buildRules = (
132 | );
133 | dependencies = (
134 | );
135 | name = Aquaman;
136 | productName = Aquaman;
137 | productReference = DF0DDAB721E35C440086663E /* Aquaman.framework */;
138 | productType = "com.apple.product-type.framework";
139 | };
140 | /* End PBXNativeTarget section */
141 |
142 | /* Begin PBXProject section */
143 | DF0DDAAE21E35C440086663E /* Project object */ = {
144 | isa = PBXProject;
145 | attributes = {
146 | LastUpgradeCheck = 1010;
147 | ORGANIZATIONNAME = bawn;
148 | TargetAttributes = {
149 | DF0DDAB621E35C440086663E = {
150 | CreatedOnToolsVersion = 10.1;
151 | };
152 | };
153 | };
154 | buildConfigurationList = DF0DDAB121E35C440086663E /* Build configuration list for PBXProject "Aquaman" */;
155 | compatibilityVersion = "Xcode 9.3";
156 | developmentRegion = en;
157 | hasScannedForEncodings = 0;
158 | knownRegions = (
159 | en,
160 | Base,
161 | );
162 | mainGroup = DF0DDAAD21E35C440086663E;
163 | productRefGroup = DF0DDAB821E35C440086663E /* Products */;
164 | projectDirPath = "";
165 | projectRoot = "";
166 | targets = (
167 | DF0DDAB621E35C440086663E /* Aquaman */,
168 | );
169 | };
170 | /* End PBXProject section */
171 |
172 | /* Begin PBXResourcesBuildPhase section */
173 | DF0DDAB521E35C440086663E /* Resources */ = {
174 | isa = PBXResourcesBuildPhase;
175 | buildActionMask = 2147483647;
176 | files = (
177 | );
178 | runOnlyForDeploymentPostprocessing = 0;
179 | };
180 | /* End PBXResourcesBuildPhase section */
181 |
182 | /* Begin PBXShellScriptBuildPhase section */
183 | 12A91B9C704D6696F36D03EA /* [CP] Check Pods Manifest.lock */ = {
184 | isa = PBXShellScriptBuildPhase;
185 | buildActionMask = 2147483647;
186 | files = (
187 | );
188 | inputFileListPaths = (
189 | );
190 | inputPaths = (
191 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
192 | "${PODS_ROOT}/Manifest.lock",
193 | );
194 | name = "[CP] Check Pods Manifest.lock";
195 | outputFileListPaths = (
196 | );
197 | outputPaths = (
198 | "$(DERIVED_FILE_DIR)/Pods-Aquaman-checkManifestLockResult.txt",
199 | );
200 | runOnlyForDeploymentPostprocessing = 0;
201 | shellPath = /bin/sh;
202 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
203 | showEnvVarsInLog = 0;
204 | };
205 | /* End PBXShellScriptBuildPhase section */
206 |
207 | /* Begin PBXSourcesBuildPhase section */
208 | DF0DDAB321E35C440086663E /* Sources */ = {
209 | isa = PBXSourcesBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | DF7F9F1121E37969000F4317 /* NSCache+Additional.swift in Sources */,
213 | DF7F9F0D21E37969000F4317 /* UIScrollView+Additional.swift in Sources */,
214 | DF7F9F0F21E37969000F4317 /* AquaMainScrollView.swift in Sources */,
215 | DFFEA09D24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift in Sources */,
216 | DF7F9F1221E37969000F4317 /* AquamanPageViewController.swift in Sources */,
217 | DF7F9F0E21E37969000F4317 /* AquamanContainView.swift in Sources */,
218 | DF7F9F0C21E37969000F4317 /* UIViewController+Additional.swift in Sources */,
219 | DF744C3C239F4F1F003A8EB4 /* AquamanProtocol.swift in Sources */,
220 | DF7F9F1021E37969000F4317 /* AquamanChildViewController.swift in Sources */,
221 | );
222 | runOnlyForDeploymentPostprocessing = 0;
223 | };
224 | /* End PBXSourcesBuildPhase section */
225 |
226 | /* Begin XCBuildConfiguration section */
227 | DF0DDABD21E35C440086663E /* Debug */ = {
228 | isa = XCBuildConfiguration;
229 | buildSettings = {
230 | ALWAYS_SEARCH_USER_PATHS = NO;
231 | CLANG_ANALYZER_NONNULL = YES;
232 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
233 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
234 | CLANG_CXX_LIBRARY = "libc++";
235 | CLANG_ENABLE_MODULES = YES;
236 | CLANG_ENABLE_OBJC_ARC = YES;
237 | CLANG_ENABLE_OBJC_WEAK = YES;
238 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
239 | CLANG_WARN_BOOL_CONVERSION = YES;
240 | CLANG_WARN_COMMA = YES;
241 | CLANG_WARN_CONSTANT_CONVERSION = YES;
242 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
245 | CLANG_WARN_EMPTY_BODY = YES;
246 | CLANG_WARN_ENUM_CONVERSION = YES;
247 | CLANG_WARN_INFINITE_RECURSION = YES;
248 | CLANG_WARN_INT_CONVERSION = YES;
249 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
250 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
251 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
253 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
254 | CLANG_WARN_STRICT_PROTOTYPES = YES;
255 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
256 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
257 | CLANG_WARN_UNREACHABLE_CODE = YES;
258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
259 | CODE_SIGN_IDENTITY = "iPhone Developer";
260 | COPY_PHASE_STRIP = NO;
261 | CURRENT_PROJECT_VERSION = 1;
262 | DEBUG_INFORMATION_FORMAT = dwarf;
263 | ENABLE_STRICT_OBJC_MSGSEND = YES;
264 | ENABLE_TESTABILITY = YES;
265 | GCC_C_LANGUAGE_STANDARD = gnu11;
266 | GCC_DYNAMIC_NO_PIC = NO;
267 | GCC_NO_COMMON_BLOCKS = YES;
268 | GCC_OPTIMIZATION_LEVEL = 0;
269 | GCC_PREPROCESSOR_DEFINITIONS = (
270 | "DEBUG=1",
271 | "$(inherited)",
272 | );
273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
275 | GCC_WARN_UNDECLARED_SELECTOR = YES;
276 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
277 | GCC_WARN_UNUSED_FUNCTION = YES;
278 | GCC_WARN_UNUSED_VARIABLE = YES;
279 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
280 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
281 | MTL_FAST_MATH = YES;
282 | ONLY_ACTIVE_ARCH = YES;
283 | SDKROOT = iphoneos;
284 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
285 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
286 | VERSIONING_SYSTEM = "apple-generic";
287 | VERSION_INFO_PREFIX = "";
288 | };
289 | name = Debug;
290 | };
291 | DF0DDABE21E35C440086663E /* Release */ = {
292 | isa = XCBuildConfiguration;
293 | buildSettings = {
294 | ALWAYS_SEARCH_USER_PATHS = NO;
295 | CLANG_ANALYZER_NONNULL = YES;
296 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
298 | CLANG_CXX_LIBRARY = "libc++";
299 | CLANG_ENABLE_MODULES = YES;
300 | CLANG_ENABLE_OBJC_ARC = YES;
301 | CLANG_ENABLE_OBJC_WEAK = YES;
302 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
303 | CLANG_WARN_BOOL_CONVERSION = YES;
304 | CLANG_WARN_COMMA = YES;
305 | CLANG_WARN_CONSTANT_CONVERSION = YES;
306 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
307 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
308 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
309 | CLANG_WARN_EMPTY_BODY = YES;
310 | CLANG_WARN_ENUM_CONVERSION = YES;
311 | CLANG_WARN_INFINITE_RECURSION = YES;
312 | CLANG_WARN_INT_CONVERSION = YES;
313 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
314 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
317 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
318 | CLANG_WARN_STRICT_PROTOTYPES = YES;
319 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
320 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
321 | CLANG_WARN_UNREACHABLE_CODE = YES;
322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
323 | CODE_SIGN_IDENTITY = "iPhone Developer";
324 | COPY_PHASE_STRIP = NO;
325 | CURRENT_PROJECT_VERSION = 1;
326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
327 | ENABLE_NS_ASSERTIONS = NO;
328 | ENABLE_STRICT_OBJC_MSGSEND = YES;
329 | GCC_C_LANGUAGE_STANDARD = gnu11;
330 | GCC_NO_COMMON_BLOCKS = YES;
331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
333 | GCC_WARN_UNDECLARED_SELECTOR = YES;
334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
335 | GCC_WARN_UNUSED_FUNCTION = YES;
336 | GCC_WARN_UNUSED_VARIABLE = YES;
337 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
338 | MTL_ENABLE_DEBUG_INFO = NO;
339 | MTL_FAST_MATH = YES;
340 | SDKROOT = iphoneos;
341 | SWIFT_COMPILATION_MODE = wholemodule;
342 | SWIFT_OPTIMIZATION_LEVEL = "-O";
343 | VALIDATE_PRODUCT = YES;
344 | VERSIONING_SYSTEM = "apple-generic";
345 | VERSION_INFO_PREFIX = "";
346 | };
347 | name = Release;
348 | };
349 | DF0DDAC021E35C440086663E /* Debug */ = {
350 | isa = XCBuildConfiguration;
351 | baseConfigurationReference = 4E2ADF93CCF5BBBB14110499 /* Pods-Aquaman.debug.xcconfig */;
352 | buildSettings = {
353 | CODE_SIGN_IDENTITY = "";
354 | CODE_SIGN_STYLE = Automatic;
355 | DEFINES_MODULE = YES;
356 | DYLIB_COMPATIBILITY_VERSION = 1;
357 | DYLIB_CURRENT_VERSION = 1;
358 | DYLIB_INSTALL_NAME_BASE = "@rpath";
359 | INFOPLIST_FILE = Aquaman/Info.plist;
360 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
361 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
362 | LD_RUNPATH_SEARCH_PATHS = (
363 | "$(inherited)",
364 | "@executable_path/Frameworks",
365 | "@loader_path/Frameworks",
366 | );
367 | PRODUCT_BUNDLE_IDENTIFIER = bawn.Aquaman;
368 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
369 | SKIP_INSTALL = YES;
370 | SWIFT_VERSION = 4.2;
371 | TARGETED_DEVICE_FAMILY = "1,2";
372 | };
373 | name = Debug;
374 | };
375 | DF0DDAC121E35C440086663E /* Release */ = {
376 | isa = XCBuildConfiguration;
377 | baseConfigurationReference = 6DFF8C1B0CD3525BDCE645C5 /* Pods-Aquaman.release.xcconfig */;
378 | buildSettings = {
379 | CODE_SIGN_IDENTITY = "";
380 | CODE_SIGN_STYLE = Automatic;
381 | DEFINES_MODULE = YES;
382 | DYLIB_COMPATIBILITY_VERSION = 1;
383 | DYLIB_CURRENT_VERSION = 1;
384 | DYLIB_INSTALL_NAME_BASE = "@rpath";
385 | INFOPLIST_FILE = Aquaman/Info.plist;
386 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
387 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
388 | LD_RUNPATH_SEARCH_PATHS = (
389 | "$(inherited)",
390 | "@executable_path/Frameworks",
391 | "@loader_path/Frameworks",
392 | );
393 | PRODUCT_BUNDLE_IDENTIFIER = bawn.Aquaman;
394 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
395 | SKIP_INSTALL = YES;
396 | SWIFT_VERSION = 4.2;
397 | TARGETED_DEVICE_FAMILY = "1,2";
398 | };
399 | name = Release;
400 | };
401 | /* End XCBuildConfiguration section */
402 |
403 | /* Begin XCConfigurationList section */
404 | DF0DDAB121E35C440086663E /* Build configuration list for PBXProject "Aquaman" */ = {
405 | isa = XCConfigurationList;
406 | buildConfigurations = (
407 | DF0DDABD21E35C440086663E /* Debug */,
408 | DF0DDABE21E35C440086663E /* Release */,
409 | );
410 | defaultConfigurationIsVisible = 0;
411 | defaultConfigurationName = Release;
412 | };
413 | DF0DDABF21E35C440086663E /* Build configuration list for PBXNativeTarget "Aquaman" */ = {
414 | isa = XCConfigurationList;
415 | buildConfigurations = (
416 | DF0DDAC021E35C440086663E /* Debug */,
417 | DF0DDAC121E35C440086663E /* Release */,
418 | );
419 | defaultConfigurationIsVisible = 0;
420 | defaultConfigurationName = Release;
421 | };
422 | /* End XCConfigurationList section */
423 | };
424 | rootObject = DF0DDAAE21E35C440086663E /* Project object */;
425 | }
426 |
--------------------------------------------------------------------------------
/Aquaman/Aquaman/AquamanPageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AquamanPageViewController.swift
3 | // Aquaman
4 | //
5 | // Created by bawn on 2018/12/7.
6 | // Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io )
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import UIKit
27 |
28 | open class AquamanPageViewController: UIViewController, AMPageControllerDataSource, AMPageControllerDelegate {
29 |
30 | public private(set) var currentViewController: (UIViewController & AquamanChildViewController)?
31 | public private(set) var currentIndex = 0
32 | internal var originIndex = 0
33 |
34 | lazy public private(set) var mainScrollView: AquaMainScrollView = {
35 | let scrollView = AquaMainScrollView()
36 | scrollView.delegate = self
37 | scrollView.am_isCanScroll = true
38 | return scrollView
39 | }()
40 |
41 | lazy internal var contentScrollView: UIScrollView = {
42 | let scrollView = UIScrollView()
43 | scrollView.delegate = self
44 | scrollView.bounces = false
45 | scrollView.isPagingEnabled = true
46 | scrollView.scrollsToTop = false
47 | scrollView.showsVerticalScrollIndicator = false
48 | scrollView.showsHorizontalScrollIndicator = false
49 | scrollView.translatesAutoresizingMaskIntoConstraints = false
50 | if let popGesture = navigationController?.interactivePopGestureRecognizer {
51 | scrollView.panGestureRecognizer.require(toFail: popGesture)
52 | }
53 | return scrollView
54 | }()
55 |
56 | private let contentStackView: UIStackView = {
57 | let stackView = UIStackView()
58 | stackView.alignment = .fill
59 | stackView.distribution = .fillEqually
60 | stackView.axis = .horizontal
61 | stackView.translatesAutoresizingMaskIntoConstraints = false
62 | return stackView
63 | }()
64 |
65 | private var contentScrollViewConstraint: NSLayoutConstraint?
66 | private var menuViewConstraint: NSLayoutConstraint?
67 | internal var headerViewConstraint: NSLayoutConstraint?
68 | private var mainScrollViewConstraints: [NSLayoutConstraint] = []
69 |
70 | internal var headerViewHeight: CGFloat = 0.0
71 | private let headerContentView = UIView()
72 | private let menuContentView = UIView()
73 | private var menuViewHeight: CGFloat = 0.0
74 | internal var menuViewPinHeight: CGFloat = 0.0
75 | internal var sillValue: CGFloat = 0.0
76 | private var childControllerCount = 0
77 | private var countArray = [Int]()
78 | private var containViews = [AquamanContainView]()
79 | internal var currentChildScrollView: UIScrollView?
80 | private var childScrollViewObservation: NSKeyValueObservation?
81 |
82 | private let memoryCache = NSCache()
83 | private weak var dataSource: AMPageControllerDataSource?
84 | private weak var delegate: AMPageControllerDelegate?
85 |
86 | open override var shouldAutomaticallyForwardAppearanceMethods: Bool {
87 | return false
88 | }
89 |
90 | public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
91 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
92 | dataSource = self
93 | delegate = self
94 | }
95 |
96 | public required init?(coder aDecoder: NSCoder) {
97 | super.init(coder: aDecoder)
98 | dataSource = self
99 | delegate = self
100 | }
101 |
102 | open override func viewDidLoad() {
103 | super.viewDidLoad()
104 |
105 | obtainDataSource()
106 | setupOriginContent()
107 | setupDataSource()
108 | view.layoutIfNeeded()
109 | if originIndex > 0 {
110 | setSelect(index: originIndex, animation: false)
111 | } else {
112 | showChildViewContoller(at: originIndex)
113 | didDisplayViewController(at: originIndex)
114 | }
115 | }
116 |
117 | deinit {
118 | childScrollViewObservation?.invalidate()
119 | }
120 |
121 | internal func didDisplayViewController(at index: Int) {
122 | guard childControllerCount > 0
123 | , index >= 0
124 | , index < childControllerCount
125 | , containViews.isEmpty == false else {
126 | return
127 | }
128 | let containView = containViews[index]
129 | currentViewController = containView.viewController
130 | currentChildScrollView = currentViewController?.aquamanChildScrollView()
131 | currentIndex = index
132 |
133 | childScrollViewObservation?.invalidate()
134 | let keyValueObservation = currentChildScrollView?.observe(\.contentOffset, options: [.new, .old], changeHandler: { [weak self] (scrollView, change) in
135 | guard let self = self, change.newValue != change.oldValue else {
136 | return
137 | }
138 | self.childScrollViewDidScroll(scrollView)
139 | })
140 | childScrollViewObservation = keyValueObservation
141 |
142 | if let viewController = containView.viewController {
143 | pageController(self, didDisplay: viewController, forItemAt: index)
144 | }
145 | }
146 |
147 |
148 | internal func obtainDataSource() {
149 | originIndex = originIndexFor(self)
150 |
151 | headerViewHeight = headerViewHeightFor(self)
152 |
153 | menuViewHeight = menuViewHeightFor(self)
154 | menuViewPinHeight = menuViewPinHeightFor(self)
155 |
156 | childControllerCount = numberOfViewControllers(in: self)
157 |
158 | sillValue = headerViewHeight - menuViewPinHeight
159 | countArray = Array(stride(from: 0, to: childControllerCount, by: 1))
160 | }
161 |
162 | private func setupOriginContent() {
163 |
164 | mainScrollView.headerViewHeight = headerViewHeight
165 | mainScrollView.menuViewHeight = menuViewHeight
166 | if #available(iOS 13.0, *) {
167 | mainScrollView.contentInsetAdjustmentBehavior = .never
168 | } else {
169 | automaticallyAdjustsScrollViewInsets = false
170 | }
171 |
172 | view.addSubview(mainScrollView)
173 | let contentInset = contentInsetFor(self)
174 | let constraints = [
175 | mainScrollView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: contentInset.top),
176 | mainScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: contentInset.left),
177 | mainScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -contentInset.bottom),
178 | mainScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -contentInset.right)
179 | ]
180 | mainScrollViewConstraints = constraints
181 | NSLayoutConstraint.activate(constraints)
182 |
183 |
184 | mainScrollView.addSubview(headerContentView)
185 | headerContentView.translatesAutoresizingMaskIntoConstraints = false
186 |
187 | let headerContentViewHeight = headerContentView.heightAnchor.constraint(equalToConstant: headerViewHeight)
188 | headerViewConstraint = headerContentViewHeight
189 | NSLayoutConstraint.activate([
190 | headerContentView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor),
191 | headerContentView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor),
192 | headerContentView.topAnchor.constraint(equalTo: mainScrollView.topAnchor),
193 | headerContentViewHeight,
194 | ])
195 |
196 | mainScrollView.addSubview(menuContentView)
197 | menuContentView.translatesAutoresizingMaskIntoConstraints = false
198 |
199 | let menuContentViewHeight = menuContentView.heightAnchor.constraint(equalToConstant: menuViewHeight)
200 | menuViewConstraint = menuContentViewHeight
201 | NSLayoutConstraint.activate([
202 | menuContentView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor),
203 | menuContentView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor),
204 | menuContentView.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor),
205 | menuContentView.topAnchor.constraint(equalTo: headerContentView.bottomAnchor),
206 | menuContentViewHeight
207 | ])
208 |
209 |
210 | mainScrollView.addSubview(contentScrollView)
211 |
212 | let contentScrollViewHeight = contentScrollView.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor, constant: -menuViewHeight - menuViewPinHeight)
213 | contentScrollViewConstraint = contentScrollViewHeight
214 | NSLayoutConstraint.activate([
215 | contentScrollView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor),
216 | contentScrollView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor),
217 | contentScrollView.bottomAnchor.constraint(equalTo: mainScrollView.bottomAnchor),
218 | contentScrollView.widthAnchor.constraint(equalTo: mainScrollView.widthAnchor),
219 | contentScrollView.topAnchor.constraint(equalTo: menuContentView.bottomAnchor),
220 | contentScrollViewHeight
221 | ])
222 |
223 |
224 | contentScrollView.addSubview(contentStackView)
225 |
226 | NSLayoutConstraint.activate([
227 | contentStackView.leadingAnchor.constraint(equalTo: contentScrollView.leadingAnchor),
228 | contentStackView.trailingAnchor.constraint(equalTo: contentScrollView.trailingAnchor),
229 | contentStackView.bottomAnchor.constraint(equalTo: contentScrollView.bottomAnchor),
230 | contentStackView.topAnchor.constraint(equalTo: contentScrollView.topAnchor),
231 | contentStackView.heightAnchor.constraint(equalTo: contentScrollView.heightAnchor)
232 | ])
233 |
234 | mainScrollView.bringSubviewToFront(menuContentView)
235 | mainScrollView.bringSubviewToFront(headerContentView)
236 | }
237 |
238 | internal func updateOriginContent() {
239 | mainScrollView.headerViewHeight = headerViewHeight
240 | mainScrollView.menuViewHeight = menuViewHeight
241 |
242 | if mainScrollViewConstraints.count == 4 {
243 | let contentInset = contentInsetFor(self)
244 | mainScrollViewConstraints.first?.constant = contentInset.top
245 | mainScrollViewConstraints[1].constant = contentInset.left
246 | mainScrollViewConstraints[2].constant = -contentInset.bottom
247 | mainScrollViewConstraints.last?.constant = -contentInset.right
248 | }
249 | headerViewConstraint?.constant = headerViewHeight
250 | menuViewConstraint?.constant = menuViewHeight
251 | contentScrollViewConstraint?.constant = -menuViewHeight - menuViewPinHeight
252 | }
253 |
254 | internal func clear() {
255 | childScrollViewObservation?.invalidate()
256 |
257 | originIndex = 0
258 | currentIndex = 0
259 |
260 | mainScrollView.am_isCanScroll = true
261 | currentChildScrollView?.am_isCanScroll = false
262 |
263 | childControllerCount = 0
264 |
265 | currentViewController = nil
266 | currentChildScrollView?.am_originOffset = nil
267 | currentChildScrollView = nil
268 |
269 | menuContentView.subviews.forEach({$0.removeFromSuperview()})
270 | headerContentView.subviews.forEach({$0.removeFromSuperview()})
271 | contentScrollView.contentOffset = .zero
272 |
273 | contentStackView.arrangedSubviews.forEach({$0.removeFromSuperview()})
274 | clearMemoryCache()
275 |
276 | containViews.forEach({$0.viewController?.clearFromParent()})
277 | containViews.removeAll()
278 |
279 | countArray.removeAll()
280 | }
281 |
282 | internal func clearMemoryCache() {
283 | countArray.forEach { (index) in
284 | let viewController = memoryCache[index] as? (UIViewController & AquamanChildViewController)
285 | let scrollView = viewController?.aquamanChildScrollView()
286 | scrollView?.am_originOffset = nil
287 | }
288 | memoryCache.removeAllObjects()
289 | }
290 |
291 | internal func setupDataSource() {
292 | memoryCache.countLimit = childControllerCount
293 |
294 | let headerView = headerViewFor(self)
295 | headerContentView.addSubview(headerView)
296 | headerView.translatesAutoresizingMaskIntoConstraints = false
297 | NSLayoutConstraint.activate([
298 | headerView.leadingAnchor.constraint(equalTo: headerContentView.leadingAnchor),
299 | headerView.trailingAnchor.constraint(equalTo: headerContentView.trailingAnchor),
300 | headerView.bottomAnchor.constraint(equalTo: headerContentView.bottomAnchor),
301 | headerView.topAnchor.constraint(equalTo: headerContentView.topAnchor)
302 | ])
303 |
304 | let menuView = menuViewFor(self)
305 | menuContentView.addSubview(menuView)
306 | menuView.translatesAutoresizingMaskIntoConstraints = false
307 | NSLayoutConstraint.activate([
308 | menuView.leadingAnchor.constraint(equalTo: menuContentView.leadingAnchor),
309 | menuView.trailingAnchor.constraint(equalTo: menuContentView.trailingAnchor),
310 | menuView.bottomAnchor.constraint(equalTo: menuContentView.bottomAnchor),
311 | menuView.topAnchor.constraint(equalTo: menuContentView.topAnchor)
312 | ])
313 |
314 |
315 | countArray.forEach { (_) in
316 | let containView = AquamanContainView()
317 | contentStackView.addArrangedSubview(containView)
318 | NSLayoutConstraint.activate([
319 | containView.heightAnchor.constraint(equalTo: contentScrollView.heightAnchor),
320 | containView.widthAnchor.constraint(equalTo: contentScrollView.widthAnchor)
321 | ])
322 | containViews.append(containView)
323 | }
324 | }
325 |
326 | internal func showChildViewContoller(at index: Int) {
327 | guard childControllerCount > 0
328 | , index >= 0
329 | , index < childControllerCount
330 | , containViews.isEmpty == false else {
331 | return
332 | }
333 |
334 | let containView = containViews[index]
335 | guard containView.isEmpty else {
336 | return
337 | }
338 |
339 | let cachedViewContoller = memoryCache[index] as? (UIViewController & AquamanChildViewController)
340 | let viewController = cachedViewContoller != nil ? cachedViewContoller : pageController(self, viewControllerAt: index)
341 |
342 | guard let targetViewController = viewController else {
343 | return
344 | }
345 | pageController(self, willDisplay: targetViewController, forItemAt: index)
346 |
347 | addChild(targetViewController)
348 | targetViewController.beginAppearanceTransition(true, animated: false)
349 | containView.addSubview(targetViewController.view)
350 | targetViewController.view.translatesAutoresizingMaskIntoConstraints = false
351 | NSLayoutConstraint.activate([
352 | targetViewController.view.leadingAnchor.constraint(equalTo: containView.leadingAnchor),
353 | targetViewController.view.trailingAnchor.constraint(equalTo: containView.trailingAnchor),
354 | targetViewController.view.bottomAnchor.constraint(equalTo: containView.bottomAnchor),
355 | targetViewController.view.topAnchor.constraint(equalTo: containView.topAnchor),
356 | ])
357 | targetViewController.endAppearanceTransition()
358 | targetViewController.didMove(toParent: self)
359 | targetViewController.view.layoutSubviews()
360 | containView.viewController = targetViewController
361 |
362 | let scrollView = targetViewController.aquamanChildScrollView()
363 | scrollView.am_originOffset = scrollView.contentOffset
364 |
365 | if mainScrollView.contentOffset.y < sillValue {
366 | scrollView.contentOffset = scrollView.am_originOffset ?? .zero
367 | scrollView.am_isCanScroll = false
368 | mainScrollView.am_isCanScroll = true
369 | }
370 | }
371 |
372 |
373 | private func removeChildViewController(at index: Int) {
374 | guard childControllerCount > 0
375 | , index >= 0
376 | , index < childControllerCount
377 | , containViews.isEmpty == false else {
378 | return
379 | }
380 |
381 | let containView = containViews[index]
382 | guard containView.isEmpty == false
383 | , let viewController = containView.viewController else {
384 | return
385 | }
386 | viewController.clearFromParent()
387 | if memoryCache[index] == nil {
388 | pageController(self, willCache: viewController, forItemAt: index)
389 | memoryCache[index] = viewController
390 | }
391 | }
392 |
393 | internal func layoutChildViewControlls() {
394 | countArray.forEach { (index) in
395 | let containView = containViews[index]
396 | let isDisplayingInScreen = containView.displayingIn(view: view, containView: contentScrollView)
397 | isDisplayingInScreen ? showChildViewContoller(at: index) : removeChildViewController(at: index)
398 | }
399 | }
400 |
401 | internal func contentScrollViewDidEndScroll(_ scrollView: UIScrollView) {
402 | let scrollViewWidth = scrollView.bounds.width
403 | guard scrollViewWidth > 0 else {
404 | return
405 | }
406 |
407 | let offsetX = scrollView.contentOffset.x
408 | let index = Int(offsetX / scrollViewWidth)
409 | didDisplayViewController(at: index)
410 | pageController(self, contentScrollViewDidEndScroll: contentScrollView)
411 | }
412 |
413 |
414 | open func pageController(_ pageController: AquamanPageViewController, viewControllerAt index: Int) -> (UIViewController & AquamanChildViewController) {
415 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
416 | return UIViewController() as! (UIViewController & AquamanChildViewController)
417 | }
418 |
419 | open func numberOfViewControllers(in pageController: AquamanPageViewController) -> Int {
420 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
421 | return 0
422 | }
423 |
424 | open func headerViewFor(_ pageController: AquamanPageViewController) -> UIView {
425 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
426 | return UIView()
427 | }
428 |
429 | open func headerViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
430 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
431 | return 0
432 | }
433 |
434 | open func menuViewFor(_ pageController: AquamanPageViewController) -> UIView {
435 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
436 | return UIView()
437 | }
438 |
439 | open func menuViewHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
440 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method")
441 | return 0
442 | }
443 |
444 | open func originIndexFor(_ pageController: AquamanPageViewController) -> Int {
445 | return 0
446 | }
447 |
448 | open func menuViewPinHeightFor(_ pageController: AquamanPageViewController) -> CGFloat {
449 | return 0
450 | }
451 |
452 | open func pageController(_ pageController: AquamanPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) {
453 |
454 | }
455 |
456 | open func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidEndScroll scrollView: UIScrollView) {
457 |
458 | }
459 |
460 | open func pageController(_ pageController: AquamanPageViewController, contentScrollViewDidScroll scrollView: UIScrollView) {
461 |
462 | }
463 |
464 | open func pageController(_ pageController: AquamanPageViewController, willCache viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
465 |
466 | }
467 |
468 | open func pageController(_ pageController: AquamanPageViewController, willDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
469 |
470 | }
471 |
472 | open func pageController(_ pageController: AquamanPageViewController, didDisplay viewController: (UIViewController & AquamanChildViewController), forItemAt index: Int) {
473 |
474 | }
475 |
476 | open func pageController(_ pageController: AquamanPageViewController, menuView isAdsorption: Bool) {
477 |
478 | }
479 |
480 | open func contentInsetFor(_ pageController: AquamanPageViewController) -> UIEdgeInsets {
481 | return .zero
482 | }
483 | }
484 |
485 |
486 |
--------------------------------------------------------------------------------
/Aquaman-Demo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3E70E23AE12A03F719A61B86 /* Pods_Aquaman_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1818A6060E4BCD927F3FAB53 /* Pods_Aquaman_Demo.framework */; };
11 | DF457BB323B6131F00708C49 /* Aquaman_DemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF457BB223B6131F00708C49 /* Aquaman_DemoUITests.swift */; };
12 | DF7AC0272320BB9E002E595E /* TheFlashViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7AC0262320BB9E002E595E /* TheFlashViewController.swift */; };
13 | DF7F9F2121E37EEB000F4317 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F2021E37EEB000F4317 /* AppDelegate.swift */; };
14 | DF7F9F2821E37EEC000F4317 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DF7F9F2721E37EEC000F4317 /* Assets.xcassets */; };
15 | DF7F9F2B21E37EEC000F4317 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DF7F9F2921E37EEC000F4317 /* LaunchScreen.storyboard */; };
16 | DF7F9F3E21E37FAA000F4317 /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F3221E37FA9000F4317 /* HeaderView.swift */; };
17 | DF7F9F4321E37FAA000F4317 /* BatmanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F3721E37FA9000F4317 /* BatmanViewController.swift */; };
18 | DF7F9F4421E37FAA000F4317 /* SupermanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F3821E37FA9000F4317 /* SupermanViewController.swift */; };
19 | DF7F9F4521E37FAA000F4317 /* PageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F3921E37FA9000F4317 /* PageViewController.swift */; };
20 | DF7F9F4721E37FAA000F4317 /* WonderWomanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F3B21E37FA9000F4317 /* WonderWomanViewController.swift */; };
21 | DF7F9F4B21E37FBB000F4317 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DF7F9F4A21E37FBB000F4317 /* Main.storyboard */; };
22 | DF931184250C7D5600870847 /* Trident in Frameworks */ = {isa = PBXBuildFile; productRef = DF931183250C7D5600870847 /* Trident */; };
23 | DF931187250C7DDC00870847 /* Aquaman in Frameworks */ = {isa = PBXBuildFile; productRef = DF931186250C7DDC00870847 /* Aquaman */; };
24 | DFD4116121E84011006E8D77 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD4116021E84011006E8D77 /* ViewController.swift */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXContainerItemProxy section */
28 | DF457BB523B6131F00708C49 /* PBXContainerItemProxy */ = {
29 | isa = PBXContainerItemProxy;
30 | containerPortal = DF7F9F1521E37EEB000F4317 /* Project object */;
31 | proxyType = 1;
32 | remoteGlobalIDString = DF7F9F1C21E37EEB000F4317;
33 | remoteInfo = "Aquaman-Demo";
34 | };
35 | /* End PBXContainerItemProxy section */
36 |
37 | /* Begin PBXCopyFilesBuildPhase section */
38 | DF37AB8E23B9F47D0047FEF9 /* Embed Frameworks */ = {
39 | isa = PBXCopyFilesBuildPhase;
40 | buildActionMask = 2147483647;
41 | dstPath = "";
42 | dstSubfolderSpec = 10;
43 | files = (
44 | );
45 | name = "Embed Frameworks";
46 | runOnlyForDeploymentPostprocessing = 0;
47 | };
48 | /* End PBXCopyFilesBuildPhase section */
49 |
50 | /* Begin PBXFileReference section */
51 | 1818A6060E4BCD927F3FAB53 /* Pods_Aquaman_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Aquaman_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 3A86685D0616AED53669BBEF /* Pods-Aquaman-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aquaman-Demo.release.xcconfig"; path = "Target Support Files/Pods-Aquaman-Demo/Pods-Aquaman-Demo.release.xcconfig"; sourceTree = ""; };
53 | DF457BB023B6131F00708C49 /* Aquaman-DemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Aquaman-DemoUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
54 | DF457BB223B6131F00708C49 /* Aquaman_DemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Aquaman_DemoUITests.swift; sourceTree = ""; };
55 | DF457BB423B6131F00708C49 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
56 | DF786CD82230CB8800DD6955 /* Aquaman.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Aquaman.framework; sourceTree = BUILT_PRODUCTS_DIR; };
57 | DF7AC0262320BB9E002E595E /* TheFlashViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheFlashViewController.swift; sourceTree = ""; };
58 | DF7F9F1D21E37EEB000F4317 /* Aquaman-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Aquaman-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
59 | DF7F9F2021E37EEB000F4317 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
60 | DF7F9F2721E37EEC000F4317 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
61 | DF7F9F2A21E37EEC000F4317 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
62 | DF7F9F2C21E37EEC000F4317 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
63 | DF7F9F3221E37FA9000F4317 /* HeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; };
64 | DF7F9F3721E37FA9000F4317 /* BatmanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatmanViewController.swift; sourceTree = ""; };
65 | DF7F9F3821E37FA9000F4317 /* SupermanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupermanViewController.swift; sourceTree = ""; };
66 | DF7F9F3921E37FA9000F4317 /* PageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PageViewController.swift; sourceTree = ""; };
67 | DF7F9F3B21E37FA9000F4317 /* WonderWomanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WonderWomanViewController.swift; sourceTree = ""; };
68 | DF7F9F4A21E37FBB000F4317 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
69 | DFD4116021E84011006E8D77 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
70 | F5EA41D9B5EC67782591227C /* Pods-Aquaman-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aquaman-Demo.debug.xcconfig"; path = "Target Support Files/Pods-Aquaman-Demo/Pods-Aquaman-Demo.debug.xcconfig"; sourceTree = ""; };
71 | /* End PBXFileReference section */
72 |
73 | /* Begin PBXFrameworksBuildPhase section */
74 | DF457BAD23B6131E00708C49 /* Frameworks */ = {
75 | isa = PBXFrameworksBuildPhase;
76 | buildActionMask = 2147483647;
77 | files = (
78 | );
79 | runOnlyForDeploymentPostprocessing = 0;
80 | };
81 | DF7F9F1A21E37EEB000F4317 /* Frameworks */ = {
82 | isa = PBXFrameworksBuildPhase;
83 | buildActionMask = 2147483647;
84 | files = (
85 | DF931187250C7DDC00870847 /* Aquaman in Frameworks */,
86 | 3E70E23AE12A03F719A61B86 /* Pods_Aquaman_Demo.framework in Frameworks */,
87 | DF931184250C7D5600870847 /* Trident in Frameworks */,
88 | );
89 | runOnlyForDeploymentPostprocessing = 0;
90 | };
91 | /* End PBXFrameworksBuildPhase section */
92 |
93 | /* Begin PBXGroup section */
94 | 26D8BFA01A1516C315CC832E /* Pods */ = {
95 | isa = PBXGroup;
96 | children = (
97 | F5EA41D9B5EC67782591227C /* Pods-Aquaman-Demo.debug.xcconfig */,
98 | 3A86685D0616AED53669BBEF /* Pods-Aquaman-Demo.release.xcconfig */,
99 | );
100 | path = Pods;
101 | sourceTree = "";
102 | };
103 | 7E74EA9976E9E47CAA6BDD04 /* Frameworks */ = {
104 | isa = PBXGroup;
105 | children = (
106 | DF786CD82230CB8800DD6955 /* Aquaman.framework */,
107 | 1818A6060E4BCD927F3FAB53 /* Pods_Aquaman_Demo.framework */,
108 | );
109 | name = Frameworks;
110 | sourceTree = "";
111 | };
112 | DF457BB123B6131F00708C49 /* Aquaman-DemoUITests */ = {
113 | isa = PBXGroup;
114 | children = (
115 | DF457BB223B6131F00708C49 /* Aquaman_DemoUITests.swift */,
116 | DF457BB423B6131F00708C49 /* Info.plist */,
117 | );
118 | path = "Aquaman-DemoUITests";
119 | sourceTree = "";
120 | };
121 | DF7F9F1421E37EEB000F4317 = {
122 | isa = PBXGroup;
123 | children = (
124 | DF7F9F1F21E37EEB000F4317 /* Aquaman-Demo */,
125 | DF457BB123B6131F00708C49 /* Aquaman-DemoUITests */,
126 | DF7F9F1E21E37EEB000F4317 /* Products */,
127 | 7E74EA9976E9E47CAA6BDD04 /* Frameworks */,
128 | 26D8BFA01A1516C315CC832E /* Pods */,
129 | );
130 | sourceTree = "";
131 | };
132 | DF7F9F1E21E37EEB000F4317 /* Products */ = {
133 | isa = PBXGroup;
134 | children = (
135 | DF7F9F1D21E37EEB000F4317 /* Aquaman-Demo.app */,
136 | DF457BB023B6131F00708C49 /* Aquaman-DemoUITests.xctest */,
137 | );
138 | name = Products;
139 | sourceTree = "";
140 | };
141 | DF7F9F1F21E37EEB000F4317 /* Aquaman-Demo */ = {
142 | isa = PBXGroup;
143 | children = (
144 | DF7F9F2021E37EEB000F4317 /* AppDelegate.swift */,
145 | DF7F9F3921E37FA9000F4317 /* PageViewController.swift */,
146 | DF7F9F3821E37FA9000F4317 /* SupermanViewController.swift */,
147 | DF7F9F3721E37FA9000F4317 /* BatmanViewController.swift */,
148 | DF7F9F3B21E37FA9000F4317 /* WonderWomanViewController.swift */,
149 | DF7AC0262320BB9E002E595E /* TheFlashViewController.swift */,
150 | DF7F9F3221E37FA9000F4317 /* HeaderView.swift */,
151 | DFD4116021E84011006E8D77 /* ViewController.swift */,
152 | DF7F9F4A21E37FBB000F4317 /* Main.storyboard */,
153 | DF7F9F2721E37EEC000F4317 /* Assets.xcassets */,
154 | DF7F9F2921E37EEC000F4317 /* LaunchScreen.storyboard */,
155 | DF7F9F2C21E37EEC000F4317 /* Info.plist */,
156 | );
157 | path = "Aquaman-Demo";
158 | sourceTree = "";
159 | };
160 | /* End PBXGroup section */
161 |
162 | /* Begin PBXNativeTarget section */
163 | DF457BAF23B6131E00708C49 /* Aquaman-DemoUITests */ = {
164 | isa = PBXNativeTarget;
165 | buildConfigurationList = DF457BB923B6131F00708C49 /* Build configuration list for PBXNativeTarget "Aquaman-DemoUITests" */;
166 | buildPhases = (
167 | DF457BAC23B6131E00708C49 /* Sources */,
168 | DF457BAD23B6131E00708C49 /* Frameworks */,
169 | DF457BAE23B6131E00708C49 /* Resources */,
170 | );
171 | buildRules = (
172 | );
173 | dependencies = (
174 | DF457BB623B6131F00708C49 /* PBXTargetDependency */,
175 | );
176 | name = "Aquaman-DemoUITests";
177 | productName = "Aquaman-DemoUITests";
178 | productReference = DF457BB023B6131F00708C49 /* Aquaman-DemoUITests.xctest */;
179 | productType = "com.apple.product-type.bundle.ui-testing";
180 | };
181 | DF7F9F1C21E37EEB000F4317 /* Aquaman-Demo */ = {
182 | isa = PBXNativeTarget;
183 | buildConfigurationList = DF7F9F2F21E37EEC000F4317 /* Build configuration list for PBXNativeTarget "Aquaman-Demo" */;
184 | buildPhases = (
185 | 8EF3531CB233F0CACA93EEEF /* [CP] Check Pods Manifest.lock */,
186 | DF7F9F1921E37EEB000F4317 /* Sources */,
187 | DF7F9F1A21E37EEB000F4317 /* Frameworks */,
188 | DF7F9F1B21E37EEB000F4317 /* Resources */,
189 | DF37AB8E23B9F47D0047FEF9 /* Embed Frameworks */,
190 | D65C893F5D7CA8B838CECDC6 /* [CP] Embed Pods Frameworks */,
191 | );
192 | buildRules = (
193 | );
194 | dependencies = (
195 | );
196 | name = "Aquaman-Demo";
197 | packageProductDependencies = (
198 | DF931183250C7D5600870847 /* Trident */,
199 | DF931186250C7DDC00870847 /* Aquaman */,
200 | );
201 | productName = "Aquaman-Demo";
202 | productReference = DF7F9F1D21E37EEB000F4317 /* Aquaman-Demo.app */;
203 | productType = "com.apple.product-type.application";
204 | };
205 | /* End PBXNativeTarget section */
206 |
207 | /* Begin PBXProject section */
208 | DF7F9F1521E37EEB000F4317 /* Project object */ = {
209 | isa = PBXProject;
210 | attributes = {
211 | LastSwiftUpdateCheck = 1130;
212 | LastUpgradeCheck = 1010;
213 | ORGANIZATIONNAME = bawn;
214 | TargetAttributes = {
215 | DF457BAF23B6131E00708C49 = {
216 | CreatedOnToolsVersion = 11.3;
217 | TestTargetID = DF7F9F1C21E37EEB000F4317;
218 | };
219 | DF7F9F1C21E37EEB000F4317 = {
220 | CreatedOnToolsVersion = 10.1;
221 | };
222 | };
223 | };
224 | buildConfigurationList = DF7F9F1821E37EEB000F4317 /* Build configuration list for PBXProject "Aquaman-Demo" */;
225 | compatibilityVersion = "Xcode 9.3";
226 | developmentRegion = en;
227 | hasScannedForEncodings = 0;
228 | knownRegions = (
229 | en,
230 | Base,
231 | );
232 | mainGroup = DF7F9F1421E37EEB000F4317;
233 | packageReferences = (
234 | DF931182250C7D5600870847 /* XCRemoteSwiftPackageReference "Trident" */,
235 | DF931185250C7DDC00870847 /* XCRemoteSwiftPackageReference "Aquaman" */,
236 | );
237 | productRefGroup = DF7F9F1E21E37EEB000F4317 /* Products */;
238 | projectDirPath = "";
239 | projectRoot = "";
240 | targets = (
241 | DF7F9F1C21E37EEB000F4317 /* Aquaman-Demo */,
242 | DF457BAF23B6131E00708C49 /* Aquaman-DemoUITests */,
243 | );
244 | };
245 | /* End PBXProject section */
246 |
247 | /* Begin PBXResourcesBuildPhase section */
248 | DF457BAE23B6131E00708C49 /* Resources */ = {
249 | isa = PBXResourcesBuildPhase;
250 | buildActionMask = 2147483647;
251 | files = (
252 | );
253 | runOnlyForDeploymentPostprocessing = 0;
254 | };
255 | DF7F9F1B21E37EEB000F4317 /* Resources */ = {
256 | isa = PBXResourcesBuildPhase;
257 | buildActionMask = 2147483647;
258 | files = (
259 | DF7F9F4B21E37FBB000F4317 /* Main.storyboard in Resources */,
260 | DF7F9F2B21E37EEC000F4317 /* LaunchScreen.storyboard in Resources */,
261 | DF7F9F2821E37EEC000F4317 /* Assets.xcassets in Resources */,
262 | );
263 | runOnlyForDeploymentPostprocessing = 0;
264 | };
265 | /* End PBXResourcesBuildPhase section */
266 |
267 | /* Begin PBXShellScriptBuildPhase section */
268 | 8EF3531CB233F0CACA93EEEF /* [CP] Check Pods Manifest.lock */ = {
269 | isa = PBXShellScriptBuildPhase;
270 | buildActionMask = 2147483647;
271 | files = (
272 | );
273 | inputFileListPaths = (
274 | );
275 | inputPaths = (
276 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
277 | "${PODS_ROOT}/Manifest.lock",
278 | );
279 | name = "[CP] Check Pods Manifest.lock";
280 | outputFileListPaths = (
281 | );
282 | outputPaths = (
283 | "$(DERIVED_FILE_DIR)/Pods-Aquaman-Demo-checkManifestLockResult.txt",
284 | );
285 | runOnlyForDeploymentPostprocessing = 0;
286 | shellPath = /bin/sh;
287 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
288 | showEnvVarsInLog = 0;
289 | };
290 | D65C893F5D7CA8B838CECDC6 /* [CP] Embed Pods Frameworks */ = {
291 | isa = PBXShellScriptBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | );
295 | inputFileListPaths = (
296 | "${PODS_ROOT}/Target Support Files/Pods-Aquaman-Demo/Pods-Aquaman-Demo-frameworks-${CONFIGURATION}-input-files.xcfilelist",
297 | );
298 | name = "[CP] Embed Pods Frameworks";
299 | outputFileListPaths = (
300 | "${PODS_ROOT}/Target Support Files/Pods-Aquaman-Demo/Pods-Aquaman-Demo-frameworks-${CONFIGURATION}-output-files.xcfilelist",
301 | );
302 | runOnlyForDeploymentPostprocessing = 0;
303 | shellPath = /bin/sh;
304 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Aquaman-Demo/Pods-Aquaman-Demo-frameworks.sh\"\n";
305 | showEnvVarsInLog = 0;
306 | };
307 | /* End PBXShellScriptBuildPhase section */
308 |
309 | /* Begin PBXSourcesBuildPhase section */
310 | DF457BAC23B6131E00708C49 /* Sources */ = {
311 | isa = PBXSourcesBuildPhase;
312 | buildActionMask = 2147483647;
313 | files = (
314 | DF457BB323B6131F00708C49 /* Aquaman_DemoUITests.swift in Sources */,
315 | );
316 | runOnlyForDeploymentPostprocessing = 0;
317 | };
318 | DF7F9F1921E37EEB000F4317 /* Sources */ = {
319 | isa = PBXSourcesBuildPhase;
320 | buildActionMask = 2147483647;
321 | files = (
322 | DF7F9F4521E37FAA000F4317 /* PageViewController.swift in Sources */,
323 | DF7AC0272320BB9E002E595E /* TheFlashViewController.swift in Sources */,
324 | DF7F9F4721E37FAA000F4317 /* WonderWomanViewController.swift in Sources */,
325 | DF7F9F3E21E37FAA000F4317 /* HeaderView.swift in Sources */,
326 | DFD4116121E84011006E8D77 /* ViewController.swift in Sources */,
327 | DF7F9F2121E37EEB000F4317 /* AppDelegate.swift in Sources */,
328 | DF7F9F4321E37FAA000F4317 /* BatmanViewController.swift in Sources */,
329 | DF7F9F4421E37FAA000F4317 /* SupermanViewController.swift in Sources */,
330 | );
331 | runOnlyForDeploymentPostprocessing = 0;
332 | };
333 | /* End PBXSourcesBuildPhase section */
334 |
335 | /* Begin PBXTargetDependency section */
336 | DF457BB623B6131F00708C49 /* PBXTargetDependency */ = {
337 | isa = PBXTargetDependency;
338 | target = DF7F9F1C21E37EEB000F4317 /* Aquaman-Demo */;
339 | targetProxy = DF457BB523B6131F00708C49 /* PBXContainerItemProxy */;
340 | };
341 | /* End PBXTargetDependency section */
342 |
343 | /* Begin PBXVariantGroup section */
344 | DF7F9F2921E37EEC000F4317 /* LaunchScreen.storyboard */ = {
345 | isa = PBXVariantGroup;
346 | children = (
347 | DF7F9F2A21E37EEC000F4317 /* Base */,
348 | );
349 | name = LaunchScreen.storyboard;
350 | sourceTree = "";
351 | };
352 | /* End PBXVariantGroup section */
353 |
354 | /* Begin XCBuildConfiguration section */
355 | DF457BB723B6131F00708C49 /* Debug */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | CODE_SIGN_STYLE = Automatic;
359 | DEVELOPMENT_TEAM = 8246L2QR6A;
360 | INFOPLIST_FILE = "Aquaman-DemoUITests/Info.plist";
361 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
362 | LD_RUNPATH_SEARCH_PATHS = (
363 | "$(inherited)",
364 | "@executable_path/Frameworks",
365 | "@loader_path/Frameworks",
366 | );
367 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Aquaman-DemoUITests";
368 | PRODUCT_NAME = "$(TARGET_NAME)";
369 | SWIFT_VERSION = 5.0;
370 | TARGETED_DEVICE_FAMILY = "1,2";
371 | TEST_TARGET_NAME = "Aquaman-Demo";
372 | };
373 | name = Debug;
374 | };
375 | DF457BB823B6131F00708C49 /* Release */ = {
376 | isa = XCBuildConfiguration;
377 | buildSettings = {
378 | CODE_SIGN_STYLE = Automatic;
379 | DEVELOPMENT_TEAM = 8246L2QR6A;
380 | INFOPLIST_FILE = "Aquaman-DemoUITests/Info.plist";
381 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
382 | LD_RUNPATH_SEARCH_PATHS = (
383 | "$(inherited)",
384 | "@executable_path/Frameworks",
385 | "@loader_path/Frameworks",
386 | );
387 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Aquaman-DemoUITests";
388 | PRODUCT_NAME = "$(TARGET_NAME)";
389 | SWIFT_VERSION = 5.0;
390 | TARGETED_DEVICE_FAMILY = "1,2";
391 | TEST_TARGET_NAME = "Aquaman-Demo";
392 | };
393 | name = Release;
394 | };
395 | DF7F9F2D21E37EEC000F4317 /* Debug */ = {
396 | isa = XCBuildConfiguration;
397 | buildSettings = {
398 | ALWAYS_SEARCH_USER_PATHS = NO;
399 | CLANG_ANALYZER_NONNULL = YES;
400 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
402 | CLANG_CXX_LIBRARY = "libc++";
403 | CLANG_ENABLE_MODULES = YES;
404 | CLANG_ENABLE_OBJC_ARC = YES;
405 | CLANG_ENABLE_OBJC_WEAK = YES;
406 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
407 | CLANG_WARN_BOOL_CONVERSION = YES;
408 | CLANG_WARN_COMMA = YES;
409 | CLANG_WARN_CONSTANT_CONVERSION = YES;
410 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
411 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
412 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
413 | CLANG_WARN_EMPTY_BODY = YES;
414 | CLANG_WARN_ENUM_CONVERSION = YES;
415 | CLANG_WARN_INFINITE_RECURSION = YES;
416 | CLANG_WARN_INT_CONVERSION = YES;
417 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
418 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
419 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
420 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
421 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
422 | CLANG_WARN_STRICT_PROTOTYPES = YES;
423 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
424 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
425 | CLANG_WARN_UNREACHABLE_CODE = YES;
426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
427 | CODE_SIGN_IDENTITY = "iPhone Developer";
428 | COPY_PHASE_STRIP = NO;
429 | DEBUG_INFORMATION_FORMAT = dwarf;
430 | ENABLE_STRICT_OBJC_MSGSEND = YES;
431 | ENABLE_TESTABILITY = YES;
432 | GCC_C_LANGUAGE_STANDARD = gnu11;
433 | GCC_DYNAMIC_NO_PIC = NO;
434 | GCC_NO_COMMON_BLOCKS = YES;
435 | GCC_OPTIMIZATION_LEVEL = 0;
436 | GCC_PREPROCESSOR_DEFINITIONS = (
437 | "DEBUG=1",
438 | "$(inherited)",
439 | );
440 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
441 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
442 | GCC_WARN_UNDECLARED_SELECTOR = YES;
443 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
444 | GCC_WARN_UNUSED_FUNCTION = YES;
445 | GCC_WARN_UNUSED_VARIABLE = YES;
446 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
447 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
448 | MTL_FAST_MATH = YES;
449 | ONLY_ACTIVE_ARCH = YES;
450 | SDKROOT = iphoneos;
451 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
452 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
453 | };
454 | name = Debug;
455 | };
456 | DF7F9F2E21E37EEC000F4317 /* Release */ = {
457 | isa = XCBuildConfiguration;
458 | buildSettings = {
459 | ALWAYS_SEARCH_USER_PATHS = NO;
460 | CLANG_ANALYZER_NONNULL = YES;
461 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
462 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
463 | CLANG_CXX_LIBRARY = "libc++";
464 | CLANG_ENABLE_MODULES = YES;
465 | CLANG_ENABLE_OBJC_ARC = YES;
466 | CLANG_ENABLE_OBJC_WEAK = YES;
467 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
468 | CLANG_WARN_BOOL_CONVERSION = YES;
469 | CLANG_WARN_COMMA = YES;
470 | CLANG_WARN_CONSTANT_CONVERSION = YES;
471 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
472 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
473 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
474 | CLANG_WARN_EMPTY_BODY = YES;
475 | CLANG_WARN_ENUM_CONVERSION = YES;
476 | CLANG_WARN_INFINITE_RECURSION = YES;
477 | CLANG_WARN_INT_CONVERSION = YES;
478 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
479 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
480 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
481 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
482 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
483 | CLANG_WARN_STRICT_PROTOTYPES = YES;
484 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
485 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
486 | CLANG_WARN_UNREACHABLE_CODE = YES;
487 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
488 | CODE_SIGN_IDENTITY = "iPhone Developer";
489 | COPY_PHASE_STRIP = NO;
490 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
491 | ENABLE_NS_ASSERTIONS = NO;
492 | ENABLE_STRICT_OBJC_MSGSEND = YES;
493 | GCC_C_LANGUAGE_STANDARD = gnu11;
494 | GCC_NO_COMMON_BLOCKS = YES;
495 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
496 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
497 | GCC_WARN_UNDECLARED_SELECTOR = YES;
498 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
499 | GCC_WARN_UNUSED_FUNCTION = YES;
500 | GCC_WARN_UNUSED_VARIABLE = YES;
501 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
502 | MTL_ENABLE_DEBUG_INFO = NO;
503 | MTL_FAST_MATH = YES;
504 | SDKROOT = iphoneos;
505 | SWIFT_COMPILATION_MODE = wholemodule;
506 | SWIFT_OPTIMIZATION_LEVEL = "-O";
507 | VALIDATE_PRODUCT = YES;
508 | };
509 | name = Release;
510 | };
511 | DF7F9F3021E37EEC000F4317 /* Debug */ = {
512 | isa = XCBuildConfiguration;
513 | baseConfigurationReference = F5EA41D9B5EC67782591227C /* Pods-Aquaman-Demo.debug.xcconfig */;
514 | buildSettings = {
515 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
516 | CODE_SIGN_STYLE = Automatic;
517 | DEVELOPMENT_TEAM = 8246L2QR6A;
518 | INFOPLIST_FILE = "Aquaman-Demo/Info.plist";
519 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
520 | LD_RUNPATH_SEARCH_PATHS = (
521 | "$(inherited)",
522 | "@executable_path/Frameworks",
523 | );
524 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Aquaman-Demo";
525 | PRODUCT_NAME = "$(TARGET_NAME)";
526 | SWIFT_VERSION = 4.2;
527 | TARGETED_DEVICE_FAMILY = "1,2";
528 | };
529 | name = Debug;
530 | };
531 | DF7F9F3121E37EEC000F4317 /* Release */ = {
532 | isa = XCBuildConfiguration;
533 | baseConfigurationReference = 3A86685D0616AED53669BBEF /* Pods-Aquaman-Demo.release.xcconfig */;
534 | buildSettings = {
535 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
536 | CODE_SIGN_STYLE = Automatic;
537 | DEVELOPMENT_TEAM = 8246L2QR6A;
538 | INFOPLIST_FILE = "Aquaman-Demo/Info.plist";
539 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
540 | LD_RUNPATH_SEARCH_PATHS = (
541 | "$(inherited)",
542 | "@executable_path/Frameworks",
543 | );
544 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Aquaman-Demo";
545 | PRODUCT_NAME = "$(TARGET_NAME)";
546 | SWIFT_VERSION = 4.2;
547 | TARGETED_DEVICE_FAMILY = "1,2";
548 | };
549 | name = Release;
550 | };
551 | /* End XCBuildConfiguration section */
552 |
553 | /* Begin XCConfigurationList section */
554 | DF457BB923B6131F00708C49 /* Build configuration list for PBXNativeTarget "Aquaman-DemoUITests" */ = {
555 | isa = XCConfigurationList;
556 | buildConfigurations = (
557 | DF457BB723B6131F00708C49 /* Debug */,
558 | DF457BB823B6131F00708C49 /* Release */,
559 | );
560 | defaultConfigurationIsVisible = 0;
561 | defaultConfigurationName = Release;
562 | };
563 | DF7F9F1821E37EEB000F4317 /* Build configuration list for PBXProject "Aquaman-Demo" */ = {
564 | isa = XCConfigurationList;
565 | buildConfigurations = (
566 | DF7F9F2D21E37EEC000F4317 /* Debug */,
567 | DF7F9F2E21E37EEC000F4317 /* Release */,
568 | );
569 | defaultConfigurationIsVisible = 0;
570 | defaultConfigurationName = Release;
571 | };
572 | DF7F9F2F21E37EEC000F4317 /* Build configuration list for PBXNativeTarget "Aquaman-Demo" */ = {
573 | isa = XCConfigurationList;
574 | buildConfigurations = (
575 | DF7F9F3021E37EEC000F4317 /* Debug */,
576 | DF7F9F3121E37EEC000F4317 /* Release */,
577 | );
578 | defaultConfigurationIsVisible = 0;
579 | defaultConfigurationName = Release;
580 | };
581 | /* End XCConfigurationList section */
582 |
583 | /* Begin XCRemoteSwiftPackageReference section */
584 | DF931182250C7D5600870847 /* XCRemoteSwiftPackageReference "Trident" */ = {
585 | isa = XCRemoteSwiftPackageReference;
586 | repositoryURL = "https://github.com/bawn/Trident.git";
587 | requirement = {
588 | kind = upToNextMajorVersion;
589 | minimumVersion = 0.7.0;
590 | };
591 | };
592 | DF931185250C7DDC00870847 /* XCRemoteSwiftPackageReference "Aquaman" */ = {
593 | isa = XCRemoteSwiftPackageReference;
594 | repositoryURL = "https://github.com/bawn/Aquaman.git";
595 | requirement = {
596 | kind = upToNextMajorVersion;
597 | minimumVersion = 0.1.3;
598 | };
599 | };
600 | /* End XCRemoteSwiftPackageReference section */
601 |
602 | /* Begin XCSwiftPackageProductDependency section */
603 | DF931183250C7D5600870847 /* Trident */ = {
604 | isa = XCSwiftPackageProductDependency;
605 | package = DF931182250C7D5600870847 /* XCRemoteSwiftPackageReference "Trident" */;
606 | productName = Trident;
607 | };
608 | DF931186250C7DDC00870847 /* Aquaman */ = {
609 | isa = XCSwiftPackageProductDependency;
610 | package = DF931185250C7DDC00870847 /* XCRemoteSwiftPackageReference "Aquaman" */;
611 | productName = Aquaman;
612 | };
613 | /* End XCSwiftPackageProductDependency section */
614 | };
615 | rootObject = DF7F9F1521E37EEB000F4317 /* Project object */;
616 | }
617 |
--------------------------------------------------------------------------------
/Aquaman-Demo/Main.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 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
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 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
--------------------------------------------------------------------------------