├── .gitignore ├── LICENSE ├── Podfile ├── Podfile.lock ├── README-CHINESE.md ├── README.md ├── Shazam-Demo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── bawn.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── bawn.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── Shazam-Demo ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── BatmanViewController.swift ├── HeaderView.swift ├── Info.plist ├── PageViewController.swift ├── SupermanViewController.swift ├── ViewController.swift └── WonderWomanViewController.swift ├── Shazam.podspec ├── Shazam.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── bawn.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── Shazam.xcscheme └── xcuserdata │ └── bawn.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── Shazam.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── bawn.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── Shazam ├── .gitattributes ├── .gitignore ├── Info.plist ├── NSCache+Additional.swift ├── Shazam.h ├── ShazamChildViewController.swift ├── ShazamContainView.swift ├── ShazamHeaderView.swift ├── ShazamPageViewController.swift ├── ShazamTopView.swift ├── UIScrollView+Additional.swift └── UIViewController+Additional.swift └── demo.gif /.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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 './Shazam.xcworkspace' 5 | 6 | target 'Shazam' do 7 | project './Shazam' 8 | use_frameworks! 9 | 10 | end 11 | 12 | target 'Shazam-Demo' do 13 | project './Shazam-Demo' 14 | use_frameworks! 15 | pod 'SnapKit' 16 | pod 'MJRefresh' 17 | pod 'Trident' 18 | pod 'Reveal-SDK', '27', :configurations => ['Debug'] 19 | end 20 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MJRefresh (3.3.1) 3 | - Reveal-SDK (27) 4 | - SnapKit (4.2.0) 5 | - Trident (0.3.0): 6 | - SnapKit (~> 4.2.0) 7 | 8 | DEPENDENCIES: 9 | - MJRefresh 10 | - Reveal-SDK (= 27) 11 | - SnapKit 12 | - Trident 13 | 14 | SPEC REPOS: 15 | https://cdn.cocoapods.org/: 16 | - MJRefresh 17 | - Reveal-SDK 18 | - SnapKit 19 | - Trident 20 | 21 | SPEC CHECKSUMS: 22 | MJRefresh: eeda70fbf0ad277f3178cef1cd0c3532591d6237 23 | Reveal-SDK: 306e2880395ee396f5a8b4c485c3a86dd19866c7 24 | SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a 25 | Trident: 76516f68f7d1e267b09d4fd0f02badba5ad56582 26 | 27 | PODFILE CHECKSUM: 8e005d863a1255d6bc0a9f81f145a8d3a9d9b45c 28 | 29 | COCOAPODS: 1.9.3 30 | -------------------------------------------------------------------------------- /README-CHINESE.md: -------------------------------------------------------------------------------- 1 | # Shazam 2 | 3 | ![License MIT](https://img.shields.io/dub/l/vibe-d.svg) 4 | ![Pod version](http://img.shields.io/cocoapods/v/Shazam.svg?style=flat) 5 | ![Platform info](http://img.shields.io/cocoapods/p/LCNetwork.svg?style=flat) 6 | [![Support](https://img.shields.io/badge/support-iOS9.0+-blue.svg?style=flat)](https://www.apple.com/nl/ios/) 7 | [![Swift 4.2](https://camo.githubusercontent.com/cc157628e33009bbb18f6e476955a0f641f407d9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53776966742d342e322d6f72616e67652e7376673f7374796c653d666c6174)](https://developer.apple.com/swift/) 8 | 9 | A pure-Swift library for nested display of horizontal and vertical scrolling views. 10 | 11 | ![demo](./demo.gif) 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 'Shazam' 29 | ``` 30 | 31 | ## Usage 32 | 33 | 首先需要导入 Shazam 34 | 35 | ``` 36 | import Shazam 37 | ``` 38 | 39 | 40 | 41 | #### 创建 ShazamPageViewController 子类 42 | 43 | ```swift 44 | import Shazam 45 | 46 | class PageViewController: ShazamPageViewController { 47 | // ... 48 | } 49 | ``` 50 | 51 | #### 重写协议方法以提供 viewController 和相应的数量 52 | 53 | ```swift 54 | override func numberOfViewControllers(in pageController: ShazamPageViewController) -> Int { 55 | return count 56 | } 57 | 58 | override func pageController(_ pageController: ShazamPageViewController, viewControllerAt index: Int) -> (UIViewController & ShazamChildViewController) { 59 | // ... 60 | return viewController 61 | } 62 | 63 | ``` 64 | 65 | 所提供的 viewController 必须都遵守 `ShazamChildViewController` 协议,并实现 `func shazamChildScrollView() -> UIScrollView` 方法 66 | 67 | ```swift 68 | import Shazam 69 | class ChildViewController: UIViewController, ShazamChildViewController { 70 | 71 | @IBOutlet weak var tableView: UITableView! 72 | func shazamChildScrollView() -> UIScrollView { 73 | return tableView 74 | } 75 | // ... 76 | } 77 | ``` 78 | 79 | **注意:ChildViewController 的 scrollview 必须在顶部预留 headerView + menuView 的高度,比如在 Demo 里的 BatmanViewController,就需要设置 collectionView 的 Header 高度** 80 | 81 | ```swift 82 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 83 | guard let pageViewContoller = szPageViewContoller else { 84 | return .zero 85 | } 86 | let headerViewHeight = pageViewContoller.headerViewHeightFor(pageViewContoller) 87 | let menuViewHeight = pageViewContoller.menuViewHeightFor(pageViewContoller) 88 | return CGSize(width: collectionView.bounds.width, height: headerViewHeight + menuViewHeight) 89 | } 90 | ``` 91 | 92 | 93 | 94 | #### 重写协议方法以提供 headerView 及其高度 95 | 96 | ```swift 97 | override func headerViewFor(_ pageController: ShazamPageViewController) -> UIView { 98 | return HeaderView() 99 | } 100 | 101 | override func headerViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 102 | return headerViewHeight 103 | } 104 | ``` 105 | 106 | 而且 HeaderView 必须遵守 `ShazamHeaderView` 协议,并实现 `func userInteractionViews() -> [UIView]?` 方法 107 | 108 | ```swift 109 | func userInteractionViews() -> [UIView]? { 110 | return [button] 111 | } 112 | ``` 113 | 114 | #### 重写协议方法以提供 menuView 及其高度 115 | 116 | ```swift 117 | override func menuViewFor(_ pageController: ShazamPageViewController) -> UIView { 118 | return menuView 119 | } 120 | 121 | override func menuViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 122 | return menuViewHeight 123 | } 124 | ``` 125 | 126 | 考虑到有时候 menuView 需要高度的定制性,所以设计成由开发者自行提供(demo 中有 menuView 的实现方法)。 127 | 128 | #### 更新 menuView 的布局 129 | 130 | ```swift 131 | override func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) { 132 | menuView.updateLayout(scrollView) 133 | } 134 | 135 | override func pageController(_ pageController: ShazamPageViewController, 136 | mainScrollViewDidEndScroll scrollView: UIScrollView) { 137 | menuView.checkState() 138 | } 139 | ``` 140 | 141 | 包括在内容的滚动的时候和停止滚动的时候,具体可参考 demo 142 | 143 | ## Examples 144 | 145 | Follow these 4 steps to run Example project: 146 | 147 | 1. Clone Shazam repository 148 | 2. Run the `pod install` Shazam 149 | 3. Open Shazam workspace 150 | 4. Run the Shazam-Demo project. 151 | 152 | ### License 153 | 154 | Shazam is released under the MIT license. See LICENSE for details. 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shazam 2 | 3 | ![License MIT](https://img.shields.io/dub/l/vibe-d.svg) 4 | ![Pod version](http://img.shields.io/cocoapods/v/Shazam.svg?style=flat) 5 | ![Platform info](http://img.shields.io/cocoapods/p/LCNetwork.svg?style=flat) 6 | [![Support](https://img.shields.io/badge/support-iOS9.0+-blue.svg?style=flat)](https://www.apple.com/nl/ios/) 7 | [![Swift 4.2](https://camo.githubusercontent.com/cc157628e33009bbb18f6e476955a0f641f407d9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53776966742d342e322d6f72616e67652e7376673f7374796c653d666c6174)](https://developer.apple.com/swift/) 8 | 9 | A pure-Swift library for nested display of horizontal and vertical scrolling views. 10 | 11 | ![demo](./demo.gif) 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 'Shazam' 29 | ``` 30 | 31 | ## Usage 32 | 33 | [中文文档](https://github.com/bawn/Shazam/blob/master/README-CHINESE.md) 34 | 35 | First make sure to import the framework: 36 | 37 | ``` 38 | import Shazam 39 | ``` 40 | 41 | Basically, we just need to provide the list of child view controllers to show. Then call some necessary methods. 42 | 43 | Let's see the steps to do this: 44 | 45 | #### Create a ShazamPageViewController subclass 46 | 47 | ```swift 48 | import Shazam 49 | 50 | class PageViewController: ShazamPageViewController { 51 | // ... 52 | } 53 | ``` 54 | 55 | #### Provide the view controllers that will appear embedded into the ShazamPageViewController 56 | 57 | ```swift 58 | override func numberOfViewControllers(in pageController: ShazamPageViewController) -> Int { 59 | return count 60 | } 61 | 62 | override func pageController(_ pageController: ShazamPageViewController, viewControllerAt index: Int) -> (UIViewController & ShazamChildViewController) { 63 | // ... 64 | return viewController 65 | } 66 | 67 | ``` 68 | 69 | Every UIViewController that will appear within the ShazamPageViewController should conform to `ShazamChildViewController` by implementing `func shazamChildScrollView() -> UIScrollView` 70 | 71 | ```swift 72 | import Shazam 73 | class ChildViewController: UIViewController, ShazamChildViewController { 74 | 75 | @IBOutlet weak var tableView: UITableView! 76 | func shazamChildScrollView() -> UIScrollView { 77 | return tableView 78 | } 79 | // ... 80 | } 81 | ``` 82 | 83 | **Note: The scrollview of ChildViewController must reserve the height of headerView + menuView at the top. For example, in BatmanViewController in Demo, you need to set the height of Header of collectionView.** 84 | 85 | ```swift 86 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 87 | guard let pageViewContoller = szPageViewContoller else { 88 | return .zero 89 | } 90 | let headerViewHeight = pageViewContoller.headerViewHeightFor(pageViewContoller) 91 | let menuViewHeight = pageViewContoller.menuViewHeightFor(pageViewContoller) 92 | return CGSize(width: collectionView.bounds.width, height: headerViewHeight + menuViewHeight) 93 | } 94 | ``` 95 | 96 | 97 | 98 | #### Provide the headerView and headerView height 99 | 100 | ```swift 101 | override func headerViewFor(_ pageController: ShazamPageViewController) -> UIView & ShazamHeaderView { 102 | return HeaderView() 103 | } 104 | 105 | override func headerViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 106 | return headerViewHeight 107 | } 108 | ``` 109 | 110 | The headerView should conform to `ShazamHeaderView` by implementing `func userInteractionViews() -> [UIView]?` 111 | 112 | ```swift 113 | func userInteractionViews() -> [UIView]? { 114 | return [button] 115 | } 116 | ``` 117 | 118 | #### Provide the menuView and menuView height 119 | 120 | ```swift 121 | override func menuViewFor(_ pageController: ShazamPageViewController) -> UIView { 122 | return menuView 123 | } 124 | 125 | override func menuViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 126 | return menuViewHeight 127 | } 128 | ``` 129 | 130 | #### Update menuView's layout when main scroll view did scroll and check state when did end scoll 131 | 132 | ```swift 133 | override func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) { 134 | menuView.updateLayout(scrollView) 135 | } 136 | 137 | override func pageController(_ pageController: ShazamPageViewController, 138 | mainScrollViewDidEndScroll scrollView: UIScrollView) { 139 | menuView.checkState() 140 | } 141 | ``` 142 | 143 | 144 | 145 | ## Examples 146 | 147 | Follow these 4 steps to run Example project: 148 | 149 | 1. Clone Shazam repository 150 | 2. Run the `pod install` command 151 | 3. Open Shazam workspace 152 | 4. Run the Shazam-Demo project. 153 | 154 | ### License 155 | 156 | Shazam is released under the MIT license. See LICENSE for details. 157 | -------------------------------------------------------------------------------- /Shazam-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3AD48766E9FD9720EECE84E1 /* Pods_Shazam_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3331F2A2889E34EFE6A2248E /* Pods_Shazam_Demo.framework */; }; 11 | DF11ABBE2230DFDB00D97FF1 /* Shazam.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF11ABBD2230DFDB00D97FF1 /* Shazam.framework */; }; 12 | DF4E92FD221FFF1300ECDEB2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92FC221FFF1300ECDEB2 /* AppDelegate.swift */; }; 13 | DF4E92FF221FFF1300ECDEB2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92FE221FFF1300ECDEB2 /* ViewController.swift */; }; 14 | DF4E9302221FFF1300ECDEB2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DF4E9300221FFF1300ECDEB2 /* Main.storyboard */; }; 15 | DF4E9304221FFF1400ECDEB2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DF4E9303221FFF1400ECDEB2 /* Assets.xcassets */; }; 16 | DF4E9307221FFF1400ECDEB2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DF4E9305221FFF1400ECDEB2 /* LaunchScreen.storyboard */; }; 17 | DF4E932A2220011800ECDEB2 /* PageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E93292220011800ECDEB2 /* PageViewController.swift */; }; 18 | DF4E932C2220012500ECDEB2 /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E932B2220012500ECDEB2 /* HeaderView.swift */; }; 19 | DF4E93302220013000ECDEB2 /* WonderWomanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E932D2220013000ECDEB2 /* WonderWomanViewController.swift */; }; 20 | DF4E93312220013000ECDEB2 /* SupermanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E932E2220013000ECDEB2 /* SupermanViewController.swift */; }; 21 | DF4E93322220013000ECDEB2 /* BatmanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E932F2220013000ECDEB2 /* BatmanViewController.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | 3331F2A2889E34EFE6A2248E /* Pods_Shazam_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Shazam_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 628512E47EE97318ADF10243 /* Pods-Shazam-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shazam-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo.release.xcconfig"; sourceTree = ""; }; 27 | DF11ABBD2230DFDB00D97FF1 /* Shazam.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Shazam.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | DF4E92F9221FFF1300ECDEB2 /* Shazam-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Shazam-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | DF4E92FC221FFF1300ECDEB2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 30 | DF4E92FE221FFF1300ECDEB2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 31 | DF4E9301221FFF1300ECDEB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 32 | DF4E9303221FFF1400ECDEB2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | DF4E9306221FFF1400ECDEB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 34 | DF4E9308221FFF1400ECDEB2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | DF4E93292220011800ECDEB2 /* PageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageViewController.swift; sourceTree = ""; }; 36 | DF4E932B2220012500ECDEB2 /* HeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; }; 37 | DF4E932D2220013000ECDEB2 /* WonderWomanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WonderWomanViewController.swift; sourceTree = ""; }; 38 | DF4E932E2220013000ECDEB2 /* SupermanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupermanViewController.swift; sourceTree = ""; }; 39 | DF4E932F2220013000ECDEB2 /* BatmanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatmanViewController.swift; sourceTree = ""; }; 40 | EFD61C808D23695D9BD2D14F /* Pods-Shazam-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shazam-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo.debug.xcconfig"; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | DF4E92F6221FFF1300ECDEB2 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | DF11ABBE2230DFDB00D97FF1 /* Shazam.framework in Frameworks */, 49 | 3AD48766E9FD9720EECE84E1 /* Pods_Shazam_Demo.framework in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 262295EA9F8F472588602B38 /* Frameworks */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | DF11ABBD2230DFDB00D97FF1 /* Shazam.framework */, 60 | 3331F2A2889E34EFE6A2248E /* Pods_Shazam_Demo.framework */, 61 | ); 62 | name = Frameworks; 63 | sourceTree = ""; 64 | }; 65 | DF4E92F0221FFF1300ECDEB2 = { 66 | isa = PBXGroup; 67 | children = ( 68 | DF4E92FB221FFF1300ECDEB2 /* Shazam-Demo */, 69 | DF4E92FA221FFF1300ECDEB2 /* Products */, 70 | E61A2B841DB466091078F444 /* Pods */, 71 | 262295EA9F8F472588602B38 /* Frameworks */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | DF4E92FA221FFF1300ECDEB2 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | DF4E92F9221FFF1300ECDEB2 /* Shazam-Demo.app */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | DF4E92FB221FFF1300ECDEB2 /* Shazam-Demo */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | DF4E92FC221FFF1300ECDEB2 /* AppDelegate.swift */, 87 | DF4E92FE221FFF1300ECDEB2 /* ViewController.swift */, 88 | DF4E932B2220012500ECDEB2 /* HeaderView.swift */, 89 | DF4E93292220011800ECDEB2 /* PageViewController.swift */, 90 | DF4E932F2220013000ECDEB2 /* BatmanViewController.swift */, 91 | DF4E932E2220013000ECDEB2 /* SupermanViewController.swift */, 92 | DF4E932D2220013000ECDEB2 /* WonderWomanViewController.swift */, 93 | DF4E9300221FFF1300ECDEB2 /* Main.storyboard */, 94 | DF4E9303221FFF1400ECDEB2 /* Assets.xcassets */, 95 | DF4E9305221FFF1400ECDEB2 /* LaunchScreen.storyboard */, 96 | DF4E9308221FFF1400ECDEB2 /* Info.plist */, 97 | ); 98 | path = "Shazam-Demo"; 99 | sourceTree = ""; 100 | }; 101 | E61A2B841DB466091078F444 /* Pods */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | EFD61C808D23695D9BD2D14F /* Pods-Shazam-Demo.debug.xcconfig */, 105 | 628512E47EE97318ADF10243 /* Pods-Shazam-Demo.release.xcconfig */, 106 | ); 107 | name = Pods; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | DF4E92F8221FFF1300ECDEB2 /* Shazam-Demo */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = DF4E930B221FFF1400ECDEB2 /* Build configuration list for PBXNativeTarget "Shazam-Demo" */; 116 | buildPhases = ( 117 | 422F087A4661E121A7ACC4AB /* [CP] Check Pods Manifest.lock */, 118 | 2E34BA500AEE8238E21544FB /* [CP] Prepare Artifacts */, 119 | DF4E92F5221FFF1300ECDEB2 /* Sources */, 120 | DF4E92F6221FFF1300ECDEB2 /* Frameworks */, 121 | DF4E92F7221FFF1300ECDEB2 /* Resources */, 122 | E428F3492C9FDF1F3555EAFA /* [CP] Embed Pods Frameworks */, 123 | ); 124 | buildRules = ( 125 | ); 126 | dependencies = ( 127 | ); 128 | name = "Shazam-Demo"; 129 | productName = "Shazam-Demo"; 130 | productReference = DF4E92F9221FFF1300ECDEB2 /* Shazam-Demo.app */; 131 | productType = "com.apple.product-type.application"; 132 | }; 133 | /* End PBXNativeTarget section */ 134 | 135 | /* Begin PBXProject section */ 136 | DF4E92F1221FFF1300ECDEB2 /* Project object */ = { 137 | isa = PBXProject; 138 | attributes = { 139 | LastSwiftUpdateCheck = 1010; 140 | LastUpgradeCheck = 1010; 141 | ORGANIZATIONNAME = bawn; 142 | TargetAttributes = { 143 | DF4E92F8221FFF1300ECDEB2 = { 144 | CreatedOnToolsVersion = 10.1; 145 | }; 146 | }; 147 | }; 148 | buildConfigurationList = DF4E92F4221FFF1300ECDEB2 /* Build configuration list for PBXProject "Shazam-Demo" */; 149 | compatibilityVersion = "Xcode 9.3"; 150 | developmentRegion = en; 151 | hasScannedForEncodings = 0; 152 | knownRegions = ( 153 | en, 154 | Base, 155 | ); 156 | mainGroup = DF4E92F0221FFF1300ECDEB2; 157 | productRefGroup = DF4E92FA221FFF1300ECDEB2 /* Products */; 158 | projectDirPath = ""; 159 | projectRoot = ""; 160 | targets = ( 161 | DF4E92F8221FFF1300ECDEB2 /* Shazam-Demo */, 162 | ); 163 | }; 164 | /* End PBXProject section */ 165 | 166 | /* Begin PBXResourcesBuildPhase section */ 167 | DF4E92F7221FFF1300ECDEB2 /* Resources */ = { 168 | isa = PBXResourcesBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | DF4E9307221FFF1400ECDEB2 /* LaunchScreen.storyboard in Resources */, 172 | DF4E9304221FFF1400ECDEB2 /* Assets.xcassets in Resources */, 173 | DF4E9302221FFF1300ECDEB2 /* Main.storyboard in Resources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXResourcesBuildPhase section */ 178 | 179 | /* Begin PBXShellScriptBuildPhase section */ 180 | 2E34BA500AEE8238E21544FB /* [CP] Prepare Artifacts */ = { 181 | isa = PBXShellScriptBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | ); 185 | inputFileListPaths = ( 186 | "${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-artifacts-${CONFIGURATION}-input-files.xcfilelist", 187 | ); 188 | name = "[CP] Prepare Artifacts"; 189 | outputFileListPaths = ( 190 | "${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-artifacts-${CONFIGURATION}-output-files.xcfilelist", 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | shellPath = /bin/sh; 194 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-artifacts.sh\"\n"; 195 | showEnvVarsInLog = 0; 196 | }; 197 | 422F087A4661E121A7ACC4AB /* [CP] Check Pods Manifest.lock */ = { 198 | isa = PBXShellScriptBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | ); 202 | inputFileListPaths = ( 203 | ); 204 | inputPaths = ( 205 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 206 | "${PODS_ROOT}/Manifest.lock", 207 | ); 208 | name = "[CP] Check Pods Manifest.lock"; 209 | outputFileListPaths = ( 210 | ); 211 | outputPaths = ( 212 | "$(DERIVED_FILE_DIR)/Pods-Shazam-Demo-checkManifestLockResult.txt", 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | shellPath = /bin/sh; 216 | 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"; 217 | showEnvVarsInLog = 0; 218 | }; 219 | E428F3492C9FDF1F3555EAFA /* [CP] Embed Pods Frameworks */ = { 220 | isa = PBXShellScriptBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ); 224 | inputFileListPaths = ( 225 | "${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-frameworks-${CONFIGURATION}-input-files.xcfilelist", 226 | ); 227 | name = "[CP] Embed Pods Frameworks"; 228 | outputFileListPaths = ( 229 | "${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-frameworks-${CONFIGURATION}-output-files.xcfilelist", 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | shellPath = /bin/sh; 233 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Shazam-Demo/Pods-Shazam-Demo-frameworks.sh\"\n"; 234 | showEnvVarsInLog = 0; 235 | }; 236 | /* End PBXShellScriptBuildPhase section */ 237 | 238 | /* Begin PBXSourcesBuildPhase section */ 239 | DF4E92F5221FFF1300ECDEB2 /* Sources */ = { 240 | isa = PBXSourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | DF4E93302220013000ECDEB2 /* WonderWomanViewController.swift in Sources */, 244 | DF4E932A2220011800ECDEB2 /* PageViewController.swift in Sources */, 245 | DF4E92FF221FFF1300ECDEB2 /* ViewController.swift in Sources */, 246 | DF4E92FD221FFF1300ECDEB2 /* AppDelegate.swift in Sources */, 247 | DF4E932C2220012500ECDEB2 /* HeaderView.swift in Sources */, 248 | DF4E93322220013000ECDEB2 /* BatmanViewController.swift in Sources */, 249 | DF4E93312220013000ECDEB2 /* SupermanViewController.swift in Sources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | /* End PBXSourcesBuildPhase section */ 254 | 255 | /* Begin PBXVariantGroup section */ 256 | DF4E9300221FFF1300ECDEB2 /* Main.storyboard */ = { 257 | isa = PBXVariantGroup; 258 | children = ( 259 | DF4E9301221FFF1300ECDEB2 /* Base */, 260 | ); 261 | name = Main.storyboard; 262 | sourceTree = ""; 263 | }; 264 | DF4E9305221FFF1400ECDEB2 /* LaunchScreen.storyboard */ = { 265 | isa = PBXVariantGroup; 266 | children = ( 267 | DF4E9306221FFF1400ECDEB2 /* Base */, 268 | ); 269 | name = LaunchScreen.storyboard; 270 | sourceTree = ""; 271 | }; 272 | /* End PBXVariantGroup section */ 273 | 274 | /* Begin XCBuildConfiguration section */ 275 | DF4E9309221FFF1400ECDEB2 /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_ANALYZER_NONNULL = YES; 280 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 282 | CLANG_CXX_LIBRARY = "libc++"; 283 | CLANG_ENABLE_MODULES = YES; 284 | CLANG_ENABLE_OBJC_ARC = YES; 285 | CLANG_ENABLE_OBJC_WEAK = YES; 286 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 287 | CLANG_WARN_BOOL_CONVERSION = YES; 288 | CLANG_WARN_COMMA = YES; 289 | CLANG_WARN_CONSTANT_CONVERSION = YES; 290 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 291 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 292 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 293 | CLANG_WARN_EMPTY_BODY = YES; 294 | CLANG_WARN_ENUM_CONVERSION = YES; 295 | CLANG_WARN_INFINITE_RECURSION = YES; 296 | CLANG_WARN_INT_CONVERSION = YES; 297 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 298 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 299 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 300 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 302 | CLANG_WARN_STRICT_PROTOTYPES = YES; 303 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 304 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | CODE_SIGN_IDENTITY = "iPhone Developer"; 308 | COPY_PHASE_STRIP = NO; 309 | DEBUG_INFORMATION_FORMAT = dwarf; 310 | ENABLE_STRICT_OBJC_MSGSEND = YES; 311 | ENABLE_TESTABILITY = YES; 312 | GCC_C_LANGUAGE_STANDARD = gnu11; 313 | GCC_DYNAMIC_NO_PIC = NO; 314 | GCC_NO_COMMON_BLOCKS = YES; 315 | GCC_OPTIMIZATION_LEVEL = 0; 316 | GCC_PREPROCESSOR_DEFINITIONS = ( 317 | "DEBUG=1", 318 | "$(inherited)", 319 | ); 320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 322 | GCC_WARN_UNDECLARED_SELECTOR = YES; 323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 324 | GCC_WARN_UNUSED_FUNCTION = YES; 325 | GCC_WARN_UNUSED_VARIABLE = YES; 326 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 327 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 328 | MTL_FAST_MATH = YES; 329 | ONLY_ACTIVE_ARCH = YES; 330 | SDKROOT = iphoneos; 331 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 332 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 333 | }; 334 | name = Debug; 335 | }; 336 | DF4E930A221FFF1400ECDEB2 /* Release */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | ALWAYS_SEARCH_USER_PATHS = NO; 340 | CLANG_ANALYZER_NONNULL = YES; 341 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 342 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 343 | CLANG_CXX_LIBRARY = "libc++"; 344 | CLANG_ENABLE_MODULES = YES; 345 | CLANG_ENABLE_OBJC_ARC = YES; 346 | CLANG_ENABLE_OBJC_WEAK = YES; 347 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 348 | CLANG_WARN_BOOL_CONVERSION = YES; 349 | CLANG_WARN_COMMA = YES; 350 | CLANG_WARN_CONSTANT_CONVERSION = YES; 351 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 352 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 353 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 354 | CLANG_WARN_EMPTY_BODY = YES; 355 | CLANG_WARN_ENUM_CONVERSION = YES; 356 | CLANG_WARN_INFINITE_RECURSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 359 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 360 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 361 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 362 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 363 | CLANG_WARN_STRICT_PROTOTYPES = YES; 364 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 365 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | CODE_SIGN_IDENTITY = "iPhone Developer"; 369 | COPY_PHASE_STRIP = NO; 370 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 371 | ENABLE_NS_ASSERTIONS = NO; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | GCC_C_LANGUAGE_STANDARD = gnu11; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 376 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 377 | GCC_WARN_UNDECLARED_SELECTOR = YES; 378 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 379 | GCC_WARN_UNUSED_FUNCTION = YES; 380 | GCC_WARN_UNUSED_VARIABLE = YES; 381 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 382 | MTL_ENABLE_DEBUG_INFO = NO; 383 | MTL_FAST_MATH = YES; 384 | SDKROOT = iphoneos; 385 | SWIFT_COMPILATION_MODE = wholemodule; 386 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 387 | VALIDATE_PRODUCT = YES; 388 | }; 389 | name = Release; 390 | }; 391 | DF4E930C221FFF1400ECDEB2 /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | baseConfigurationReference = EFD61C808D23695D9BD2D14F /* Pods-Shazam-Demo.debug.xcconfig */; 394 | buildSettings = { 395 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 396 | CODE_SIGN_STYLE = Automatic; 397 | INFOPLIST_FILE = "Shazam-Demo/Info.plist"; 398 | LD_RUNPATH_SEARCH_PATHS = ( 399 | "$(inherited)", 400 | "@executable_path/Frameworks", 401 | ); 402 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Shazam-Demo"; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SWIFT_VERSION = 4.2; 405 | TARGETED_DEVICE_FAMILY = "1,2"; 406 | }; 407 | name = Debug; 408 | }; 409 | DF4E930D221FFF1400ECDEB2 /* Release */ = { 410 | isa = XCBuildConfiguration; 411 | baseConfigurationReference = 628512E47EE97318ADF10243 /* Pods-Shazam-Demo.release.xcconfig */; 412 | buildSettings = { 413 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 414 | CODE_SIGN_STYLE = Automatic; 415 | INFOPLIST_FILE = "Shazam-Demo/Info.plist"; 416 | LD_RUNPATH_SEARCH_PATHS = ( 417 | "$(inherited)", 418 | "@executable_path/Frameworks", 419 | ); 420 | PRODUCT_BUNDLE_IDENTIFIER = "bawn.Shazam-Demo"; 421 | PRODUCT_NAME = "$(TARGET_NAME)"; 422 | SWIFT_VERSION = 4.2; 423 | TARGETED_DEVICE_FAMILY = "1,2"; 424 | }; 425 | name = Release; 426 | }; 427 | /* End XCBuildConfiguration section */ 428 | 429 | /* Begin XCConfigurationList section */ 430 | DF4E92F4221FFF1300ECDEB2 /* Build configuration list for PBXProject "Shazam-Demo" */ = { 431 | isa = XCConfigurationList; 432 | buildConfigurations = ( 433 | DF4E9309221FFF1400ECDEB2 /* Debug */, 434 | DF4E930A221FFF1400ECDEB2 /* Release */, 435 | ); 436 | defaultConfigurationIsVisible = 0; 437 | defaultConfigurationName = Release; 438 | }; 439 | DF4E930B221FFF1400ECDEB2 /* Build configuration list for PBXNativeTarget "Shazam-Demo" */ = { 440 | isa = XCConfigurationList; 441 | buildConfigurations = ( 442 | DF4E930C221FFF1400ECDEB2 /* Debug */, 443 | DF4E930D221FFF1400ECDEB2 /* Release */, 444 | ); 445 | defaultConfigurationIsVisible = 0; 446 | defaultConfigurationName = Release; 447 | }; 448 | /* End XCConfigurationList section */ 449 | }; 450 | rootObject = DF4E92F1221FFF1300ECDEB2 /* Project object */; 451 | } 452 | -------------------------------------------------------------------------------- /Shazam-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Shazam-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Shazam-Demo.xcodeproj/project.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bawn/Shazam/a3f3e6a34fa4750d6e365829d5ec1f3bb6440b3e/Shazam-Demo.xcodeproj/project.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Shazam-Demo.xcodeproj/xcuserdata/bawn.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Shazam-Demo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 7 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Shazam-Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Shazam-Demo 4 | // 5 | // Created by bawn on 2019/2/22. 6 | // Copyright © 2019 bawn. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Shazam-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 | } -------------------------------------------------------------------------------- /Shazam-Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Shazam-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 | -------------------------------------------------------------------------------- /Shazam-Demo/Base.lproj/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 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 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 | 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 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 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 | -------------------------------------------------------------------------------- /Shazam-Demo/BatmanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BatmanViewController.swift 3 | // Shazam-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 Shazam 28 | 29 | class BatmanViewController: UIViewController, ShazamChildViewController { 30 | @IBOutlet weak var collectionView: UICollectionView! 31 | var selectedIndex = 0 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | collectionView.alwaysBounceVertical = true 36 | if selectedIndex == 0 { 37 | if #available(iOS 11.0, *) { 38 | collectionView.contentInsetAdjustmentBehavior = .never 39 | } else { 40 | automaticallyAdjustsScrollViewInsets = false 41 | } 42 | } 43 | } 44 | 45 | func shazamChildScrollView() -> UIScrollView { 46 | return collectionView 47 | } 48 | 49 | 50 | override func viewWillAppear(_ animated: Bool) { 51 | super.viewWillAppear(animated) 52 | } 53 | 54 | override func viewDidAppear(_ animated: Bool) { 55 | super.viewDidAppear(animated) 56 | } 57 | 58 | } 59 | 60 | extension BatmanViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 61 | 62 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 63 | return 12 64 | } 65 | 66 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 67 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) 68 | return cell 69 | } 70 | 71 | 72 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 73 | return 12 74 | } 75 | 76 | 77 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 78 | return 12 79 | } 80 | 81 | 82 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 83 | return UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12) 84 | } 85 | 86 | 87 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 88 | let width = floor((collectionView.bounds.width - 12.0 * 3.0) * 0.5) 89 | return CGSize(width: width, height: width) 90 | } 91 | 92 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 93 | collectionView.deselectItem(at: indexPath, animated: true) 94 | } 95 | 96 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 97 | if kind == UICollectionView.elementKindSectionHeader { 98 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "Header", for: indexPath) 99 | return headerView 100 | } else { 101 | let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "Footer", for: indexPath) 102 | return footerView 103 | } 104 | } 105 | 106 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 107 | guard let pageViewContoller = szPageViewContoller else { 108 | return .zero 109 | } 110 | let headerViewHeight = pageViewContoller.headerViewHeightFor(pageViewContoller) 111 | let menuViewHeight = pageViewContoller.menuViewHeightFor(pageViewContoller) 112 | return CGSize(width: collectionView.bounds.width, height: headerViewHeight + menuViewHeight) 113 | } 114 | 115 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { 116 | return .zero 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Shazam-Demo/HeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeaderView.swift 3 | // Shazam-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 | import SnapKit 28 | import Shazam 29 | 30 | class HeaderView: UIView, ShazamHeaderView { 31 | 32 | let button = UIButton() 33 | 34 | override init(frame: CGRect) { 35 | super.init(frame: frame) 36 | backgroundColor = .cyan 37 | addSubview(button) 38 | button.backgroundColor = .blue 39 | button.snp.makeConstraints { (make) in 40 | make.center.equalToSuperview() 41 | make.size.equalTo(CGSize(width: 60, height: 40)) 42 | } 43 | } 44 | 45 | func userInteractionViews() -> [UIView]? { 46 | return [button] 47 | } 48 | 49 | required init?(coder aDecoder: NSCoder) { 50 | super.init(coder: aDecoder) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Shazam-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 | -------------------------------------------------------------------------------- /Shazam-Demo/PageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageViewController.swift 3 | // Shazam-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 Shazam 28 | import Trident 29 | 30 | class PageViewController: ShazamPageViewController { 31 | 32 | let navBar = UIView() 33 | let headerView = HeaderView() 34 | lazy var menuView: TridentMenuView = { 35 | let view = TridentMenuView(parts: 36 | .normalTextColor(UIColor.gray), 37 | .selectedTextColor(UIColor.blue), 38 | .normalTextFont(UIFont.systemFont(ofSize: 15, weight: .regular)), 39 | .selectedTextFont(UIFont.systemFont(ofSize: 15, 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(4.0), 48 | .originWidth(30.0), 49 | .shape(.line), 50 | .elasticValue(1.2) 51 | ) 52 | ) 53 | ) 54 | view.delegate = self 55 | return view 56 | }() 57 | var count = 3 58 | var headerViewHeight: CGFloat = 200.0 59 | var menuViewHeight: CGFloat = 44.0 60 | lazy var selectedIndex = tabBarController?.selectedIndex ?? 0 61 | 62 | override func viewDidLoad() { 63 | super.viewDidLoad() 64 | 65 | view.backgroundColor = .white 66 | headerView.button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside) 67 | // headerView.isHidden = true 68 | menuView.contentInset = UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 24) 69 | 70 | if selectedIndex == 0 { 71 | if #available(iOS 11.0, *) { 72 | mainScrollView.contentInsetAdjustmentBehavior = .never 73 | } else { 74 | automaticallyAdjustsScrollViewInsets = false 75 | } 76 | } 77 | 78 | navigationController?.interactivePopGestureRecognizer?.delegate = nil 79 | 80 | navBar.alpha = 0.0 81 | navBar.backgroundColor = .white 82 | view.addSubview(navBar) 83 | navBar.snp.makeConstraints { (make) in 84 | make.leading.equalToSuperview() 85 | make.top.equalToSuperview() 86 | make.trailing.equalToSuperview() 87 | make.height.equalTo(UIApplication.shared.statusBarFrame.height + 44.0) 88 | } 89 | 90 | menuView.titles = ["Superman", "Batman", "WonderWoman"] 91 | menuView.delegate = self 92 | } 93 | 94 | @objc func buttonAction(_ sender: UIButton) { 95 | print(#function) 96 | } 97 | 98 | override func viewWillAppear(_ animated: Bool) { 99 | super.viewWillAppear(animated) 100 | 101 | if selectedIndex == 0 { 102 | navigationController?.setNavigationBarHidden(true, animated: animated) 103 | } 104 | } 105 | 106 | 107 | override func headerViewFor(_ pageController: ShazamPageViewController) -> UIView & ShazamHeaderView { 108 | return headerView 109 | } 110 | 111 | override func headerViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 112 | return headerViewHeight 113 | } 114 | 115 | override func numberOfViewControllers(in pageController: ShazamPageViewController) -> Int { 116 | return count 117 | } 118 | 119 | override func pageController(_ pageController: ShazamPageViewController, viewControllerAt index: Int) -> (UIViewController & ShazamChildViewController) { 120 | 121 | 122 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 123 | if index == 0 { 124 | let viewController = storyboard.instantiateViewController(withIdentifier: "SupermanViewController") as! SupermanViewController 125 | viewController.selectedIndex = selectedIndex 126 | return viewController 127 | } else if index == 1 { 128 | let viewController = storyboard.instantiateViewController(withIdentifier: "BatmanViewController") as! BatmanViewController 129 | viewController.selectedIndex = selectedIndex 130 | return viewController 131 | } else { 132 | let viewController = storyboard.instantiateViewController(withIdentifier: "WonderWomanViewController") as! WonderWomanViewController 133 | viewController.selectedIndex = selectedIndex 134 | return viewController 135 | } 136 | 137 | } 138 | 139 | 140 | // override func originIndexFor(_ pageController: ShazamPageViewController) -> Int { 141 | // return 2 142 | // } 143 | 144 | override func menuViewFor(_ pageController: ShazamPageViewController) -> UIView { 145 | return menuView 146 | } 147 | 148 | override func menuViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 149 | return menuViewHeight 150 | } 151 | 152 | override func menuViewPinHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 153 | return UIApplication.shared.statusBarFrame.height + 44.0 154 | } 155 | 156 | 157 | override func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) { 158 | menuView.updateLayout(scrollView) 159 | } 160 | 161 | override func pageController(_ pageController: ShazamPageViewController, 162 | mainScrollViewDidEndScroll scrollView: UIScrollView) { 163 | menuView.checkState(animation: true) 164 | } 165 | 166 | override func pageController(_ pageController: ShazamPageViewController, headerView offset: CGPoint, isAdsorption: Bool) { 167 | 168 | let rate = (UIApplication.shared.statusBarFrame.height * 3.0) 169 | navBar.alpha = min(-offset.y / rate, 1.0) 170 | navBar.backgroundColor = isAdsorption ? .blue : .white 171 | } 172 | 173 | override func pageController(_ pageController: ShazamPageViewController, childScrollViewDidScroll scrollView: UIScrollView) { 174 | if scrollView.contentOffset.y == 0 { 175 | navBar.alpha = 0 176 | } 177 | } 178 | 179 | override func keepChildScrollViewOffset(_ pageController: ShazamPageViewController) -> Bool { 180 | return false 181 | // return selectedIndex == 0 ? true : false 182 | } 183 | 184 | override func pageController(_ pageController: ShazamPageViewController, willDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) { 185 | 186 | } 187 | 188 | override func pageController(_ pageController: ShazamPageViewController, didDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) { 189 | } 190 | 191 | deinit { 192 | print(#function) 193 | } 194 | } 195 | 196 | 197 | extension PageViewController: TridentMenuViewDelegate { 198 | func menuView(_ menuView: TridentMenuView, didSelectedItemAt index: Int) { 199 | guard index < count else { 200 | return 201 | } 202 | setSelect(index: index, animation: true) 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /Shazam-Demo/SupermanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SupermanViewController.swift 3 | // Shazam-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 Shazam 28 | import MJRefresh 29 | 30 | class SupermanViewController: UIViewController, ShazamChildViewController { 31 | 32 | @IBOutlet weak var tableView: UITableView! 33 | var selectedIndex = 0 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | if selectedIndex == 0 { 38 | if #available(iOS 11.0, *) { 39 | tableView.contentInsetAdjustmentBehavior = .never 40 | } else { 41 | automaticallyAdjustsScrollViewInsets = false 42 | } 43 | } 44 | 45 | let refreshControl = UIRefreshControl() 46 | tableView.refreshControl = refreshControl 47 | refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged) 48 | } 49 | 50 | @objc private func refresh() { 51 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(6)) { 52 | self.tableView.refreshControl?.endRefreshing() 53 | } 54 | } 55 | 56 | func shazamChildScrollView() -> UIScrollView { 57 | return tableView 58 | } 59 | 60 | override func viewWillAppear(_ animated: Bool) { 61 | super.viewWillAppear(animated) 62 | } 63 | 64 | override func viewDidAppear(_ animated: Bool) { 65 | super.viewDidAppear(animated) 66 | } 67 | } 68 | 69 | 70 | extension SupermanViewController: UITableViewDelegate, UITableViewDataSource { 71 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 72 | return 40 73 | } 74 | 75 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 76 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 77 | cell.textLabel?.text = "\(type(of: self))" + "-" + "\(indexPath.row)" 78 | return cell 79 | } 80 | 81 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 82 | tableView.deselectRow(at: indexPath, animated: true) 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /Shazam-Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Shazam-Demo 4 | // 5 | // Created by bawn on 2019/2/22. 6 | // Copyright © 2019 bawn. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | 19 | @IBAction func buttonAction(_ sender: Any) { 20 | navigationController?.pushViewController(PageViewController(), animated: true) 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Shazam-Demo/WonderWomanViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WonderWomanViewController.swift 3 | // Shazam-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 Shazam 28 | 29 | class WonderWomanViewController: UIViewController, ShazamChildViewController { 30 | 31 | @IBOutlet weak var tableView: UITableView! 32 | var selectedIndex = 0 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | 37 | if selectedIndex == 0 { 38 | if #available(iOS 11.0, *) { 39 | tableView.contentInsetAdjustmentBehavior = .never 40 | } else { 41 | automaticallyAdjustsScrollViewInsets = false 42 | } 43 | } 44 | } 45 | 46 | func shazamChildScrollView() -> UIScrollView { 47 | return tableView 48 | } 49 | } 50 | 51 | extension WonderWomanViewController: UITableViewDelegate, UITableViewDataSource { 52 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 53 | return 40 54 | } 55 | 56 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 57 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 58 | cell.textLabel?.text = "\(type(of: self))" + "-" + "\(indexPath.row)" 59 | return cell 60 | } 61 | 62 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 63 | tableView.deselectRow(at: indexPath, animated: true) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Shazam.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "Shazam" 3 | s.version = "0.0.9" 4 | s.summary = "An easy solution to nested scrolling" 5 | s.homepage = "https://github.com/bawn/Shazam" 6 | s.license = { :type => "MIT", :file => "LICENSE" } 7 | s.authors = { "bawn" => "lc5491137@gmail.com" } 8 | s.swift_version = "4.2" 9 | s.source = { :git => "https://github.com/bawn/Shazam.git", :tag => s.version.to_s } 10 | s.platform = :ios, '9.0' 11 | s.requires_arc = true 12 | s.source_files = ["Shazam/*.swift", "Shazam/Shazam.h"] 13 | end 14 | -------------------------------------------------------------------------------- /Shazam.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 144107FDADD1624C653AEC13 /* Pods_Shazam.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F11FC9459A12BA37955AC712 /* Pods_Shazam.framework */; }; 11 | DF4E92B4221EDA5700ECDEB2 /* Shazam.h in Headers */ = {isa = PBXBuildFile; fileRef = DF4E92B2221EDA5700ECDEB2 /* Shazam.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | DF4E92C0221EDAB300ECDEB2 /* ShazamPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BA221EDAB300ECDEB2 /* ShazamPageViewController.swift */; }; 13 | DF4E92C1221EDAB300ECDEB2 /* ShazamChildViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BB221EDAB300ECDEB2 /* ShazamChildViewController.swift */; }; 14 | DF4E92C2221EDAB300ECDEB2 /* ShazamHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BC221EDAB300ECDEB2 /* ShazamHeaderView.swift */; }; 15 | DF4E92C3221EDAB300ECDEB2 /* ShazamContainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BD221EDAB300ECDEB2 /* ShazamContainView.swift */; }; 16 | DF4E92C4221EDAB300ECDEB2 /* ShazamTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BE221EDAB300ECDEB2 /* ShazamTopView.swift */; }; 17 | DF4E92C5221EDAB300ECDEB2 /* NSCache+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92BF221EDAB300ECDEB2 /* NSCache+Additional.swift */; }; 18 | DF4E92C7221EDAC100ECDEB2 /* UIScrollView+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92C6221EDAC100ECDEB2 /* UIScrollView+Additional.swift */; }; 19 | DF4E92C9221EDAC600ECDEB2 /* UIViewController+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4E92C8221EDAC600ECDEB2 /* UIViewController+Additional.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | AA9E95405942883CCAA6E15C /* Pods-Shazam.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shazam.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Shazam/Pods-Shazam.debug.xcconfig"; sourceTree = ""; }; 24 | B11CC81FF19CDF259B1158AA /* Pods-Shazam.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shazam.release.xcconfig"; path = "Pods/Target Support Files/Pods-Shazam/Pods-Shazam.release.xcconfig"; sourceTree = ""; }; 25 | DF4E92AF221EDA5700ECDEB2 /* Shazam.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Shazam.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | DF4E92B2221EDA5700ECDEB2 /* Shazam.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Shazam.h; sourceTree = ""; }; 27 | DF4E92B3221EDA5700ECDEB2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | DF4E92BA221EDAB300ECDEB2 /* ShazamPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamPageViewController.swift; sourceTree = ""; }; 29 | DF4E92BB221EDAB300ECDEB2 /* ShazamChildViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamChildViewController.swift; sourceTree = ""; }; 30 | DF4E92BC221EDAB300ECDEB2 /* ShazamHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamHeaderView.swift; sourceTree = ""; }; 31 | DF4E92BD221EDAB300ECDEB2 /* ShazamContainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamContainView.swift; sourceTree = ""; }; 32 | DF4E92BE221EDAB300ECDEB2 /* ShazamTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamTopView.swift; sourceTree = ""; }; 33 | DF4E92BF221EDAB300ECDEB2 /* NSCache+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCache+Additional.swift"; sourceTree = ""; }; 34 | DF4E92C6221EDAC100ECDEB2 /* UIScrollView+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScrollView+Additional.swift"; sourceTree = ""; }; 35 | DF4E92C8221EDAC600ECDEB2 /* UIViewController+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Additional.swift"; sourceTree = ""; }; 36 | F11FC9459A12BA37955AC712 /* Pods_Shazam.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Shazam.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | DF4E92AC221EDA5700ECDEB2 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | 144107FDADD1624C653AEC13 /* Pods_Shazam.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 4B912D39343B1F7808FCC780 /* Pods */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | AA9E95405942883CCAA6E15C /* Pods-Shazam.debug.xcconfig */, 55 | B11CC81FF19CDF259B1158AA /* Pods-Shazam.release.xcconfig */, 56 | ); 57 | name = Pods; 58 | sourceTree = ""; 59 | }; 60 | D28274561A784C3C16784AFB /* Frameworks */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | F11FC9459A12BA37955AC712 /* Pods_Shazam.framework */, 64 | ); 65 | name = Frameworks; 66 | sourceTree = ""; 67 | }; 68 | DF4E92A5221EDA5700ECDEB2 = { 69 | isa = PBXGroup; 70 | children = ( 71 | DF4E92B1221EDA5700ECDEB2 /* Shazam */, 72 | DF4E92B0221EDA5700ECDEB2 /* Products */, 73 | 4B912D39343B1F7808FCC780 /* Pods */, 74 | D28274561A784C3C16784AFB /* Frameworks */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | DF4E92B0221EDA5700ECDEB2 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | DF4E92AF221EDA5700ECDEB2 /* Shazam.framework */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | DF4E92B1221EDA5700ECDEB2 /* Shazam */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | DF4E92BF221EDAB300ECDEB2 /* NSCache+Additional.swift */, 90 | DF4E92BB221EDAB300ECDEB2 /* ShazamChildViewController.swift */, 91 | DF4E92BD221EDAB300ECDEB2 /* ShazamContainView.swift */, 92 | DF4E92BC221EDAB300ECDEB2 /* ShazamHeaderView.swift */, 93 | DF4E92BA221EDAB300ECDEB2 /* ShazamPageViewController.swift */, 94 | DF4E92BE221EDAB300ECDEB2 /* ShazamTopView.swift */, 95 | DF4E92C6221EDAC100ECDEB2 /* UIScrollView+Additional.swift */, 96 | DF4E92C8221EDAC600ECDEB2 /* UIViewController+Additional.swift */, 97 | DF4E92B2221EDA5700ECDEB2 /* Shazam.h */, 98 | DF4E92B3221EDA5700ECDEB2 /* Info.plist */, 99 | ); 100 | path = Shazam; 101 | sourceTree = ""; 102 | }; 103 | /* End PBXGroup section */ 104 | 105 | /* Begin PBXHeadersBuildPhase section */ 106 | DF4E92AA221EDA5700ECDEB2 /* Headers */ = { 107 | isa = PBXHeadersBuildPhase; 108 | buildActionMask = 2147483647; 109 | files = ( 110 | DF4E92B4221EDA5700ECDEB2 /* Shazam.h in Headers */, 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | /* End PBXHeadersBuildPhase section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | DF4E92AE221EDA5700ECDEB2 /* Shazam */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = DF4E92B7221EDA5700ECDEB2 /* Build configuration list for PBXNativeTarget "Shazam" */; 120 | buildPhases = ( 121 | F40F0E655BE5C5022914EF55 /* [CP] Check Pods Manifest.lock */, 122 | DF4E92AA221EDA5700ECDEB2 /* Headers */, 123 | DF4E92AB221EDA5700ECDEB2 /* Sources */, 124 | DF4E92AC221EDA5700ECDEB2 /* Frameworks */, 125 | DF4E92AD221EDA5700ECDEB2 /* Resources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | ); 131 | name = Shazam; 132 | productName = Shazam; 133 | productReference = DF4E92AF221EDA5700ECDEB2 /* Shazam.framework */; 134 | productType = "com.apple.product-type.framework"; 135 | }; 136 | /* End PBXNativeTarget section */ 137 | 138 | /* Begin PBXProject section */ 139 | DF4E92A6221EDA5700ECDEB2 /* Project object */ = { 140 | isa = PBXProject; 141 | attributes = { 142 | LastUpgradeCheck = 1010; 143 | ORGANIZATIONNAME = bawn; 144 | TargetAttributes = { 145 | DF4E92AE221EDA5700ECDEB2 = { 146 | CreatedOnToolsVersion = 10.1; 147 | }; 148 | }; 149 | }; 150 | buildConfigurationList = DF4E92A9221EDA5700ECDEB2 /* Build configuration list for PBXProject "Shazam" */; 151 | compatibilityVersion = "Xcode 9.3"; 152 | developmentRegion = en; 153 | hasScannedForEncodings = 0; 154 | knownRegions = ( 155 | en, 156 | Base, 157 | ); 158 | mainGroup = DF4E92A5221EDA5700ECDEB2; 159 | productRefGroup = DF4E92B0221EDA5700ECDEB2 /* Products */; 160 | projectDirPath = ""; 161 | projectRoot = ""; 162 | targets = ( 163 | DF4E92AE221EDA5700ECDEB2 /* Shazam */, 164 | ); 165 | }; 166 | /* End PBXProject section */ 167 | 168 | /* Begin PBXResourcesBuildPhase section */ 169 | DF4E92AD221EDA5700ECDEB2 /* Resources */ = { 170 | isa = PBXResourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXResourcesBuildPhase section */ 177 | 178 | /* Begin PBXShellScriptBuildPhase section */ 179 | F40F0E655BE5C5022914EF55 /* [CP] Check Pods Manifest.lock */ = { 180 | isa = PBXShellScriptBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | ); 184 | inputFileListPaths = ( 185 | ); 186 | inputPaths = ( 187 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 188 | "${PODS_ROOT}/Manifest.lock", 189 | ); 190 | name = "[CP] Check Pods Manifest.lock"; 191 | outputFileListPaths = ( 192 | ); 193 | outputPaths = ( 194 | "$(DERIVED_FILE_DIR)/Pods-Shazam-checkManifestLockResult.txt", 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | 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"; 199 | showEnvVarsInLog = 0; 200 | }; 201 | /* End PBXShellScriptBuildPhase section */ 202 | 203 | /* Begin PBXSourcesBuildPhase section */ 204 | DF4E92AB221EDA5700ECDEB2 /* Sources */ = { 205 | isa = PBXSourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | DF4E92C5221EDAB300ECDEB2 /* NSCache+Additional.swift in Sources */, 209 | DF4E92C0221EDAB300ECDEB2 /* ShazamPageViewController.swift in Sources */, 210 | DF4E92C3221EDAB300ECDEB2 /* ShazamContainView.swift in Sources */, 211 | DF4E92C2221EDAB300ECDEB2 /* ShazamHeaderView.swift in Sources */, 212 | DF4E92C4221EDAB300ECDEB2 /* ShazamTopView.swift in Sources */, 213 | DF4E92C1221EDAB300ECDEB2 /* ShazamChildViewController.swift in Sources */, 214 | DF4E92C7221EDAC100ECDEB2 /* UIScrollView+Additional.swift in Sources */, 215 | DF4E92C9221EDAC600ECDEB2 /* UIViewController+Additional.swift in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXSourcesBuildPhase section */ 220 | 221 | /* Begin XCBuildConfiguration section */ 222 | DF4E92B5221EDA5700ECDEB2 /* Debug */ = { 223 | isa = XCBuildConfiguration; 224 | buildSettings = { 225 | ALWAYS_SEARCH_USER_PATHS = NO; 226 | CLANG_ANALYZER_NONNULL = YES; 227 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 228 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 229 | CLANG_CXX_LIBRARY = "libc++"; 230 | CLANG_ENABLE_MODULES = YES; 231 | CLANG_ENABLE_OBJC_ARC = YES; 232 | CLANG_ENABLE_OBJC_WEAK = YES; 233 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 234 | CLANG_WARN_BOOL_CONVERSION = YES; 235 | CLANG_WARN_COMMA = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 238 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 239 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 240 | CLANG_WARN_EMPTY_BODY = YES; 241 | CLANG_WARN_ENUM_CONVERSION = YES; 242 | CLANG_WARN_INFINITE_RECURSION = YES; 243 | CLANG_WARN_INT_CONVERSION = YES; 244 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 246 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 247 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 248 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 249 | CLANG_WARN_STRICT_PROTOTYPES = YES; 250 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 251 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 252 | CLANG_WARN_UNREACHABLE_CODE = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | CODE_SIGN_IDENTITY = "iPhone Developer"; 255 | COPY_PHASE_STRIP = NO; 256 | CURRENT_PROJECT_VERSION = 1; 257 | DEBUG_INFORMATION_FORMAT = dwarf; 258 | ENABLE_STRICT_OBJC_MSGSEND = YES; 259 | ENABLE_TESTABILITY = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu11; 261 | GCC_DYNAMIC_NO_PIC = NO; 262 | GCC_NO_COMMON_BLOCKS = YES; 263 | GCC_OPTIMIZATION_LEVEL = 0; 264 | GCC_PREPROCESSOR_DEFINITIONS = ( 265 | "DEBUG=1", 266 | "$(inherited)", 267 | ); 268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 269 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 270 | GCC_WARN_UNDECLARED_SELECTOR = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 272 | GCC_WARN_UNUSED_FUNCTION = YES; 273 | GCC_WARN_UNUSED_VARIABLE = YES; 274 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 275 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 276 | MTL_FAST_MATH = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = iphoneos; 279 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 280 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 281 | VERSIONING_SYSTEM = "apple-generic"; 282 | VERSION_INFO_PREFIX = ""; 283 | }; 284 | name = Debug; 285 | }; 286 | DF4E92B6221EDA5700ECDEB2 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ALWAYS_SEARCH_USER_PATHS = NO; 290 | CLANG_ANALYZER_NONNULL = YES; 291 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 292 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 293 | CLANG_CXX_LIBRARY = "libc++"; 294 | CLANG_ENABLE_MODULES = YES; 295 | CLANG_ENABLE_OBJC_ARC = YES; 296 | CLANG_ENABLE_OBJC_WEAK = YES; 297 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 298 | CLANG_WARN_BOOL_CONVERSION = YES; 299 | CLANG_WARN_COMMA = YES; 300 | CLANG_WARN_CONSTANT_CONVERSION = YES; 301 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 302 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 303 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 304 | CLANG_WARN_EMPTY_BODY = YES; 305 | CLANG_WARN_ENUM_CONVERSION = YES; 306 | CLANG_WARN_INFINITE_RECURSION = YES; 307 | CLANG_WARN_INT_CONVERSION = YES; 308 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 309 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 310 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 311 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 312 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 313 | CLANG_WARN_STRICT_PROTOTYPES = YES; 314 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 315 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 316 | CLANG_WARN_UNREACHABLE_CODE = YES; 317 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 318 | CODE_SIGN_IDENTITY = "iPhone Developer"; 319 | COPY_PHASE_STRIP = NO; 320 | CURRENT_PROJECT_VERSION = 1; 321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 322 | ENABLE_NS_ASSERTIONS = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu11; 325 | GCC_NO_COMMON_BLOCKS = YES; 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 333 | MTL_ENABLE_DEBUG_INFO = NO; 334 | MTL_FAST_MATH = YES; 335 | SDKROOT = iphoneos; 336 | SWIFT_COMPILATION_MODE = wholemodule; 337 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 338 | VALIDATE_PRODUCT = YES; 339 | VERSIONING_SYSTEM = "apple-generic"; 340 | VERSION_INFO_PREFIX = ""; 341 | }; 342 | name = Release; 343 | }; 344 | DF4E92B8221EDA5700ECDEB2 /* Debug */ = { 345 | isa = XCBuildConfiguration; 346 | baseConfigurationReference = AA9E95405942883CCAA6E15C /* Pods-Shazam.debug.xcconfig */; 347 | buildSettings = { 348 | CODE_SIGN_IDENTITY = ""; 349 | CODE_SIGN_STYLE = Automatic; 350 | DEFINES_MODULE = YES; 351 | DYLIB_COMPATIBILITY_VERSION = 1; 352 | DYLIB_CURRENT_VERSION = 1; 353 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 354 | INFOPLIST_FILE = Shazam/Info.plist; 355 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 356 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 357 | LD_RUNPATH_SEARCH_PATHS = ( 358 | "$(inherited)", 359 | "@executable_path/Frameworks", 360 | "@loader_path/Frameworks", 361 | ); 362 | PRODUCT_BUNDLE_IDENTIFIER = bawn.Shazam; 363 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 364 | SKIP_INSTALL = YES; 365 | SWIFT_VERSION = 4.2; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | }; 368 | name = Debug; 369 | }; 370 | DF4E92B9221EDA5700ECDEB2 /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | baseConfigurationReference = B11CC81FF19CDF259B1158AA /* Pods-Shazam.release.xcconfig */; 373 | buildSettings = { 374 | CODE_SIGN_IDENTITY = ""; 375 | CODE_SIGN_STYLE = Automatic; 376 | DEFINES_MODULE = YES; 377 | DYLIB_COMPATIBILITY_VERSION = 1; 378 | DYLIB_CURRENT_VERSION = 1; 379 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 380 | INFOPLIST_FILE = Shazam/Info.plist; 381 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 382 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 383 | LD_RUNPATH_SEARCH_PATHS = ( 384 | "$(inherited)", 385 | "@executable_path/Frameworks", 386 | "@loader_path/Frameworks", 387 | ); 388 | PRODUCT_BUNDLE_IDENTIFIER = bawn.Shazam; 389 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 390 | SKIP_INSTALL = YES; 391 | SWIFT_VERSION = 4.2; 392 | TARGETED_DEVICE_FAMILY = "1,2"; 393 | }; 394 | name = Release; 395 | }; 396 | /* End XCBuildConfiguration section */ 397 | 398 | /* Begin XCConfigurationList section */ 399 | DF4E92A9221EDA5700ECDEB2 /* Build configuration list for PBXProject "Shazam" */ = { 400 | isa = XCConfigurationList; 401 | buildConfigurations = ( 402 | DF4E92B5221EDA5700ECDEB2 /* Debug */, 403 | DF4E92B6221EDA5700ECDEB2 /* Release */, 404 | ); 405 | defaultConfigurationIsVisible = 0; 406 | defaultConfigurationName = Release; 407 | }; 408 | DF4E92B7221EDA5700ECDEB2 /* Build configuration list for PBXNativeTarget "Shazam" */ = { 409 | isa = XCConfigurationList; 410 | buildConfigurations = ( 411 | DF4E92B8221EDA5700ECDEB2 /* Debug */, 412 | DF4E92B9221EDA5700ECDEB2 /* Release */, 413 | ); 414 | defaultConfigurationIsVisible = 0; 415 | defaultConfigurationName = Release; 416 | }; 417 | /* End XCConfigurationList section */ 418 | }; 419 | rootObject = DF4E92A6221EDA5700ECDEB2 /* Project object */; 420 | } 421 | -------------------------------------------------------------------------------- /Shazam.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Shazam.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Shazam.xcodeproj/project.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bawn/Shazam/a3f3e6a34fa4750d6e365829d5ec1f3bb6440b3e/Shazam.xcodeproj/project.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Shazam.xcodeproj/xcshareddata/xcschemes/Shazam.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 | -------------------------------------------------------------------------------- /Shazam.xcodeproj/xcuserdata/bawn.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Shazam.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | DF4E92AE221EDA5700ECDEB2 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Shazam.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Shazam.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Shazam.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bawn/Shazam/a3f3e6a34fa4750d6e365829d5ec1f3bb6440b3e/Shazam.xcworkspace/xcuserdata/bawn.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Shazam.xcworkspace/xcuserdata/bawn.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Shazam/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Shazam/.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 -------------------------------------------------------------------------------- /Shazam/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 | -------------------------------------------------------------------------------- /Shazam/NSCache+Additional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSCache+Additional.swift 3 | // Shazam 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 | -------------------------------------------------------------------------------- /Shazam/Shazam.h: -------------------------------------------------------------------------------- 1 | // 2 | // Shazam.h 3 | // Shazam 4 | // 5 | // Created by bawn on 2019/2/21. 6 | // Copyright © 2019 bawn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Shazam. 12 | FOUNDATION_EXPORT double ShazamVersionNumber; 13 | 14 | //! Project version string for Shazam. 15 | FOUNDATION_EXPORT const unsigned char ShazamVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Shazam/ShazamChildViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamChildViewController.swift 3 | // Shazam 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 ShazamChildViewController where Self: UIViewController { 30 | func shazamChildScrollView() -> UIScrollView 31 | } 32 | -------------------------------------------------------------------------------- /Shazam/ShazamContainView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamContainView.swift 3 | // Shazam 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 ShazamContainView: UIView { 29 | weak var viewController: (UIViewController & ShazamChildViewController)? 30 | var isEmpty: Bool { 31 | return subviews.isEmpty 32 | } 33 | 34 | func displayingIn(view: UIView, containView: UIView) -> Bool { 35 | 36 | let convertedFrame = containView.convert(frame, to: view) 37 | return view.frame.intersects(convertedFrame) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Shazam/ShazamHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamHeaderView.swift 3 | // Shazam 4 | // 5 | // Created by bawn on 2019/1/24. 6 | // Copyright © 2019 bawn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | public protocol ShazamHeaderView { 13 | func userInteractionViews() -> [UIView]? 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Shazam/ShazamPageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamPageViewController.swift 3 | // Shazam 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 | private enum ScrollDirection { 29 | case up 30 | case down 31 | case none 32 | } 33 | 34 | 35 | protocol AMPageControllerDataSource: class { 36 | 37 | func pageController(_ pageController: ShazamPageViewController, viewControllerAt index: Int) -> (UIViewController & ShazamChildViewController) 38 | func numberOfViewControllers(in pageController: ShazamPageViewController) -> Int 39 | func headerViewFor(_ pageController: ShazamPageViewController) -> UIView & ShazamHeaderView 40 | func headerViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat 41 | func menuViewFor(_ pageController: ShazamPageViewController) -> UIView 42 | func menuViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat 43 | func menuViewPinHeightFor(_ pageController: ShazamPageViewController) -> CGFloat 44 | func originIndexFor(_ pageController: ShazamPageViewController) -> Int 45 | func keepChildScrollViewOffset(_ pageController: ShazamPageViewController) -> Bool 46 | } 47 | 48 | protocol AMPageControllerDelegate: class { 49 | 50 | /// Any offset changes in pageController's mainScrollView 51 | /// 52 | /// - Parameters: 53 | /// - pageController: ShazamPageViewController 54 | /// - scrollView: mainScrollView 55 | func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) 56 | 57 | 58 | /// Method call when mainScrollView did end scroll 59 | /// 60 | /// - Parameters: 61 | /// - pageController: ShazamPageViewController 62 | /// - scrollView: mainScrollView 63 | func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidEndScroll scrollView: UIScrollView) 64 | 65 | 66 | /// Any offset changes in pageController's childScrollView 67 | /// 68 | /// - Parameters: 69 | /// - pageController: ShazamPageViewController 70 | /// - scrollView: childScrollView 71 | func pageController(_ pageController: ShazamPageViewController, childScrollViewDidScroll scrollView: UIScrollView) 72 | 73 | /// Method call when viewController will cache 74 | /// 75 | /// - Parameters: 76 | /// - pageController: ShazamPageViewController 77 | /// - viewController: target viewController 78 | /// - index: target viewController's index 79 | func pageController(_ pageController: ShazamPageViewController, willCache viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) 80 | 81 | 82 | /// Method call when viewController will display 83 | /// 84 | /// - Parameters: 85 | /// - pageController: ShazamPageViewController 86 | /// - viewController: target viewController 87 | /// - index: target viewController's index 88 | func pageController(_ pageController: ShazamPageViewController, willDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) 89 | 90 | 91 | /// Method call when viewController did display 92 | /// 93 | /// - Parameters: 94 | /// - pageController: ShazamPageViewController 95 | /// - viewController: target viewController 96 | /// - index: target viewController's index 97 | func pageController(_ pageController: ShazamPageViewController, didDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) 98 | 99 | 100 | 101 | /// Method call when menuView is adsorption 102 | /// 103 | /// - Parameters: 104 | /// - pageController: ShazamPageViewController 105 | /// - offset: offset 106 | /// - isAdsorption: isAdsorption 107 | func pageController(_ pageController: ShazamPageViewController, headerView offset: CGPoint 108 | , isAdsorption: Bool) 109 | } 110 | 111 | 112 | open class ShazamPageViewController: UIViewController, AMPageControllerDataSource, AMPageControllerDelegate { 113 | 114 | public private(set) var currentViewController: (UIViewController & ShazamChildViewController)? 115 | public private(set) var currentIndex = 0 116 | private var originIndex = 0 117 | 118 | lazy public private(set) var mainScrollView: UIScrollView = { 119 | let scrollView = UIScrollView() 120 | scrollView.delegate = self 121 | scrollView.scrollsToTop = true 122 | scrollView.backgroundColor = .white 123 | scrollView.showsHorizontalScrollIndicator = false 124 | scrollView.showsVerticalScrollIndicator = false 125 | scrollView.isPagingEnabled = true 126 | if let popGesture = navigationController?.interactivePopGestureRecognizer { 127 | scrollView.panGestureRecognizer.require(toFail: popGesture) 128 | } 129 | return scrollView 130 | }() 131 | 132 | private let contentStackView: UIStackView = { 133 | let stackView = UIStackView() 134 | stackView.alignment = .fill 135 | stackView.distribution = .fillEqually 136 | stackView.axis = .horizontal 137 | return stackView 138 | }() 139 | 140 | public let topView = ShazamTopView() 141 | private var headerViewHeight: CGFloat = 0.0 142 | private var menuViewHeight: CGFloat = 0.0 143 | private var menuViewPinHeight: CGFloat = 0.0 144 | private var sillValue: CGFloat = 0.0 145 | private var childControllerCount = 0 146 | private var headerView: UIView? 147 | private var menuView: UIView? 148 | private var countArray = [Int]() 149 | private var containViews = [ShazamContainView]() 150 | private var currentChildScrollView: UIScrollView? 151 | private var childScrollViews = [UIScrollView]() 152 | private var isBeginDragging = false 153 | 154 | private var topViewLastOffset: CGFloat = 0.0 155 | private var childScrollDirection = ScrollDirection.none 156 | private var isSpecialState = false 157 | private var childScrollViewObservation: NSKeyValueObservation? 158 | private var topViewTopLayout: NSLayoutConstraint? 159 | 160 | private var childScrollOffset: CGFloat = 0.0 { 161 | didSet { 162 | if oldValue > childScrollOffset { 163 | childScrollDirection = .down 164 | } else if oldValue < childScrollOffset { 165 | childScrollDirection = .up 166 | } else { 167 | childScrollDirection = .none 168 | } 169 | } 170 | } 171 | 172 | private let memoryCache = NSCache() 173 | private weak var dataSource: AMPageControllerDataSource? 174 | private weak var delegate: AMPageControllerDelegate? 175 | 176 | public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 177 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 178 | dataSource = self 179 | delegate = self 180 | } 181 | 182 | public required init?(coder aDecoder: NSCoder) { 183 | super.init(coder: aDecoder) 184 | dataSource = self 185 | delegate = self 186 | } 187 | 188 | deinit { 189 | childScrollViewObservation?.invalidate() 190 | } 191 | 192 | open override func viewDidLoad() { 193 | super.viewDidLoad() 194 | obtainDataSource() 195 | setupOriginContent() 196 | setupDataSource() 197 | view.layoutIfNeeded() 198 | 199 | if originIndex > 0 { 200 | setSelect(index: originIndex, animation: false) 201 | } else { 202 | showChildViewContoller(at: originIndex) 203 | didDisplayViewController(at: originIndex) 204 | } 205 | } 206 | 207 | private func didDisplayViewController(at index: Int) { 208 | guard childControllerCount > 0 209 | , index >= 0 210 | , index < childControllerCount 211 | , containViews.isEmpty == false else { 212 | return 213 | } 214 | let containView = containViews[index] 215 | currentViewController = containView.viewController 216 | currentChildScrollView = currentViewController?.shazamChildScrollView() 217 | currentIndex = index 218 | 219 | if let viewController = containView.viewController { 220 | pageController(self, didDisplay: viewController, forItemAt: index) 221 | } 222 | } 223 | 224 | 225 | private func obtainDataSource() { 226 | originIndex = originIndexFor(self) 227 | 228 | headerView = headerViewFor(self) 229 | headerViewHeight = headerViewHeightFor(self) 230 | 231 | menuView = menuViewFor(self) 232 | menuViewHeight = menuViewHeightFor(self) 233 | menuViewPinHeight = menuViewPinHeightFor(self) 234 | 235 | childControllerCount = numberOfViewControllers(in: self) 236 | 237 | sillValue = headerViewHeight - menuViewPinHeight 238 | countArray = Array(stride(from: 0, to: childControllerCount, by: 1)) 239 | } 240 | 241 | 242 | private func setupOriginContent() { 243 | 244 | view.addSubview(mainScrollView) 245 | if #available(iOS 11.0, *) { 246 | mainScrollView.contentInsetAdjustmentBehavior = .never 247 | } else { 248 | automaticallyAdjustsScrollViewInsets = false 249 | } 250 | 251 | mainScrollView.translatesAutoresizingMaskIntoConstraints = false 252 | mainScrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true 253 | mainScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true 254 | mainScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true 255 | mainScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 256 | 257 | mainScrollView.addSubview(contentStackView) 258 | 259 | contentStackView.translatesAutoresizingMaskIntoConstraints = false 260 | contentStackView.topAnchor.constraint(equalTo: mainScrollView.topAnchor).isActive = true 261 | contentStackView.leadingAnchor.constraint(equalTo: mainScrollView.leadingAnchor).isActive = true 262 | contentStackView.trailingAnchor.constraint(equalTo: mainScrollView.trailingAnchor).isActive = true 263 | contentStackView.bottomAnchor.constraint(equalTo: mainScrollView.bottomAnchor).isActive = true 264 | contentStackView.heightAnchor.constraint(equalTo: mainScrollView.heightAnchor).isActive = true 265 | 266 | view.addSubview(topView) 267 | topView.translatesAutoresizingMaskIntoConstraints = false 268 | topViewTopLayout = topView.topAnchor.constraint(equalTo: topLayoutGuide.topAnchor) 269 | topViewTopLayout?.isActive = true 270 | topView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true 271 | topView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true 272 | 273 | topView.updateLayout(headerViewHeight, menuViewHeight) 274 | } 275 | 276 | 277 | private func updateOriginContent() { 278 | topView.updateLayout(headerViewHeight, menuViewHeight) 279 | } 280 | 281 | private func clear() { 282 | 283 | childScrollViewObservation?.invalidate() 284 | 285 | originIndex = 0 286 | 287 | childControllerCount = 0 288 | 289 | currentViewController = nil 290 | currentChildScrollView = nil 291 | 292 | headerView?.removeFromSuperview() 293 | mainScrollView.setContentOffset(.zero, animated: false) 294 | 295 | contentStackView.arrangedSubviews.forEach({$0.removeFromSuperview()}) 296 | memoryCache.removeAllObjects() 297 | 298 | containViews.forEach({$0.viewController?.clearFromParent()}) 299 | containViews.removeAll() 300 | } 301 | 302 | func setupDataSource() { 303 | memoryCache.countLimit = childControllerCount 304 | 305 | if let headerView = headerView { 306 | topView.headerContentView.addSubview(headerView) 307 | headerView.translatesAutoresizingMaskIntoConstraints = false 308 | headerView.topAnchor.constraint(equalTo: topView.headerContentView.topAnchor).isActive = true 309 | headerView.leadingAnchor.constraint(equalTo: topView.headerContentView.leadingAnchor).isActive = true 310 | headerView.trailingAnchor.constraint(equalTo: topView.headerContentView.trailingAnchor).isActive = true 311 | headerView.bottomAnchor.constraint(equalTo: topView.headerContentView.bottomAnchor).isActive = true 312 | } 313 | 314 | if let menuView = menuView { 315 | topView.menuContentView.addSubview(menuView) 316 | menuView.translatesAutoresizingMaskIntoConstraints = false 317 | menuView.topAnchor.constraint(equalTo: topView.menuContentView.topAnchor).isActive = true 318 | menuView.leadingAnchor.constraint(equalTo: topView.menuContentView.leadingAnchor).isActive = true 319 | menuView.trailingAnchor.constraint(equalTo: topView.menuContentView.trailingAnchor).isActive = true 320 | menuView.bottomAnchor.constraint(equalTo: topView.menuContentView.bottomAnchor).isActive = true 321 | } 322 | 323 | countArray.forEach { (_) in 324 | let containView = ShazamContainView() 325 | contentStackView.addArrangedSubview(containView) 326 | containView.translatesAutoresizingMaskIntoConstraints = false 327 | containView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true 328 | containView.heightAnchor.constraint(equalTo: contentStackView.heightAnchor).isActive = true 329 | containViews.append(containView) 330 | } 331 | } 332 | 333 | func showChildViewContoller(at index: Int) { 334 | guard childControllerCount > 0 335 | , index >= 0 336 | , index < childControllerCount 337 | , containViews.isEmpty == false else { 338 | return 339 | } 340 | 341 | let containView = containViews[index] 342 | 343 | guard containView.isEmpty else { 344 | updateSatae(containView) 345 | return 346 | } 347 | 348 | let cachedViewContoller = memoryCache[index] as? (UIViewController & ShazamChildViewController) 349 | let viewController = cachedViewContoller != nil ? cachedViewContoller : pageController(self, viewControllerAt: index) 350 | 351 | guard let targetViewController = viewController else { 352 | return 353 | } 354 | pageController(self, willDisplay: targetViewController, forItemAt: index) 355 | 356 | targetViewController.beginAppearanceTransition(true, animated: false) 357 | addChild(targetViewController) 358 | containView.addSubview(targetViewController.view) 359 | 360 | targetViewController.view.translatesAutoresizingMaskIntoConstraints = false 361 | targetViewController.view.topAnchor.constraint(equalTo: containView.topAnchor).isActive = true 362 | targetViewController.view.leadingAnchor.constraint(equalTo: containView.leadingAnchor).isActive = true 363 | targetViewController.view.trailingAnchor.constraint(equalTo: containView.trailingAnchor).isActive = true 364 | targetViewController.view.bottomAnchor.constraint(equalTo: containView.bottomAnchor).isActive = true 365 | 366 | targetViewController.view.layoutIfNeeded() 367 | targetViewController.didMove(toParent: self) 368 | targetViewController.endAppearanceTransition() 369 | 370 | containView.viewController = targetViewController 371 | 372 | updateSatae(containView) 373 | } 374 | 375 | func updateSatae(_ containView: ShazamContainView) { 376 | 377 | guard let scrollView = containView.viewController?.shazamChildScrollView() else { 378 | return 379 | } 380 | 381 | scrollView.sz_lastOffsetY = scrollView.contentOffset.y 382 | 383 | 384 | if scrollView.contentOffset.y <= sillValue { 385 | scrollView.setContentOffset(CGPoint(x: 0, y: -min(topView.frame.origin.y, 0)), animated: false) 386 | } else if keepChildScrollViewOffset(self) == false && abs(topView.frame.origin.y) < sillValue { 387 | scrollView.setContentOffset(CGPoint(x: 0, y: -topView.frame.origin.y), animated: false) 388 | } 389 | childScrollOffset = scrollView.contentOffset.y 390 | topViewLastOffset = -topView.frame.origin.y 391 | let offsetY = scrollView.contentOffset.y 392 | isSpecialState = keepChildScrollViewOffset(self) && offsetY > abs(topView.frame.origin.y) 393 | 394 | 395 | childScrollViewObservation?.invalidate() 396 | let keyValueObservation = scrollView.observe(\.contentOffset, options: [.new, .old, .initial], changeHandler: { [weak self] (scrollView, change) in 397 | guard let self = self, change.newValue != change.oldValue else { 398 | return 399 | } 400 | self.childScrollViewDidScroll(scrollView) 401 | }) 402 | childScrollViewObservation = keyValueObservation 403 | } 404 | 405 | func removeChildViewController(at index: Int) { 406 | guard childControllerCount > 0 407 | , index >= 0 408 | , index < childControllerCount 409 | , containViews.isEmpty == false else { 410 | return 411 | } 412 | 413 | // let containView = containViews[index] 414 | // guard containView.isEmpty == false 415 | // , let viewController = containView.viewController else { 416 | // return 417 | // } 418 | // viewController.clearFromParent() 419 | // 420 | // if memoryCache[index] == nil { 421 | // pageController(self, willCache: viewController, forItemAt: index) 422 | // memoryCache[index] = viewController 423 | // } 424 | } 425 | 426 | func layoutChildViewControlls() { 427 | countArray.forEach { (index) in 428 | let containView = containViews[index] 429 | let isDisplaying = containView.displayingIn(view: view, containView: mainScrollView) 430 | isDisplaying ? showChildViewContoller(at: index) : removeChildViewController(at: index) 431 | } 432 | } 433 | 434 | public func setSelect(index: Int, animation: Bool) { 435 | let offset = CGPoint(x: mainScrollView.bounds.width * CGFloat(index), y: mainScrollView.contentOffset.y) 436 | mainScrollView.setContentOffset(offset, animated: animation) 437 | if animation == false { 438 | mainScrollViewDidEndScroll(mainScrollView) 439 | } 440 | } 441 | 442 | private func mainScrollViewDidEndScroll(_ scrollView: UIScrollView) { 443 | let scrollViewWidth = scrollView.bounds.width 444 | guard scrollViewWidth > 0 else { 445 | return 446 | } 447 | 448 | let offsetX = scrollView.contentOffset.x 449 | let index = Int(offsetX / scrollViewWidth) 450 | didDisplayViewController(at: index) 451 | pageController(self, mainScrollViewDidEndScroll: mainScrollView) 452 | } 453 | 454 | public func reloadData() { 455 | mainScrollView.isUserInteractionEnabled = false 456 | clear() 457 | obtainDataSource() 458 | updateOriginContent() 459 | setupDataSource() 460 | view.layoutIfNeeded() 461 | if originIndex > 0 { 462 | setSelect(index: originIndex, animation: false) 463 | } else { 464 | showChildViewContoller(at: originIndex) 465 | didDisplayViewController(at: originIndex) 466 | } 467 | mainScrollView.isUserInteractionEnabled = true 468 | } 469 | 470 | open func pageController(_ pageController: ShazamPageViewController, viewControllerAt index: Int) -> (UIViewController & ShazamChildViewController) { 471 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 472 | return UIViewController() as! UIViewController & ShazamChildViewController 473 | } 474 | 475 | open func numberOfViewControllers(in pageController: ShazamPageViewController) -> Int { 476 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 477 | return 0 478 | } 479 | 480 | open func headerViewFor(_ pageController: ShazamPageViewController) -> UIView & ShazamHeaderView { 481 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 482 | return UIView() as! UIView & ShazamHeaderView 483 | } 484 | 485 | open func headerViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 486 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 487 | return 0 488 | } 489 | 490 | open func menuViewFor(_ pageController: ShazamPageViewController) -> UIView { 491 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 492 | return UIView() 493 | } 494 | 495 | open func menuViewHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 496 | assertionFailure("Sub-class must implement the AMPageControllerDataSource method") 497 | return 0 498 | } 499 | 500 | open func originIndexFor(_ pageController: ShazamPageViewController) -> Int { 501 | return 0 502 | } 503 | 504 | open func menuViewPinHeightFor(_ pageController: ShazamPageViewController) -> CGFloat { 505 | return 0 506 | } 507 | 508 | open func keepChildScrollViewOffset(_ pageController: ShazamPageViewController) -> Bool { 509 | return false 510 | } 511 | 512 | open func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidScroll scrollView: UIScrollView) { 513 | } 514 | 515 | 516 | open func pageController(_ pageController: ShazamPageViewController, mainScrollViewDidEndScroll scrollView: UIScrollView) { 517 | 518 | } 519 | 520 | open func pageController(_ pageController: ShazamPageViewController, childScrollViewDidScroll scrollView: UIScrollView) { 521 | 522 | } 523 | 524 | open func pageController(_ pageController: ShazamPageViewController, willCache viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) { 525 | 526 | } 527 | 528 | open func pageController(_ pageController: ShazamPageViewController, willDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) { 529 | 530 | } 531 | 532 | open func pageController(_ pageController: ShazamPageViewController, didDisplay viewController: (UIViewController & ShazamChildViewController), forItemAt index: Int) { 533 | 534 | } 535 | 536 | open func pageController(_ pageController: ShazamPageViewController, headerView offset: CGPoint, isAdsorption: Bool) { 537 | 538 | } 539 | } 540 | 541 | 542 | extension ShazamPageViewController: UIScrollViewDelegate { 543 | 544 | public func scrollViewDidScroll(_ scrollView: UIScrollView) { 545 | pageController(self, mainScrollViewDidScroll: scrollView) 546 | layoutChildViewControlls() 547 | } 548 | 549 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 550 | isBeginDragging = true 551 | } 552 | 553 | 554 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 555 | 556 | if decelerate == false { 557 | mainScrollViewDidEndScroll(mainScrollView) 558 | } 559 | } 560 | 561 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 562 | if isBeginDragging { 563 | mainScrollViewDidEndScroll(scrollView) 564 | isBeginDragging = false 565 | } 566 | } 567 | 568 | 569 | public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { 570 | mainScrollViewDidEndScroll(scrollView) 571 | } 572 | 573 | public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { 574 | guard scrollView == mainScrollView else { 575 | return false 576 | } 577 | currentChildScrollView?.setContentOffset(.zero, animated: true) 578 | return true 579 | } 580 | 581 | } 582 | 583 | extension ShazamPageViewController { 584 | private func childScrollViewDidScroll(_ scrollView: UIScrollView) { 585 | 586 | let offsetY = scrollView.contentOffset.y 587 | childScrollOffset = offsetY 588 | if isSpecialState { 589 | isSpecialState = offsetY > topViewLastOffset 590 | 591 | let value = offsetY - scrollView.sz_lastOffsetY 592 | let offset = min(value + topViewLastOffset, sillValue) 593 | if childScrollDirection == .up { 594 | topViewTopLayout?.constant = -offset 595 | } else { 596 | topViewLastOffset = -(topView.frame.origin.y) 597 | scrollView.sz_lastOffsetY = offsetY 598 | } 599 | } else { 600 | 601 | scrollView.sz_lastOffsetY = 0 602 | let offset = min(offsetY, sillValue) 603 | topViewTopLayout?.constant = -offset 604 | } 605 | let isAdsorption = abs(topView.frame.origin.y) == sillValue 606 | pageController(self, headerView: topView.frame.origin, isAdsorption: isAdsorption) 607 | pageController(self, childScrollViewDidScroll: scrollView) 608 | } 609 | } 610 | -------------------------------------------------------------------------------- /Shazam/ShazamTopView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShazamTopView.swift 3 | // Shazam 4 | // 5 | // Created by bawn on 2019/1/24. 6 | // Copyright © 2019 bawn. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class ShazamTopView: UIView { 12 | let headerContentView = UIView() 13 | let menuContentView = UIView() 14 | var heightLayout: NSLayoutConstraint? 15 | var headerHeightLayout: NSLayoutConstraint? 16 | var menuHeightLayout: NSLayoutConstraint? 17 | 18 | override init(frame: CGRect) { 19 | super.init(frame: frame) 20 | 21 | translatesAutoresizingMaskIntoConstraints = false 22 | heightLayout = heightAnchor.constraint(equalToConstant: 0) 23 | heightLayout?.isActive = true 24 | 25 | addSubview(headerContentView) 26 | headerContentView.translatesAutoresizingMaskIntoConstraints = false 27 | headerContentView.topAnchor.constraint(equalTo: topAnchor).isActive = true 28 | headerContentView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true 29 | headerContentView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true 30 | headerHeightLayout = headerContentView.heightAnchor.constraint(equalToConstant: 0) 31 | headerHeightLayout?.isActive = true 32 | 33 | addSubview(menuContentView) 34 | menuContentView.translatesAutoresizingMaskIntoConstraints = false 35 | menuContentView.topAnchor.constraint(equalTo: headerContentView.bottomAnchor).isActive = true 36 | menuContentView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true 37 | menuContentView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true 38 | menuContentView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true 39 | menuHeightLayout = menuContentView.heightAnchor.constraint(equalToConstant: 0) 40 | menuHeightLayout?.isActive = true 41 | } 42 | 43 | func updateLayout(_ headerViewHeight: CGFloat, _ menuViewHeight: CGFloat) { 44 | headerHeightLayout?.constant = headerViewHeight 45 | menuHeightLayout?.constant = menuViewHeight 46 | heightLayout?.constant = headerViewHeight + menuViewHeight 47 | } 48 | 49 | 50 | required init?(coder aDecoder: NSCoder) { 51 | super.init(coder: aDecoder) 52 | } 53 | 54 | override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 55 | if menuContentView.frame.contains(point) { 56 | return true 57 | } 58 | guard let headerView = headerContentView.subviews.first as? ShazamHeaderView 59 | , let userInteractionViews = headerView.userInteractionViews() else { 60 | return false 61 | } 62 | let frames = userInteractionViews.map({convert($0.frame, to: self)}) 63 | return !frames.filter({$0.contains(point)}).isEmpty 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Shazam/UIScrollView+Additional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+Additional.swift 3 | // Shazam 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 SZLastOffsetY = "SZLastOffsetY" 32 | } 33 | 34 | extension UIScrollView { 35 | internal var sz_lastOffsetY: CGFloat { 36 | get { 37 | return (objc_getAssociatedObject(self, &AssociatedKeys.SZLastOffsetY) as? CGFloat) ?? 0.0 38 | } 39 | set { 40 | objc_setAssociatedObject(self, &AssociatedKeys.SZLastOffsetY, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Shazam/UIViewController+Additional.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Additional.swift 3 | // Shazam 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 szPageViewContoller: ShazamPageViewController? { 32 | return parent as? ShazamPageViewController 33 | } 34 | 35 | func clearFromParent() { 36 | willMove(toParent: nil) 37 | view.removeFromSuperview() 38 | removeFromParent() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bawn/Shazam/a3f3e6a34fa4750d6e365829d5ec1f3bb6440b3e/demo.gif --------------------------------------------------------------------------------