Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8bd4fd1289 | |||
| 8b71ddf888 | |||
| f09c4d0986 | |||
| 38aa59c003 | |||
| be2ac457c1 | |||
| c451180c26 | |||
| 224581cac8 | |||
| 2f4d99a03c | |||
| e10c8b8d51 | |||
| 8314bde8e0 | |||
| 1381030931 | |||
| 7fc34c74ed | |||
| 66cb4a2d4b | |||
| 18a6f1d229 | |||
| d593da496b | |||
| 537f39373c | |||
| 73be895065 | |||
| 00003f098f | |||
| f4b74330c0 | |||
| fb25017bc7 | |||
| 1841827ef9 | |||
| a5852d8fd0 | |||
| 3e4e829ce0 | |||
| 43d1768175 | |||
| 8ecc8ab441 | |||
| 4b01b0f874 | |||
| 6b7de92136 | |||
| f3c4a22931 | |||
| 46c40f081a | |||
| 3659e868be | |||
| 4e7a35f0b8 | |||
| 082813937e | |||
| 538e84a26d | |||
| 17b8fcd413 | |||
| 64f9d0bfbd | |||
| 8dde1951c3 | |||
| 7d15070513 | |||
| b76a39208e | |||
| 2c496c3c56 | |||
| 37071b5d06 | |||
| 607260ac2e | |||
| 9f3759c90c | |||
| c346f2e0db | |||
| 6c72727408 | |||
| b649404a7e | |||
| 3272a0f63e | |||
| 70fa815037 | |||
| 794767455a | |||
| 7359ee6801 | |||
| 0b62749bff | |||
| 7179713c18 | |||
| 60f6f204c1 | |||
| 98c5b2b3e3 | |||
| e8882a952d | |||
| efc2e11fb2 | |||
| 36662fa0f3 | |||
| dce89eb448 | |||
| 32f1101e86 | |||
| d25de76a92 | |||
| 59faed8ef9 | |||
| 4f990e86a8 | |||
| 8200e0d49f | |||
| 5bb2f86b0a | |||
| c591059fbe | |||
| cf6ec23a7f | |||
| 21a7347079 | |||
| fc593b0cb7 | |||
| 55bfef578c | |||
| 620b248799 | |||
| 279ba484d3 | |||
| c46745cef8 | |||
| 8cc163dc5f | |||
| fae34995ab | |||
| 90878cc0d5 | |||
| 3f78b9bb49 | |||
| 6f8f224e00 | |||
| bc37f1b9cb | |||
| 8aff2b3627 | |||
| 135a3d2a94 | |||
| a10b94e351 | |||
| e1bf7c4991 | |||
| b19c93ff2c | |||
| 3968686410 | |||
| 0a457b414e | |||
| 5abf5ca740 | |||
| 498669bf58 | |||
| 159c87871b | |||
| 4c0733d82a | |||
| c3671408da | |||
| 3268b15e54 | |||
| 22a7723345 | |||
| 423b56b9ac | |||
| 06fbf875d0 | |||
| 9d9c22c786 | |||
| de1b010ac1 | |||
| d061bd178d | |||
| 93ddab1377 | |||
| 60854beac1 | |||
| 2e8740a91e | |||
| b387ef2dd7 | |||
| 22596320a3 | |||
| 9363b747d1 | |||
| baae6186d7 | |||
| c5f80f954c | |||
| 493fa9a7a1 | |||
| 2de8d7f758 | |||
| 62a37e20d1 | |||
| 7a799b94a8 | |||
| 3a01ab6398 | |||
| 5e4ab5e254 | |||
| 70715d6fa0 | |||
| 411bd59493 | |||
| 5e295d36eb | |||
| 6aa68df4ce | |||
| 5c292125a6 | |||
| 48eb4a2e3a | |||
| 9503c814d6 | |||
| 4dd4f54a8e | |||
| 7429a42c26 | |||
| df032e6072 | |||
| 3a7c74e2e0 | |||
| 900926f268 | |||
| f5e585857c | |||
| 1d96ef80b3 | |||
| 452b354e19 | |||
| 78a3a66a69 | |||
| 8fe0a23a38 | |||
| 3a873661c3 | |||
| 89fc05a324 | |||
| 453e110246 | |||
| b39142bc1a | |||
| a6bd743e99 | |||
| 749588918c | |||
| f5b6615c72 | |||
| 8804675b80 | |||
| b0a09a5b7d | |||
| f1e4efeb46 | |||
| aea7592d85 | |||
| 87edaf1d32 | |||
| d14a8d66b3 | |||
| 36e8131965 | |||
| 58318a638d | |||
| 06ea874cc6 | |||
| fd8437b181 | |||
| 8c0d6b636f | |||
| 44d1de7d48 | |||
| 287434b008 | |||
| c0ec53608f | |||
| 54a9f3887d | |||
| 82b3e95c29 | |||
| 7ffe987e96 | |||
| 14ddcaa1cb | |||
| e94153ce25 | |||
| b9a5ed0886 | |||
| b2c8bedaca | |||
| e94de73713 | |||
| b43f4d14f3 | |||
| b99f694129 | |||
| 0ede564456 | |||
| dc059ce7d6 | |||
| 09b0f3b6f0 | |||
| 24141cb436 | |||
| ec00f3fb2b | |||
| 71f3d30efa | |||
| 4ccb12cbd3 | |||
| 37b67786c6 | |||
| 37e9afc475 | |||
| c91995c71c | |||
| 0d3780fecc | |||
| 1f37d83568 | |||
| f3c00687aa | |||
| 058593a6fc | |||
| 9f4bc56e43 | |||
| d9229e68e9 | |||
| 53a7bd4b05 | |||
| d59ca607e0 | |||
| 54c6980a05 | |||
| 5a45d4ca0f | |||
| 8e7bf66dba | |||
| 3aad126881 | |||
| 6ef3315306 | |||
| 2cea3499ee | |||
| 77d5a9acbe | |||
| f641e674db | |||
| f5aa75c082 | |||
| a38315d17a | |||
| 89f0a781d7 | |||
| e79d59e8ec | |||
| f560687c91 | |||
| 392be96c1a | |||
| 3ca1801cfd | |||
| 0330adf802 | |||
| 3a18cb2b07 | |||
| c7f2b8d319 | |||
| 7f1cd5b12a | |||
| f890891006 | |||
| 1e1984aa73 | |||
| 0d7cca5609 | |||
| 9dcfc25b48 | |||
| 017e97db18 | |||
| fbcee66c14 | |||
| ad47e8bff1 | |||
| b4042a562d | |||
| c7c6fdf64a | |||
| 02595f2b68 | |||
| a8f0d75e66 | |||
| fbe29c7756 | |||
| 61f1556d93 | |||
| ceb3e44c31 | |||
| 01987a9d5b | |||
| b1e83dc4a8 | |||
| 89d3048c09 | |||
| ddca756462 | |||
| 1ebd491f04 | |||
| ad9fa96e33 | |||
| a2370c8cb4 | |||
| 8f995c2bc6 | |||
| 202289d5c6 | |||
| f71245ed75 | |||
| ba3703abda | |||
| 613fd9f68a | |||
| cb89d98dd8 | |||
| 419eabb79d | |||
| fee9c3cb20 | |||
| cc436ded70 | |||
| aeaeba35ac | |||
| 51576e149d | |||
| 5f27a26c13 | |||
| 0ff87874f6 | |||
| 83f8e461e1 | |||
| 40e8408ce1 | |||
| f66a3068b6 | |||
| 40ba7f335a | |||
| 32e6097602 | |||
| 2820b58e78 | |||
| 5f0ecdb410 | |||
| b58e5c0e63 | |||
| 4319029d98 | |||
| 4b8f65812f | |||
| 86a40d1346 | |||
| 4e896375f2 | |||
| 6c5469c40c | |||
| 965531907b | |||
| 1b6b8c446c | |||
| bcf178c3d5 | |||
| 46b4bdc376 | |||
| 175042e238 | |||
| 2a4d78b7fa | |||
| 1df40fa25c | |||
| 8573045525 | |||
| 9e5b11c1cc | |||
| ecdbfbb11a | |||
| 5dc207396f | |||
| 67886c73a8 | |||
| cbc1ac6624 | |||
| 9c7111e7e3 | |||
| df48679df4 | |||
| f32cf72443 | |||
| b15180fb8a | |||
| 6eae7987ef | |||
| c6b7780daf | |||
| c54f364d49 | |||
| 5ac61bc981 | |||
| b647880794 |
@@ -0,0 +1,39 @@
|
||||
# iOS CircleCI 2.0 configuration file
|
||||
#
|
||||
# Check https://circleci.com/docs/2.0/ios-migrating-from-1-2/ for more details
|
||||
#
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
|
||||
# Specify the Xcode version to use
|
||||
macos:
|
||||
xcode: "10.3.0"
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
# Install CocoaPods
|
||||
- run:
|
||||
name: Install CocoaPods
|
||||
command: pod install
|
||||
|
||||
# Build the app and run tests
|
||||
- run:
|
||||
name: Build and run tests
|
||||
command: fastlane scan
|
||||
environment:
|
||||
SCAN_DEVICE: iPhone Xʀ
|
||||
SCAN_SCHEME: SideMenu Example
|
||||
|
||||
# Collect XML test results data to show in the UI,
|
||||
# and save the same XML files under test-results folder
|
||||
# in the Artifacts tab
|
||||
- store_test_results:
|
||||
path: test_output/report.xml
|
||||
- store_artifacts:
|
||||
path: /tmp/test-results
|
||||
destination: scan-test-results
|
||||
- store_artifacts:
|
||||
path: ~/Library/Logs/scan
|
||||
destination: scan-logs
|
||||
@@ -0,0 +1,2 @@
|
||||
github: [jonkykong]
|
||||
custom: ["https://www.paypal.me/jonkykong"]
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: You must complete this template or your report will be automatically closed.
|
||||
title: ''
|
||||
labels: Bug - Help Wanted!
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**I have read the [guidelines for contributing](https://github.com/jonkykong/SideMenu/blob/master/.github/CONTRIBUTING.md) and I understand**
|
||||
- [ ] My issue is happening in the **latest version** of SideMenu (older versions are no longer maintained).
|
||||
- [ ] My issue was **not** solved in the [README](https://github.com/jonkykong/SideMenu/blob/master/README.md).
|
||||
- [ ] My issue can **not** be answered on [stackoverflow.com](stackoverflow.com).
|
||||
- [ ] My issue is **not** a request for new functionality that I am unwilling to build and contribute with a pull request.
|
||||
- [ ] My issue **is** reproducible in the [demo project](https://github.com/jonkykong/SideMenu/tree/master/Example).
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this project.
|
||||
title: ''
|
||||
labels: Feature Request - Help Wanted!
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
SideMenu currently meets the majority of people's needs with the features it already has. However, this is a great opportunity for you to [join the proud members](https://github.com/jonkykong/SideMenu/graphs/contributors) who have contributed to this open source project! Feel free to open an issue to ask any clarifying questions for your new feature before you start building. Open a [pull request](https://github.com/jonkykong/SideMenu/pull/new/master) when you're ready for me to merge it.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Ask any questions you have related to developing your solution**
|
||||
A clear and concise set of questions you'd like to ask.
|
||||
@@ -1 +0,0 @@
|
||||
3.0
|
||||
@@ -13,8 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
fileprivate func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any]?) -> Bool {
|
||||
private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
@@ -40,7 +39,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
@@ -29,6 +39,11 @@
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
@@ -1,54 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="8es-i5-QRh">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="VDo-YK-ZHx">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<navigationController id="8es-i5-QRh" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" id="XHs-h3-Wt0">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<gestureRecognizers/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="barTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="gQC-s5-YYp" kind="relationship" relationship="rootViewController" id="hL1-vz-erR"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Xx8-5L-ee5" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-561" y="336.99999999999994"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="Ksu-iT-xHl">
|
||||
<objects>
|
||||
<viewController id="gQC-s5-YYp" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="ZZW-BN-qTx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2016 Jon Kent. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
|
||||
<rect key="frame" x="20" y="626.5" width="335" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SideMenu" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||
<rect key="frame" x="20" y="202" width="335" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
|
||||
<constraint firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
|
||||
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
|
||||
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="Z5N-rE-oLS"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="NJs-Nl-tMd">
|
||||
<barButtonItem key="backBarButtonItem" title=" " id="Z6X-gi-A0H"/>
|
||||
</navigationItem>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="rlc-KC-ZA1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
<point key="canvasLocation" x="142" y="336"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
||||
+247
-223
@@ -1,12 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yAA-s6-Bam">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="yAA-s6-Bam">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
@@ -15,7 +13,7 @@
|
||||
<objects>
|
||||
<navigationController id="yAA-s6-Bam" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" id="Bue-4e-bCJ">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<gestureRecognizers/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -33,111 +31,24 @@
|
||||
<scene sceneID="XZh-dw-B7D">
|
||||
<objects>
|
||||
<viewController id="QHN-nZ-kbB" customClass="MainViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Rm7-bv-OCN"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="LW0-9z-RHu"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="0gg-po-Ih1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LFJ-SB-Zp9">
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="571"/>
|
||||
<rect key="frame" x="0.0" y="44" width="375" height="591"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DMn-tw-NTB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="469"/>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="iBe-qv-i0y">
|
||||
<rect key="frame" x="20" y="20" width="335" height="681"/>
|
||||
<subviews>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="pqT-4M-nw1">
|
||||
<rect key="frame" x="18" y="167" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeSlider:" destination="QHN-nZ-kbB" eventType="valueChanged" id="Kcj-yD-lS0"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Present Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Efp-5L-qft">
|
||||
<rect key="frame" x="20" y="8" width="154" height="20.5"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Presentation Style" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Efp-5L-qft">
|
||||
<rect key="frame" x="0.0" y="0.0" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Screen Width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Snj-Mg-6ww">
|
||||
<rect key="frame" x="20" y="272" width="151" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Osf-2d-Znm">
|
||||
<rect key="frame" x="18" y="234" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeSlider:" destination="QHN-nZ-kbB" eventType="valueChanged" id="cRR-z8-cmm"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="owH-AA-wgw">
|
||||
<rect key="frame" x="20" y="102" width="335" height="29"/>
|
||||
<segments>
|
||||
<segment title="None"/>
|
||||
<segment title="Dark"/>
|
||||
<segment title="Light"/>
|
||||
<segment title="ExtraLight"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="changeSegment:" destination="QHN-nZ-kbB" eventType="valueChanged" id="Mna-Yh-fHu"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.001" minValue="0.001" maxValue="2" translatesAutoresizingMaskIntoConstraints="NO" id="Xp9-C5-Td1">
|
||||
<rect key="frame" x="18" y="368" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeSlider:" destination="QHN-nZ-kbB" eventType="valueChanged" id="PMM-8h-apN"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Shadow Opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2QC-6F-Xpx">
|
||||
<rect key="frame" x="20" y="205" width="172.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Cor-r1-osR">
|
||||
<rect key="frame" x="18" y="301" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeSlider:" destination="QHN-nZ-kbB" eventType="valueChanged" id="TSE-rt-Run"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Transform Scale Factor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tsg-30-YHs">
|
||||
<rect key="frame" x="20" y="339" width="225" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Blur Style" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OHe-SA-S0e">
|
||||
<rect key="frame" x="20" y="73" width="120.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Fade Strength" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tRs-iN-9Ht">
|
||||
<rect key="frame" x="20" y="138" width="155.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Fade Status Bar" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gtc-KE-FIO">
|
||||
<rect key="frame" x="20" y="423.5" width="168.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oFS-2Q-kPB">
|
||||
<rect key="frame" x="306" y="418" width="51" height="31"/>
|
||||
<color key="onTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeSwitch:" destination="QHN-nZ-kbB" eventType="valueChanged" id="2wD-Py-Q4n"/>
|
||||
</connections>
|
||||
</switch>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="KV2-tN-Aff">
|
||||
<rect key="frame" x="20" y="37" width="335" height="29"/>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="KV2-tN-Aff">
|
||||
<rect key="frame" x="0.0" y="28.5" width="335" height="32"/>
|
||||
<segments>
|
||||
<segment title="Slide In"/>
|
||||
<segment title="Slide Out"/>
|
||||
@@ -145,59 +56,185 @@
|
||||
<segment title="Dissolve"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="changeSegment:" destination="QHN-nZ-kbB" eventType="valueChanged" id="B2a-9p-5O1"/>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="y76-7g-AuZ"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wsl-iY-a5K">
|
||||
<rect key="frame" x="0.0" y="67.5" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="oRw-Gi-ezT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Blur Style" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OHe-SA-S0e">
|
||||
<rect key="frame" x="0.0" y="79.5" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="owH-AA-wgw">
|
||||
<rect key="frame" x="0.0" y="108" width="335" height="32"/>
|
||||
<segments>
|
||||
<segment title="None"/>
|
||||
<segment title="Dark"/>
|
||||
<segment title="Light"/>
|
||||
<segment title="ExtraLight"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="UkJ-YS-OXg"/>
|
||||
</connections>
|
||||
</segmentedControl>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="svy-p5-tiL">
|
||||
<rect key="frame" x="0.0" y="147" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="wra-S3-qWU"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Start Alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tRs-iN-9Ht">
|
||||
<rect key="frame" x="0.0" y="159" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="pqT-4M-nw1">
|
||||
<rect key="frame" x="-2" y="187.5" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="Rfw-ZT-ziI"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="r3M-VQ-eCj">
|
||||
<rect key="frame" x="0.0" y="225.5" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="RvV-Fo-ext"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Presenting End Alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NmN-uG-ABp">
|
||||
<rect key="frame" x="0.0" y="237.5" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="xlA-NK-mN4">
|
||||
<rect key="frame" x="-2" y="266" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="ah6-OO-Zh9"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bjn-LU-15M">
|
||||
<rect key="frame" x="0.0" y="304" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="jLL-oP-eBj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Shadow Opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2QC-6F-Xpx">
|
||||
<rect key="frame" x="0.0" y="316" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Osf-2d-Znm">
|
||||
<rect key="frame" x="-2" y="344.5" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="Vw7-lT-kal"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cKX-Y9-C8e">
|
||||
<rect key="frame" x="0.0" y="382.5" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="6m5-zX-BY6"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Screen Width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Snj-Mg-6ww">
|
||||
<rect key="frame" x="0.0" y="394.5" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Cor-r1-osR">
|
||||
<rect key="frame" x="-2" y="423" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="QfP-ZL-gGs"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="03z-3b-0TF">
|
||||
<rect key="frame" x="0.0" y="461" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="Kf2-9J-fIV"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Scale Factor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tsg-30-YHs">
|
||||
<rect key="frame" x="0.0" y="473" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.001" minValue="0.001" maxValue="2" translatesAutoresizingMaskIntoConstraints="NO" id="Xp9-C5-Td1">
|
||||
<rect key="frame" x="-2" y="501.5" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="lNd-9Z-lpP"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FrH-kR-j43">
|
||||
<rect key="frame" x="0.0" y="539.5" width="335" height="4"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="4" id="9kG-hd-eZS"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Presenting Scale Factor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="j7p-7c-wlI">
|
||||
<rect key="frame" x="0.0" y="551.5" width="335" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.001" minValue="0.001" maxValue="2" translatesAutoresizingMaskIntoConstraints="NO" id="Oso-tQ-0MO">
|
||||
<rect key="frame" x="-2" y="580" width="339" height="31"/>
|
||||
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="TuI-Au-hWY"/>
|
||||
</connections>
|
||||
</slider>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DMn-tw-NTB">
|
||||
<rect key="frame" x="0.0" y="618" width="335" height="63"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Fade Status Bar" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gtc-KE-FIO">
|
||||
<rect key="frame" x="0.0" y="17.5" width="168.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oFS-2Q-kPB">
|
||||
<rect key="frame" x="286" y="12" width="51" height="31"/>
|
||||
<color key="onTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<action selector="changeControl:" destination="QHN-nZ-kbB" eventType="valueChanged" id="07O-77-z6m"/>
|
||||
</connections>
|
||||
</switch>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="oFS-2Q-kPB" secondAttribute="bottom" constant="20" id="JOj-wa-d77"/>
|
||||
<constraint firstItem="Gtc-KE-FIO" firstAttribute="centerY" secondItem="oFS-2Q-kPB" secondAttribute="centerY" id="K3W-KT-drz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="oFS-2Q-kPB" secondAttribute="trailing" id="Srm-9Q-3KT"/>
|
||||
<constraint firstItem="oFS-2Q-kPB" firstAttribute="top" secondItem="DMn-tw-NTB" secondAttribute="top" constant="12" id="rXQ-lL-9SH"/>
|
||||
<constraint firstItem="Gtc-KE-FIO" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" id="rdp-LR-6EL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="KV2-tN-Aff" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="0Xw-7D-HJS"/>
|
||||
<constraint firstItem="pqT-4M-nw1" firstAttribute="top" secondItem="tRs-iN-9Ht" secondAttribute="bottom" constant="8.5" id="4E7-dh-BVN"/>
|
||||
<constraint firstItem="Snj-Mg-6ww" firstAttribute="top" secondItem="Osf-2d-Znm" secondAttribute="bottom" constant="8" id="8Ao-Li-Epv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="KV2-tN-Aff" secondAttribute="trailing" constant="20" id="8Kt-Kr-IfW"/>
|
||||
<constraint firstItem="Efp-5L-qft" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="9Ni-I7-vh7"/>
|
||||
<constraint firstItem="tRs-iN-9Ht" firstAttribute="top" secondItem="owH-AA-wgw" secondAttribute="bottom" constant="8" id="9dH-pj-fjK"/>
|
||||
<constraint firstItem="2QC-6F-Xpx" firstAttribute="top" secondItem="pqT-4M-nw1" secondAttribute="bottom" constant="8" id="Dop-eI-Rbx"/>
|
||||
<constraint firstItem="owH-AA-wgw" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="Ges-hw-pKE"/>
|
||||
<constraint firstItem="Tsg-30-YHs" firstAttribute="top" secondItem="Cor-r1-osR" secondAttribute="bottom" constant="8" id="HRj-lJ-fP0"/>
|
||||
<constraint firstItem="Cor-r1-osR" firstAttribute="top" secondItem="Snj-Mg-6ww" secondAttribute="bottom" constant="8.5" id="IiO-0v-8ZM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="oFS-2Q-kPB" secondAttribute="bottom" constant="20" id="JOj-wa-d77"/>
|
||||
<constraint firstItem="Gtc-KE-FIO" firstAttribute="centerY" secondItem="oFS-2Q-kPB" secondAttribute="centerY" id="K3W-KT-drz"/>
|
||||
<constraint firstItem="Tsg-30-YHs" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="LKY-Cl-eby"/>
|
||||
<constraint firstItem="pqT-4M-nw1" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="NU7-Qv-W7e"/>
|
||||
<constraint firstItem="tRs-iN-9Ht" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="NkW-aK-ri6"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Cor-r1-osR" secondAttribute="trailing" constant="20" id="Olk-Cf-bYo"/>
|
||||
<constraint firstItem="OHe-SA-S0e" firstAttribute="top" secondItem="KV2-tN-Aff" secondAttribute="bottom" constant="8" id="PK0-Y3-fVe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="owH-AA-wgw" secondAttribute="trailing" constant="20" id="S3u-3a-WE4"/>
|
||||
<constraint firstItem="Xp9-C5-Td1" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="SYl-4Z-bdP"/>
|
||||
<constraint firstAttribute="trailing" secondItem="oFS-2Q-kPB" secondAttribute="trailing" constant="20" id="Srm-9Q-3KT"/>
|
||||
<constraint firstItem="Osf-2d-Znm" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="TLj-8B-NIM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Xp9-C5-Td1" secondAttribute="trailing" constant="20" id="ch1-dJ-pie"/>
|
||||
<constraint firstItem="oFS-2Q-kPB" firstAttribute="top" secondItem="Xp9-C5-Td1" secondAttribute="bottom" constant="20" id="emb-zX-GbP"/>
|
||||
<constraint firstItem="Cor-r1-osR" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="jPg-kK-NEg"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pqT-4M-nw1" secondAttribute="trailing" constant="20" id="jaX-aN-HJU"/>
|
||||
<constraint firstItem="owH-AA-wgw" firstAttribute="top" secondItem="OHe-SA-S0e" secondAttribute="bottom" constant="8.5" id="lAg-sf-9xb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Osf-2d-Znm" secondAttribute="trailing" constant="20" id="lS6-KH-Diz"/>
|
||||
<constraint firstItem="Snj-Mg-6ww" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="mMS-Cb-uWu"/>
|
||||
<constraint firstItem="KV2-tN-Aff" firstAttribute="top" secondItem="Efp-5L-qft" secondAttribute="bottom" constant="8.5" id="nqY-9A-okx"/>
|
||||
<constraint firstItem="2QC-6F-Xpx" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="nwA-9O-eAJ"/>
|
||||
<constraint firstItem="Gtc-KE-FIO" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="rdp-LR-6EL"/>
|
||||
<constraint firstItem="OHe-SA-S0e" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="sbb-k6-xRo"/>
|
||||
<constraint firstItem="Efp-5L-qft" firstAttribute="top" secondItem="DMn-tw-NTB" secondAttribute="top" constant="8" id="tLT-mz-TL7"/>
|
||||
<constraint firstItem="Xp9-C5-Td1" firstAttribute="top" secondItem="Tsg-30-YHs" secondAttribute="bottom" constant="8.5" id="v65-v6-lcg"/>
|
||||
<constraint firstItem="Osf-2d-Znm" firstAttribute="top" secondItem="2QC-6F-Xpx" secondAttribute="bottom" constant="8.5" id="w9V-Ww-OfN"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="DMn-tw-NTB" firstAttribute="leading" secondItem="LFJ-SB-Zp9" secondAttribute="leading" id="BTk-bF-S0d"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DMn-tw-NTB" secondAttribute="trailing" id="M93-XD-94I"/>
|
||||
<constraint firstItem="DMn-tw-NTB" firstAttribute="width" secondItem="LFJ-SB-Zp9" secondAttribute="width" id="MCM-o2-30q"/>
|
||||
<constraint firstItem="DMn-tw-NTB" firstAttribute="top" secondItem="LFJ-SB-Zp9" secondAttribute="top" id="QhZ-ly-cBA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="DMn-tw-NTB" secondAttribute="bottom" id="sFU-Ot-379"/>
|
||||
<constraint firstAttribute="bottom" secondItem="iBe-qv-i0y" secondAttribute="bottom" id="2eW-ho-pUq"/>
|
||||
<constraint firstItem="iBe-qv-i0y" firstAttribute="leading" secondItem="LFJ-SB-Zp9" secondAttribute="leading" constant="20" id="3hL-bu-Q3Q"/>
|
||||
<constraint firstItem="iBe-qv-i0y" firstAttribute="centerX" secondItem="LFJ-SB-Zp9" secondAttribute="centerX" id="CSK-X3-R8W"/>
|
||||
<constraint firstAttribute="trailing" secondItem="iBe-qv-i0y" secondAttribute="trailing" constant="20" id="hIF-Hy-Smw"/>
|
||||
<constraint firstItem="iBe-qv-i0y" firstAttribute="top" secondItem="LFJ-SB-Zp9" secondAttribute="top" constant="20" id="v0I-Gh-S3A"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="← Swipe Screen Edges in View →" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ma4-O6-wOT">
|
||||
<rect key="frame" x="87.5" y="643" width="200.5" height="16"/>
|
||||
<rect key="frame" x="87" y="643" width="201.5" height="16"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -205,14 +242,15 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="leading" secondItem="0gg-po-Ih1" secondAttribute="leading" id="OsA-4z-Y7t"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="leading" secondItem="x7m-y5-rfi" secondAttribute="leading" id="OsA-4z-Y7t"/>
|
||||
<constraint firstItem="ma4-O6-wOT" firstAttribute="top" secondItem="LFJ-SB-Zp9" secondAttribute="bottom" constant="8" id="UUi-lo-0RA"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="Rm7-bv-OCN" secondAttribute="bottom" id="W6M-QX-I2w"/>
|
||||
<constraint firstItem="ma4-O6-wOT" firstAttribute="centerX" secondItem="0gg-po-Ih1" secondAttribute="centerX" id="aia-PT-OH3"/>
|
||||
<constraint firstItem="LW0-9z-RHu" firstAttribute="top" secondItem="ma4-O6-wOT" secondAttribute="bottom" constant="8" id="d5Q-Sj-0Xz"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="Rm7-bv-OCN" secondAttribute="bottom" id="ssi-ps-a2k"/>
|
||||
<constraint firstAttribute="trailing" secondItem="LFJ-SB-Zp9" secondAttribute="trailing" id="t0e-pR-bB1"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="x7m-y5-rfi" secondAttribute="top" id="W6M-QX-I2w"/>
|
||||
<constraint firstItem="ma4-O6-wOT" firstAttribute="centerX" secondItem="x7m-y5-rfi" secondAttribute="centerX" id="aia-PT-OH3"/>
|
||||
<constraint firstItem="x7m-y5-rfi" firstAttribute="bottom" secondItem="ma4-O6-wOT" secondAttribute="bottom" constant="8" id="d5Q-Sj-0Xz"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="x7m-y5-rfi" secondAttribute="top" id="ssi-ps-a2k"/>
|
||||
<constraint firstItem="x7m-y5-rfi" firstAttribute="trailing" secondItem="LFJ-SB-Zp9" secondAttribute="trailing" id="t0e-pR-bB1"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="x7m-y5-rfi"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="ssi-ps-a2k"/>
|
||||
@@ -235,11 +273,13 @@
|
||||
<connections>
|
||||
<outlet property="blackOutStatusBar" destination="oFS-2Q-kPB" id="wrn-ru-xmL"/>
|
||||
<outlet property="blurSegmentControl" destination="owH-AA-wgw" id="OKW-xQ-7UM"/>
|
||||
<outlet property="darknessSlider" destination="pqT-4M-nw1" id="Bka-VM-Plx"/>
|
||||
<outlet property="presentModeSegmentedControl" destination="KV2-tN-Aff" id="dzq-Bi-3Zp"/>
|
||||
<outlet property="menuAlphaSlider" destination="pqT-4M-nw1" id="X32-tm-KBc"/>
|
||||
<outlet property="menuScaleFactorSlider" destination="Xp9-C5-Td1" id="gyq-PL-JO7"/>
|
||||
<outlet property="presentationStyleSegmentedControl" destination="KV2-tN-Aff" id="dzq-Bi-3Zp"/>
|
||||
<outlet property="presentingAlphaSlider" destination="xlA-NK-mN4" id="Dg9-nd-07P"/>
|
||||
<outlet property="presentingScaleFactorSlider" destination="Oso-tQ-0MO" id="TVy-sK-3NK"/>
|
||||
<outlet property="screenWidthSlider" destination="Cor-r1-osR" id="pOL-9d-Weh"/>
|
||||
<outlet property="shadowOpacitySlider" destination="Osf-2d-Znm" id="6ai-oQ-d06"/>
|
||||
<outlet property="shrinkFactorSlider" destination="Xp9-C5-Td1" id="i3p-s2-Y9E"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="uVk-3R-pAo" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@@ -249,9 +289,10 @@
|
||||
<!--Side Menu Navigation Controller-->
|
||||
<scene sceneID="Zbc-0f-8nT">
|
||||
<objects>
|
||||
<navigationController storyboardIdentifier="LeftMenuNavigationController" navigationBarHidden="YES" id="DuX-EW-0mP" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationController storyboardIdentifier="LeftMenuNavigationController" navigationBarHidden="YES" id="DuX-EW-0mP" customClass="SideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationItem key="navigationItem" id="ipz-Lx-Wgf"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="35F-wh-r6h">
|
||||
<rect key="frame" x="0.0" y="-20" width="0.0" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<userDefinedRuntimeAttributes>
|
||||
@@ -270,13 +311,13 @@
|
||||
<objects>
|
||||
<tableViewController id="V6g-oO-Tbm" customClass="SideMenuTableViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="Dqh-bs-m2M">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<color key="tintColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<inset key="separatorInset" minX="15" minY="0.0" maxX="8" maxY="0.0"/>
|
||||
<view key="tableFooterView" contentMode="scaleToFill" id="vVB-ag-TnU">
|
||||
<rect key="frame" x="0.0" y="132" width="375" height="0.0"/>
|
||||
<rect key="frame" x="0.0" y="188" width="375" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
@@ -284,14 +325,14 @@
|
||||
<tableViewSection id="gP8-eA-dcW">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="4WI-Ed-3Gr" style="IBUITableViewCellStyleDefault" id="7tx-O6-zAs" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="7tx-O6-zAs" id="K0u-J2-Ab7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Push View Controller 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4WI-Ed-3Gr">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -305,14 +346,14 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="DpJ-hV-lmw" style="IBUITableViewCellStyleDefault" id="f9Q-QP-TZ6" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="44" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="72" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="f9Q-QP-TZ6" id="i3p-Ya-AvO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Push View Controller 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="DpJ-hV-lmw">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -326,14 +367,14 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="mAf-mx-C48" style="IBUITableViewCellStyleDefault" id="dc6-l8-0cu" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="88" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="116" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dc6-l8-0cu" id="gyo-JQ-fx5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Push View Controller 3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="mAf-mx-C48">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -364,14 +405,11 @@
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="bCi-eF-6hb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="WdI-PK-HMg"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.80000001190000003" green="1" blue="0.40000000600000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="tWG-DO-ZIZ"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="You Can Still Swipe!" id="LXz-Eu-D0y">
|
||||
<barButtonItem key="backBarButtonItem" title=" " id="igL-eY-0yM"/>
|
||||
@@ -384,8 +422,9 @@
|
||||
<!--Side Menu Navigation Controller-->
|
||||
<scene sceneID="kei-0w-mFw">
|
||||
<objects>
|
||||
<navigationController storyboardIdentifier="RightMenuNavigationController" navigationBarHidden="YES" id="z7k-fk-pfc" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationController storyboardIdentifier="RightMenuNavigationController" navigationBarHidden="YES" id="z7k-fk-pfc" customClass="SideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="qOd-yQ-2i8">
|
||||
<rect key="frame" x="0.0" y="-20" width="0.0" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
@@ -401,12 +440,12 @@
|
||||
<objects>
|
||||
<tableViewController id="Ol4-YR-KUL" customClass="SideMenuTableViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="49z-eA-JB7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="15" maxY="0.0"/>
|
||||
<view key="tableFooterView" contentMode="scaleToFill" id="UXT-t2-k90">
|
||||
<rect key="frame" x="0.0" y="132" width="375" height="0.0"/>
|
||||
<rect key="frame" x="0.0" y="188" width="375" height="0.0"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
@@ -414,14 +453,14 @@
|
||||
<tableViewSection id="xTE-WH-UeX">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="NLA-8t-ufi" style="IBUITableViewCellStyleDefault" id="8Ng-b4-4hH" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8Ng-b4-4hH" id="U5K-l9-XWv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Present View Controller 1" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="NLA-8t-ufi">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -431,18 +470,18 @@
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<connections>
|
||||
<segue destination="uMV-sw-TbB" kind="presentation" id="7VM-K4-IQ0"/>
|
||||
<segue destination="uMV-sw-TbB" kind="presentation" modalPresentationStyle="fullScreen" id="7VM-K4-IQ0"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="IdU-2D-zHb" style="IBUITableViewCellStyleDefault" id="Eok-gX-LwQ" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="44" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="72" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Eok-gX-LwQ" id="IOJ-bC-bNt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Present View Controller 2" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="IdU-2D-zHb">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -456,14 +495,14 @@
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="6x7-O7-DkG" style="IBUITableViewCellStyleDefault" id="41i-KK-YM3" customClass="UITableViewVibrantCell" customModule="SideMenu">
|
||||
<rect key="frame" x="0.0" y="88" width="375" height="44"/>
|
||||
<rect key="frame" x="0.0" y="116" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="41i-KK-YM3" id="629-G3-Agl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Present View Controller 3" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6x7-O7-DkG">
|
||||
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -494,10 +533,6 @@
|
||||
<scene sceneID="1Bw-F8-wcb">
|
||||
<objects>
|
||||
<viewController id="uMV-sw-TbB" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="CUv-pn-QnG"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Y6o-PP-5OP"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="087-P6-J9s">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
@@ -514,12 +549,13 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="Y6o-PP-5OP" firstAttribute="top" secondItem="TJh-vs-sd4" secondAttribute="bottom" id="4Dc-FA-01g"/>
|
||||
<constraint firstItem="TJh-vs-sd4" firstAttribute="top" secondItem="CUv-pn-QnG" secondAttribute="bottom" id="JJZ-xG-7d7"/>
|
||||
<constraint firstItem="TSP-pU-CHw" firstAttribute="bottom" secondItem="TJh-vs-sd4" secondAttribute="bottom" id="4Dc-FA-01g"/>
|
||||
<constraint firstItem="TJh-vs-sd4" firstAttribute="top" secondItem="TSP-pU-CHw" secondAttribute="top" id="JJZ-xG-7d7"/>
|
||||
<constraint firstItem="TJh-vs-sd4" firstAttribute="top" secondItem="087-P6-J9s" secondAttribute="top" id="UJb-lR-QB7"/>
|
||||
<constraint firstItem="TJh-vs-sd4" firstAttribute="leading" secondItem="087-P6-J9s" secondAttribute="leading" id="WfV-Kk-KZn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="TJh-vs-sd4" secondAttribute="trailing" id="nDl-ag-4Xh"/>
|
||||
<constraint firstItem="TJh-vs-sd4" firstAttribute="leading" secondItem="TSP-pU-CHw" secondAttribute="leading" id="WfV-Kk-KZn"/>
|
||||
<constraint firstItem="TSP-pU-CHw" firstAttribute="trailing" secondItem="TJh-vs-sd4" secondAttribute="trailing" id="nDl-ag-4Xh"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="TSP-pU-CHw"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="JJZ-xG-7d7"/>
|
||||
@@ -536,16 +572,12 @@
|
||||
<scene sceneID="afw-j1-hgm">
|
||||
<objects>
|
||||
<viewController id="Upx-FH-Mbv" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="o4B-82-huU"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Cg1-5G-fVh"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="efR-Hd-Gxy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cKk-fD-whk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<state key="normal" title="Dismiss">
|
||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
@@ -557,11 +589,12 @@
|
||||
<color key="backgroundColor" red="0.40000000600000002" green="0.40000000600000002" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="cKk-fD-whk" firstAttribute="top" secondItem="efR-Hd-Gxy" secondAttribute="top" id="14o-4k-9wZ"/>
|
||||
<constraint firstItem="cKk-fD-whk" firstAttribute="leading" secondItem="efR-Hd-Gxy" secondAttribute="leading" id="BI7-Em-0rv"/>
|
||||
<constraint firstItem="cKk-fD-whk" firstAttribute="top" secondItem="o4B-82-huU" secondAttribute="bottom" id="c7O-I7-GYg"/>
|
||||
<constraint firstAttribute="trailing" secondItem="cKk-fD-whk" secondAttribute="trailing" id="cQ8-xJ-kZK"/>
|
||||
<constraint firstItem="Cg1-5G-fVh" firstAttribute="top" secondItem="cKk-fD-whk" secondAttribute="bottom" id="flh-y2-QfX"/>
|
||||
<constraint firstItem="cKk-fD-whk" firstAttribute="leading" secondItem="BaQ-yt-6sz" secondAttribute="leading" id="BI7-Em-0rv"/>
|
||||
<constraint firstItem="cKk-fD-whk" firstAttribute="top" secondItem="BaQ-yt-6sz" secondAttribute="top" id="c7O-I7-GYg"/>
|
||||
<constraint firstItem="BaQ-yt-6sz" firstAttribute="trailing" secondItem="cKk-fD-whk" secondAttribute="trailing" id="cQ8-xJ-kZK"/>
|
||||
<constraint firstItem="BaQ-yt-6sz" firstAttribute="bottom" secondItem="cKk-fD-whk" secondAttribute="bottom" id="flh-y2-QfX"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="BaQ-yt-6sz"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="c7O-I7-GYg"/>
|
||||
@@ -578,16 +611,12 @@
|
||||
<scene sceneID="lxj-KK-fq7">
|
||||
<objects>
|
||||
<viewController id="EG7-2X-5hP" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="hJH-tK-XeV"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="e3Y-bn-25N"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="vac-ts-bf9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a17-pq-WAQ">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<state key="normal" title="Dismiss">
|
||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
@@ -598,12 +627,13 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="0.40000000600000002" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="e3Y-bn-25N" firstAttribute="top" secondItem="a17-pq-WAQ" secondAttribute="bottom" id="5xQ-vm-6fc"/>
|
||||
<constraint firstAttribute="trailing" secondItem="a17-pq-WAQ" secondAttribute="trailing" id="Hxw-zj-3jZ"/>
|
||||
<constraint firstItem="A8B-VL-gbR" firstAttribute="bottom" secondItem="a17-pq-WAQ" secondAttribute="bottom" id="5xQ-vm-6fc"/>
|
||||
<constraint firstItem="A8B-VL-gbR" firstAttribute="trailing" secondItem="a17-pq-WAQ" secondAttribute="trailing" id="Hxw-zj-3jZ"/>
|
||||
<constraint firstItem="a17-pq-WAQ" firstAttribute="top" secondItem="vac-ts-bf9" secondAttribute="topMargin" id="MC9-JY-ajb"/>
|
||||
<constraint firstItem="a17-pq-WAQ" firstAttribute="leading" secondItem="vac-ts-bf9" secondAttribute="leading" id="v2E-c1-L5X"/>
|
||||
<constraint firstItem="a17-pq-WAQ" firstAttribute="top" secondItem="hJH-tK-XeV" secondAttribute="bottom" id="zAS-oF-Owc"/>
|
||||
<constraint firstItem="a17-pq-WAQ" firstAttribute="leading" secondItem="A8B-VL-gbR" secondAttribute="leading" id="v2E-c1-L5X"/>
|
||||
<constraint firstItem="a17-pq-WAQ" firstAttribute="top" secondItem="A8B-VL-gbR" secondAttribute="top" id="zAS-oF-Owc"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="A8B-VL-gbR"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="zAS-oF-Owc"/>
|
||||
@@ -620,14 +650,11 @@
|
||||
<scene sceneID="6GP-Jo-SOW">
|
||||
<objects>
|
||||
<viewController id="u7M-mb-V6o" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="RTd-LU-QPL"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="MN7-Vy-BNb"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="9Dr-7n-COJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="0.80000001190000003" blue="0.40000000600000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="hUi-v8-7VE"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="You Can Still Swipe!" id="I4v-gH-e3M">
|
||||
<barButtonItem key="backBarButtonItem" title=" " id="csP-tV-uyu"/>
|
||||
@@ -641,14 +668,11 @@
|
||||
<scene sceneID="ZQL-2c-L6r">
|
||||
<objects>
|
||||
<viewController id="b5t-IX-0yu" customClass="PresentedViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="rfX-xz-c0N"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Iuo-on-rwS"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ias-bH-Sau">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="647"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="0.40000000600000002" blue="0.40000000600000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="bHF-BB-8F0"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="You Can Still Swipe!" id="VCv-tR-uCt">
|
||||
<barButtonItem key="backBarButtonItem" title=" " id="Xem-d1-6TQ"/>
|
||||
|
||||
@@ -8,106 +8,111 @@
|
||||
import SideMenu
|
||||
|
||||
class MainViewController: UIViewController {
|
||||
|
||||
@IBOutlet fileprivate weak var presentModeSegmentedControl:UISegmentedControl!
|
||||
@IBOutlet fileprivate weak var blurSegmentControl:UISegmentedControl!
|
||||
@IBOutlet fileprivate weak var darknessSlider:UISlider!
|
||||
@IBOutlet fileprivate weak var shadowOpacitySlider:UISlider!
|
||||
@IBOutlet fileprivate weak var screenWidthSlider:UISlider!
|
||||
@IBOutlet fileprivate weak var shrinkFactorSlider:UISlider!
|
||||
@IBOutlet fileprivate weak var blackOutStatusBar:UISwitch!
|
||||
|
||||
@IBOutlet private weak var blackOutStatusBar: UISwitch!
|
||||
@IBOutlet private weak var blurSegmentControl: UISegmentedControl!
|
||||
@IBOutlet private weak var menuAlphaSlider: UISlider!
|
||||
@IBOutlet private weak var menuScaleFactorSlider: UISlider!
|
||||
@IBOutlet private weak var presentingAlphaSlider: UISlider!
|
||||
@IBOutlet private weak var presentingScaleFactorSlider: UISlider!
|
||||
@IBOutlet private weak var presentationStyleSegmentedControl: UISegmentedControl!
|
||||
@IBOutlet private weak var screenWidthSlider: UISlider!
|
||||
@IBOutlet private weak var shadowOpacitySlider: UISlider!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
setupSideMenu()
|
||||
setDefaults()
|
||||
updateUI(settings: SideMenuSettings())
|
||||
updateMenus()
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
guard let sideMenuNavigationController = segue.destination as? SideMenuNavigationController else { return }
|
||||
sideMenuNavigationController.settings = makeSettings()
|
||||
}
|
||||
|
||||
fileprivate func setupSideMenu() {
|
||||
private func setupSideMenu() {
|
||||
// Define the menus
|
||||
SideMenuManager.default.menuLeftNavigationController = storyboard!.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as? UISideMenuNavigationController
|
||||
SideMenuManager.default.menuRightNavigationController = storyboard!.instantiateViewController(withIdentifier: "RightMenuNavigationController") as? UISideMenuNavigationController
|
||||
SideMenuManager.default.leftMenuNavigationController = storyboard?.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as? SideMenuNavigationController
|
||||
SideMenuManager.default.rightMenuNavigationController = storyboard?.instantiateViewController(withIdentifier: "RightMenuNavigationController") as? SideMenuNavigationController
|
||||
|
||||
// Enable gestures. The left and/or right menus must be set up above for these to work.
|
||||
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
|
||||
SideMenuManager.default.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
|
||||
// Set up a cool background image for demo purposes
|
||||
SideMenuManager.default.menuAnimationBackgroundColor = UIColor(patternImage: UIImage(named: "background")!)
|
||||
SideMenuManager.default.addPanGestureToPresent(toView: navigationController!.navigationBar)
|
||||
SideMenuManager.default.addScreenEdgePanGesturesToPresent(toView: view)
|
||||
}
|
||||
|
||||
fileprivate func setDefaults() {
|
||||
let modes:[SideMenuManager.MenuPresentMode] = [.menuSlideIn, .viewSlideOut, .menuDissolveIn]
|
||||
presentModeSegmentedControl.selectedSegmentIndex = modes.index(of: SideMenuManager.default.menuPresentMode)!
|
||||
|
||||
let styles:[UIBlurEffectStyle] = [.dark, .light, .extraLight]
|
||||
if let menuBlurEffectStyle = SideMenuManager.default.menuBlurEffectStyle {
|
||||
blurSegmentControl.selectedSegmentIndex = styles.index(of: menuBlurEffectStyle) ?? 0
|
||||
private func updateUI(settings: SideMenuSettings) {
|
||||
let styles:[UIBlurEffect.Style] = [.dark, .light, .extraLight]
|
||||
if let menuBlurEffectStyle = settings.blurEffectStyle {
|
||||
blurSegmentControl.selectedSegmentIndex = (styles.firstIndex(of: menuBlurEffectStyle) ?? 0) + 1
|
||||
} else {
|
||||
blurSegmentControl.selectedSegmentIndex = 0
|
||||
}
|
||||
|
||||
darknessSlider.value = Float(SideMenuManager.default.menuAnimationFadeStrength)
|
||||
shadowOpacitySlider.value = Float(SideMenuManager.default.menuShadowOpacity)
|
||||
shrinkFactorSlider.value = Float(SideMenuManager.default.menuAnimationTransformScaleFactor)
|
||||
screenWidthSlider.value = Float(SideMenuManager.default.menuWidth / view.frame.width)
|
||||
blackOutStatusBar.isOn = SideMenuManager.default.menuFadeStatusBar
|
||||
}
|
||||
|
||||
@IBAction fileprivate func changeSegment(_ segmentControl: UISegmentedControl) {
|
||||
switch segmentControl {
|
||||
case presentModeSegmentedControl:
|
||||
let modes:[SideMenuManager.MenuPresentMode] = [.menuSlideIn, .viewSlideOut, .viewSlideInOut, .menuDissolveIn]
|
||||
SideMenuManager.default.menuPresentMode = modes[segmentControl.selectedSegmentIndex]
|
||||
case blurSegmentControl:
|
||||
if segmentControl.selectedSegmentIndex == 0 {
|
||||
SideMenuManager.default.menuBlurEffectStyle = nil
|
||||
} else {
|
||||
let styles:[UIBlurEffectStyle] = [.dark, .light, .extraLight]
|
||||
SideMenuManager.default.menuBlurEffectStyle = styles[segmentControl.selectedSegmentIndex - 1]
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction fileprivate func changeSlider(_ slider: UISlider) {
|
||||
switch slider {
|
||||
case darknessSlider:
|
||||
SideMenuManager.default.menuAnimationFadeStrength = CGFloat(slider.value)
|
||||
case shadowOpacitySlider:
|
||||
SideMenuManager.default.menuShadowOpacity = slider.value
|
||||
case shrinkFactorSlider:
|
||||
SideMenuManager.default.menuAnimationTransformScaleFactor = CGFloat(slider.value)
|
||||
case screenWidthSlider:
|
||||
SideMenuManager.default.menuWidth = view.frame.width * CGFloat(slider.value)
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction fileprivate func changeSwitch(_ switchControl: UISwitch) {
|
||||
SideMenuManager.default.menuFadeStatusBar = switchControl.isOn
|
||||
|
||||
blackOutStatusBar.isOn = settings.statusBarEndAlpha > 0
|
||||
menuAlphaSlider.value = Float(settings.presentationStyle.menuStartAlpha)
|
||||
menuScaleFactorSlider.value = Float(settings.presentationStyle.menuScaleFactor)
|
||||
presentingAlphaSlider.value = Float(settings.presentationStyle.presentingEndAlpha)
|
||||
presentingScaleFactorSlider.value = Float(settings.presentationStyle.presentingScaleFactor)
|
||||
screenWidthSlider.value = Float(settings.menuWidth / min(view.frame.width, view.frame.height))
|
||||
shadowOpacitySlider.value = Float(settings.presentationStyle.onTopShadowOpacity)
|
||||
}
|
||||
|
||||
@IBAction private func changeControl(_ control: UIControl) {
|
||||
if control == presentationStyleSegmentedControl {
|
||||
var settings = makeSettings()
|
||||
settings.presentationStyle = selectedPresentationStyle()
|
||||
updateUI(settings: settings)
|
||||
}
|
||||
updateMenus()
|
||||
}
|
||||
|
||||
private func updateMenus() {
|
||||
let settings = makeSettings()
|
||||
SideMenuManager.default.leftMenuNavigationController?.settings = settings
|
||||
SideMenuManager.default.rightMenuNavigationController?.settings = settings
|
||||
}
|
||||
|
||||
private func selectedPresentationStyle() -> SideMenuPresentationStyle {
|
||||
let modes: [SideMenuPresentationStyle] = [.menuSlideIn, .viewSlideOut, .viewSlideOutMenuIn, .menuDissolveIn]
|
||||
return modes[presentationStyleSegmentedControl.selectedSegmentIndex]
|
||||
}
|
||||
|
||||
private func makeSettings() -> SideMenuSettings {
|
||||
let presentationStyle = selectedPresentationStyle()
|
||||
presentationStyle.backgroundColor = UIColor(patternImage: #imageLiteral(resourceName: "background"))
|
||||
presentationStyle.menuStartAlpha = CGFloat(menuAlphaSlider.value)
|
||||
presentationStyle.menuScaleFactor = CGFloat(menuScaleFactorSlider.value)
|
||||
presentationStyle.onTopShadowOpacity = shadowOpacitySlider.value
|
||||
presentationStyle.presentingEndAlpha = CGFloat(presentingAlphaSlider.value)
|
||||
presentationStyle.presentingScaleFactor = CGFloat(presentingScaleFactorSlider.value)
|
||||
|
||||
var settings = SideMenuSettings()
|
||||
settings.presentationStyle = presentationStyle
|
||||
settings.menuWidth = min(view.frame.width, view.frame.height) * CGFloat(screenWidthSlider.value)
|
||||
let styles:[UIBlurEffect.Style?] = [nil, .dark, .light, .extraLight]
|
||||
settings.blurEffectStyle = styles[blurSegmentControl.selectedSegmentIndex]
|
||||
settings.statusBarEndAlpha = blackOutStatusBar.isOn ? 1 : 0
|
||||
|
||||
return settings
|
||||
}
|
||||
}
|
||||
|
||||
extension MainViewController: UISideMenuNavigationControllerDelegate {
|
||||
extension MainViewController: SideMenuNavigationControllerDelegate {
|
||||
|
||||
func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuWillAppear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuDidAppear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuWillDisappear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuDidDisappear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import UIKit
|
||||
|
||||
class PresentedViewController: UIViewController {
|
||||
|
||||
@IBAction fileprivate func close() {
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
@IBAction private func close() {
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
// Copyright © 2016 CocoaPods. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SideMenu
|
||||
|
||||
class SideMenuTableViewController: UITableViewController {
|
||||
@@ -17,12 +16,12 @@ class SideMenuTableViewController: UITableViewController {
|
||||
// refresh cell blur effect in case it changed
|
||||
tableView.reloadData()
|
||||
|
||||
guard SideMenuManager.default.menuBlurEffectStyle == nil else {
|
||||
guard let menu = navigationController as? SideMenuNavigationController, menu.blurEffectStyle == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
// Set up a cool background image for demo purposes
|
||||
let imageView = UIImageView(image: UIImage(named: "saturn"))
|
||||
let imageView = UIImageView(image: #imageLiteral(resourceName: "saturn"))
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
imageView.backgroundColor = UIColor.black.withAlphaComponent(0.2)
|
||||
tableView.backgroundView = imageView
|
||||
@@ -30,8 +29,10 @@ class SideMenuTableViewController: UITableViewController {
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = super.tableView(tableView, cellForRowAt: indexPath) as! UITableViewVibrantCell
|
||||
|
||||
cell.blurEffectStyle = SideMenuManager.default.menuBlurEffectStyle
|
||||
|
||||
if let menu = navigationController as? SideMenuNavigationController {
|
||||
cell.blurEffectStyle = menu.blurEffectStyle
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// ExampleTests.swift
|
||||
// ExampleTests
|
||||
//
|
||||
// Created by Jon Kent on 8/10/19.
|
||||
// Copyright © 2019 jonkykong. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class ExampleTests: XCTestCase {
|
||||
|
||||
private let styleTitles = ["Slide In", "Slide Out", "In + Out", "Dissolve"]
|
||||
private let swipeHere = "Swipe Here"
|
||||
|
||||
private let app = XCUIApplication()
|
||||
private var mainViewController: XCUIElement {
|
||||
return app.navigationBars[swipeHere]
|
||||
}
|
||||
|
||||
override func setUp() {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
|
||||
// In UI tests it is usually best to stop immediately when a failure occurs.
|
||||
continueAfterFailure = false
|
||||
|
||||
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
|
||||
XCUIApplication().launch()
|
||||
|
||||
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
func testTapLeft() {
|
||||
let elementsQuery = app.scrollViews.otherElements
|
||||
for title in styleTitles {
|
||||
elementsQuery.buttons[title].tap()
|
||||
mainViewController.buttons["Left Menu"].tap()
|
||||
app.tables/*@START_MENU_TOKEN@*/.staticTexts["Push View Controller 1"]/*[[".cells.staticTexts[\"Push View Controller 1\"]",".staticTexts[\"Push View Controller 1\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
|
||||
app.navigationBars["You Can Still Swipe!"].buttons[swipeHere].tap()
|
||||
validate()
|
||||
}
|
||||
}
|
||||
|
||||
func testTapRight() {
|
||||
let elementsQuery = app.scrollViews.otherElements
|
||||
for title in styleTitles {
|
||||
elementsQuery.buttons[title].tap()
|
||||
mainViewController.buttons["Right Menu"].tap()
|
||||
app.tables/*@START_MENU_TOKEN@*/.staticTexts["Present View Controller 1"]/*[[".cells.staticTexts[\"Present View Controller 1\"]",".staticTexts[\"Present View Controller 1\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap()
|
||||
app.buttons["Dismiss"].tap()
|
||||
mainViewController.tap()
|
||||
validate()
|
||||
}
|
||||
}
|
||||
|
||||
func testSwiping() {
|
||||
mainViewController.swipeRight()
|
||||
mainViewController.swipeLeft()
|
||||
validate()
|
||||
|
||||
mainViewController.swipeLeft()
|
||||
mainViewController.swipeRight()
|
||||
validate()
|
||||
}
|
||||
|
||||
private func validate() {
|
||||
XCTAssertTrue(mainViewController.exists)
|
||||
}
|
||||
|
||||
/* TODO - More tests:
|
||||
- Rotation
|
||||
- All menu settings
|
||||
*/
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -16,8 +16,6 @@
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import UIKit
|
||||
import XCTest
|
||||
import SideMenu
|
||||
|
||||
class Tests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
XCTAssert(true, "Pass")
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
self.measure() {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// swift-tools-version:5.0
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "SideMenu",
|
||||
products: [
|
||||
.library(name: "SideMenu", targets: ["SideMenu"])
|
||||
],
|
||||
dependencies: [],
|
||||
targets: [
|
||||
.target(name: "SideMenu", path: "Pod/Classes")
|
||||
],
|
||||
swiftLanguageVersions: [.v4_2, .v5]
|
||||
)
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// Deprecations.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 7/3/19.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
// Deprecations; to be removed at a future date.
|
||||
extension SideMenuManager {
|
||||
|
||||
@available(*, deprecated, renamed: "leftMenuNavigationController")
|
||||
open var menuLeftNavigationController: SideMenuNavigationController? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "rightMenuNavigationController")
|
||||
open var menuRightNavigationController: SideMenuNavigationController? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuPresentMode: SideMenuPresentationStyle {
|
||||
get { return .viewSlideOut }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuPushStyle: SideMenuPushStyle {
|
||||
get { return .default }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAllowPushOfSameClassTwice: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuWidth: CGFloat {
|
||||
get { return 0 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationPresentDuration: Double {
|
||||
get { return 0.35 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationDismissDuration: Double {
|
||||
get { return 0.35 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationCompleteGestureDuration: Double {
|
||||
get { return 0.35 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuAnimationFadeStrength: CGFloat {
|
||||
get { return 0 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuAnimationTransformScaleFactor: CGFloat {
|
||||
get { return 1 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuAnimationBackgroundColor: UIColor? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuShadowOpacity: Float {
|
||||
get { return 0.5 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuShadowColor: UIColor {
|
||||
get { return .black }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuShadowRadius: CGFloat {
|
||||
get { return 5 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuPresentingViewControllerUserInteractionEnabled: Bool {
|
||||
get { return false }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuPresentationStyle class.")
|
||||
public var menuParallaxStrength: Int {
|
||||
get { return 0 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuFadeStatusBar: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationOptions: UIView.AnimationOptions {
|
||||
get { return .curveEaseInOut }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationCompletionCurve: UIView.AnimationCurve {
|
||||
get { return .easeIn }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationUsingSpringWithDamping: CGFloat {
|
||||
get { return 1 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAnimationInitialSpringVelocity: CGFloat {
|
||||
get { return 1 }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuDismissOnPush: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuAlwaysAnimate: Bool {
|
||||
get { return false }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuDismissWhenBackgrounded: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuBlurEffectStyle: UIBlurEffect.Style? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get { return nil }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This property has been moved to the SideMenuNavigationController class.")
|
||||
public var menuEnableSwipeGestures: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "enableSwipeToDismissGesture")
|
||||
public var enableSwipeGestures: Bool {
|
||||
get { return true }
|
||||
set {}
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "SideMenuPresentationStyle")
|
||||
public typealias MenuPresentMode = SideMenuPresentationStyle
|
||||
|
||||
@available(*, deprecated, renamed: "addScreenEdgePanGesturesToPresent")
|
||||
@discardableResult public func menuAddScreenEdgePanGesturesToPresent(toView view: UIView, forMenu sides: [PresentDirection] = [.left, .right]) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
return []
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "addPanGestureToPresent")
|
||||
@discardableResult public func menuAddPanGestureToPresent(toView view: UIView) -> UIPanGestureRecognizer {
|
||||
return UIPanGestureRecognizer()
|
||||
}
|
||||
}
|
||||
|
||||
extension SideMenuPresentationStyle {
|
||||
@available(*, deprecated, renamed: "viewSlideOutMenuIn")
|
||||
public static var viewSlideInOut: SideMenuPresentationStyle { return viewSlideOutMenuIn }
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "SideMenuNavigationController")
|
||||
public typealias UISideMenuNavigationController = SideMenuNavigationController
|
||||
|
||||
@available(*, deprecated, renamed: "SideMenuNavigationControllerDelegate")
|
||||
public typealias UISideMenuNavigationControllerDelegate = SideMenuNavigationControllerDelegate
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Extensions.swift
|
||||
// Pods-Example
|
||||
//
|
||||
// Created by Jon Kent on 7/1/19.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension NSObject: InitializableClass {}
|
||||
|
||||
internal extension UIView {
|
||||
|
||||
@discardableResult func untransformed(_ block: () -> CGFloat) -> CGFloat {
|
||||
let t = transform
|
||||
transform = .identity
|
||||
let value = block()
|
||||
transform = t
|
||||
return value
|
||||
}
|
||||
|
||||
func bringToFront() {
|
||||
superview?.bringSubviewToFront(self)
|
||||
}
|
||||
|
||||
func untransform(_ block: () -> Void) {
|
||||
untransformed { () -> CGFloat in
|
||||
block()
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
static func animationsEnabled(_ enabled: Bool = true, _ block: () -> Void) {
|
||||
let a = areAnimationsEnabled
|
||||
setAnimationsEnabled(enabled)
|
||||
block()
|
||||
setAnimationsEnabled(a)
|
||||
}
|
||||
}
|
||||
|
||||
internal extension UIViewController {
|
||||
|
||||
// View controller actively displayed in that layer. It may not be visible if it's presenting another view controller.
|
||||
var activeViewController: UIViewController {
|
||||
switch self {
|
||||
case let navigationController as UINavigationController:
|
||||
return navigationController.topViewController?.activeViewController ?? self
|
||||
case let tabBarController as UITabBarController:
|
||||
return tabBarController.selectedViewController?.activeViewController ?? self
|
||||
case let splitViewController as UISplitViewController:
|
||||
return splitViewController.viewControllers.last?.activeViewController ?? self
|
||||
default:
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// View controller being displayed on screen to the user.
|
||||
var topMostViewController: UIViewController {
|
||||
let activeViewController = self.activeViewController
|
||||
return activeViewController.presentedViewController?.topMostViewController ?? activeViewController
|
||||
}
|
||||
|
||||
var containerViewController: UIViewController {
|
||||
return navigationController?.containerViewController ??
|
||||
tabBarController?.containerViewController ??
|
||||
splitViewController?.containerViewController ??
|
||||
self
|
||||
}
|
||||
|
||||
@objc var isHidden: Bool {
|
||||
return presentingViewController == nil
|
||||
}
|
||||
}
|
||||
|
||||
internal extension UIGestureRecognizer {
|
||||
|
||||
convenience init(addTo view: UIView, target: Any, action: Selector) {
|
||||
self.init(target: target, action: action)
|
||||
view.addGestureRecognizer(self)
|
||||
}
|
||||
|
||||
convenience init?(addTo view: UIView?, target: Any, action: Selector) {
|
||||
guard let view = view else { return nil }
|
||||
self.init(addTo: view, target: target, action: action)
|
||||
}
|
||||
|
||||
func remove() {
|
||||
view?.removeGestureRecognizer(self)
|
||||
}
|
||||
}
|
||||
|
||||
internal extension UIPanGestureRecognizer {
|
||||
|
||||
var canSwitch: Bool {
|
||||
return !(self is UIScreenEdgePanGestureRecognizer)
|
||||
}
|
||||
|
||||
var xTranslation: CGFloat {
|
||||
return view?.untransformed {
|
||||
return self.translation(in: view).x
|
||||
} ?? 0
|
||||
}
|
||||
|
||||
var xVelocity: CGFloat {
|
||||
return view?.untransformed {
|
||||
return self.velocity(in: view).x
|
||||
} ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
internal extension UIApplication {
|
||||
|
||||
var keyWindow: UIWindow? {
|
||||
return UIApplication.shared.windows.filter { $0.isKeyWindow }.first
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Initializable.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 7/2/19.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal protocol InitializableClass: class {
|
||||
init()
|
||||
}
|
||||
|
||||
extension InitializableClass {
|
||||
init(_ block: (Self) -> Void) {
|
||||
self.init()
|
||||
block(self)
|
||||
}
|
||||
|
||||
@discardableResult func with(_ block: (Self) -> Void) -> Self {
|
||||
block(self)
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
public protocol InitializableStruct {
|
||||
init()
|
||||
}
|
||||
|
||||
public extension InitializableStruct {
|
||||
init(_ block: (inout Self) -> Void) {
|
||||
self.init()
|
||||
block(&self)
|
||||
}
|
||||
|
||||
@discardableResult mutating func with(_ block: (inout Self) -> Void) -> Self {
|
||||
block(&self)
|
||||
return self
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Print.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 12/5/18.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal enum Print: String { case
|
||||
cannotPush = "Attempt to push a View Controller from %@ where its navigationController == nil. It must be embedded in a UINavigationController for this to work.",
|
||||
emptyMenu = "The menu doesn't have a view controller to show! SideMenuNavigationController needs a view controller to display just like a UINavigationController.",
|
||||
menuAlreadyAssigned = "%@ was already assigned to the %@ of %@. When using multiple SideMenuManagers you may want to use new instances of SideMenuNavigationController instead of existing instances to avoid crashes if the menu is presented more than once.",
|
||||
menuInUse = "%@ cannot be modified while it's presented.",
|
||||
panGestureAdded = "%@ was called before %@ or %@ was set. Gestures will not work without a menu.",
|
||||
property = "A menu's %@ property can only be changed when it is hidden.",
|
||||
screenGestureAdded = "%@ was called before %@ was set. The gesture will not work without a menu. Use %@ to add gestures for only one menu.",
|
||||
transitioningDelegate = "SideMenu requires use of the transitioningDelegate. It cannot be modified."
|
||||
|
||||
enum PropertyName: String { case
|
||||
leftSide
|
||||
}
|
||||
|
||||
static func warning(_ print: Print, arguments: CVarArg..., required: Bool = false) {
|
||||
warning(String(format: print.rawValue, arguments: arguments), required: required)
|
||||
}
|
||||
|
||||
static func warning(_ print: Print, arguments: PropertyName..., required: Bool = false) {
|
||||
warning(String(format: print.rawValue, arguments: arguments.map { $0.rawValue }), required: required)
|
||||
}
|
||||
|
||||
static func warning(_ print: Print, required: Bool = false) {
|
||||
warning(print.rawValue, required: required)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Print {
|
||||
|
||||
static func warning(_ message: String, required: Bool = false) {
|
||||
let message = "SideMenu Warning: \(message)"
|
||||
|
||||
if required {
|
||||
print(message)
|
||||
return
|
||||
}
|
||||
#if !STFU_SIDEMENU
|
||||
print(message)
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Protected.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 2/9/19.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal final class Protected<T: Equatable> {
|
||||
|
||||
typealias ConditionBlock = (_ oldValue: T, T) -> T
|
||||
|
||||
private var _value: T
|
||||
private var condition: ConditionBlock
|
||||
|
||||
public var value: T {
|
||||
get { return _value }
|
||||
set { _value = condition(_value, newValue) }
|
||||
}
|
||||
|
||||
init(_ value: T, when condition: @escaping ConditionBlock) {
|
||||
self._value = value
|
||||
self.condition = condition
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// SideMenuAnimationController.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 10/24/18.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
internal protocol AnimationModel {
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var animationOptions: UIView.AnimationOptions { get }
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
var completeGestureDuration: Double { get }
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
var dismissDuration: Double { get }
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var initialSpringVelocity: CGFloat { get }
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
var presentDuration: Double { get }
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var usingSpringWithDamping: CGFloat { get }
|
||||
}
|
||||
|
||||
internal protocol SideMenuAnimationControllerDelegate: class {
|
||||
func sideMenuAnimationController(_ animationController: SideMenuAnimationController, didDismiss viewController: UIViewController)
|
||||
func sideMenuAnimationController(_ animationController: SideMenuAnimationController, didPresent viewController: UIViewController)
|
||||
}
|
||||
|
||||
internal final class SideMenuAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
|
||||
|
||||
typealias Model = AnimationModel & PresentationModel
|
||||
|
||||
private var config: Model
|
||||
private weak var containerView: UIView?
|
||||
private let leftSide: Bool
|
||||
private weak var originalSuperview: UIView?
|
||||
private var presentationController: SideMenuPresentationController?
|
||||
private unowned var presentedViewController: UIViewController?
|
||||
private unowned var presentingViewController: UIViewController?
|
||||
weak var delegate: SideMenuAnimationControllerDelegate?
|
||||
|
||||
init(config: Model, leftSide: Bool, delegate: SideMenuAnimationControllerDelegate? = nil) {
|
||||
self.config = config
|
||||
self.leftSide = leftSide
|
||||
self.delegate = delegate
|
||||
}
|
||||
|
||||
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
guard
|
||||
let presentedViewController = transitionContext.presentedViewController,
|
||||
let presentingViewController = transitionContext.presentingViewController
|
||||
else { return }
|
||||
|
||||
if transitionContext.isPresenting {
|
||||
self.containerView = transitionContext.containerView
|
||||
self.presentedViewController = presentedViewController
|
||||
self.presentingViewController = presentingViewController
|
||||
self.presentationController = SideMenuPresentationController(
|
||||
config: config,
|
||||
leftSide: leftSide,
|
||||
presentedViewController: presentedViewController,
|
||||
presentingViewController: presentingViewController,
|
||||
containerView: transitionContext.containerView
|
||||
)
|
||||
}
|
||||
|
||||
transition(using: transitionContext)
|
||||
}
|
||||
|
||||
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||
guard let transitionContext = transitionContext else { return 0 }
|
||||
return duration(presenting: transitionContext.isPresenting, interactive: transitionContext.isInteractive)
|
||||
}
|
||||
|
||||
func animationEnded(_ transitionCompleted: Bool) {
|
||||
guard let presentedViewController = presentedViewController else { return }
|
||||
if presentedViewController.isHidden {
|
||||
delegate?.sideMenuAnimationController(self, didDismiss: presentedViewController)
|
||||
} else {
|
||||
delegate?.sideMenuAnimationController(self, didPresent: presentedViewController)
|
||||
}
|
||||
}
|
||||
|
||||
func transition(presenting: Bool, animated: Bool = true, interactive: Bool = false, alongsideTransition: (() -> Void)? = nil, complete: Bool = true, completion: ((Bool) -> Void)? = nil) {
|
||||
prepare(presenting: presenting)
|
||||
transitionWillBegin(presenting: presenting)
|
||||
transition(
|
||||
presenting: presenting,
|
||||
animated: animated,
|
||||
interactive: interactive,
|
||||
animations: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.transition(presenting: presenting)
|
||||
alongsideTransition?()
|
||||
}, completion: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
if complete {
|
||||
self.transitionDidEnd(presenting: presenting, completed: true)
|
||||
self.finish(presenting: presenting, completed: true)
|
||||
}
|
||||
completion?(true)
|
||||
})
|
||||
}
|
||||
|
||||
func layout() {
|
||||
presentationController?.containerViewWillLayoutSubviews()
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuAnimationController {
|
||||
|
||||
func duration(presenting: Bool, interactive: Bool) -> Double {
|
||||
if interactive { return config.completeGestureDuration }
|
||||
return presenting ? config.presentDuration : config.dismissDuration
|
||||
}
|
||||
|
||||
func prepare(presenting: Bool) {
|
||||
guard
|
||||
presenting,
|
||||
let presentingViewController = presentingViewController,
|
||||
let presentedViewController = presentedViewController
|
||||
else { return }
|
||||
|
||||
originalSuperview = presentingViewController.view.superview
|
||||
containerView?.addSubview(presentingViewController.view)
|
||||
containerView?.addSubview(presentedViewController.view)
|
||||
}
|
||||
|
||||
func transitionWillBegin(presenting: Bool) {
|
||||
// prevent any other menu gestures from firing
|
||||
containerView?.isUserInteractionEnabled = false
|
||||
if presenting {
|
||||
presentationController?.presentationTransitionWillBegin()
|
||||
} else {
|
||||
presentationController?.dismissalTransitionWillBegin()
|
||||
}
|
||||
}
|
||||
|
||||
func transition(presenting: Bool) {
|
||||
if presenting {
|
||||
presentationController?.presentationTransition()
|
||||
} else {
|
||||
presentationController?.dismissalTransition()
|
||||
}
|
||||
}
|
||||
|
||||
func transitionDidEnd(presenting: Bool, completed: Bool) {
|
||||
if presenting {
|
||||
presentationController?.presentationTransitionDidEnd(completed)
|
||||
} else {
|
||||
presentationController?.dismissalTransitionDidEnd(completed)
|
||||
}
|
||||
containerView?.isUserInteractionEnabled = true
|
||||
}
|
||||
|
||||
func finish(presenting: Bool, completed: Bool) {
|
||||
guard
|
||||
presenting != completed,
|
||||
let presentingViewController = self.presentingViewController
|
||||
else { return }
|
||||
presentedViewController?.view.removeFromSuperview()
|
||||
originalSuperview?.addSubview(presentingViewController.view)
|
||||
}
|
||||
|
||||
func transition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
prepare(presenting: transitionContext.isPresenting)
|
||||
transitionWillBegin(presenting: transitionContext.isPresenting)
|
||||
transition(
|
||||
presenting: transitionContext.isPresenting,
|
||||
animated: transitionContext.isAnimated,
|
||||
interactive: transitionContext.isInteractive,
|
||||
animations: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.transition(presenting: transitionContext.isPresenting)
|
||||
}, completion: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
let completed = !transitionContext.transitionWasCancelled
|
||||
self.transitionDidEnd(presenting: transitionContext.isPresenting, completed: completed)
|
||||
self.finish(presenting: transitionContext.isPresenting, completed: completed)
|
||||
|
||||
// Called last. This causes the transition container to be removed and animationEnded() to be called.
|
||||
transitionContext.completeTransition(completed)
|
||||
})
|
||||
}
|
||||
|
||||
func transition(presenting: Bool, animated: Bool = true, interactive: Bool = false, animations: @escaping (() -> Void) = {}, completion: @escaping ((Bool) -> Void) = { _ in }) {
|
||||
if !animated {
|
||||
animations()
|
||||
completion(true)
|
||||
return
|
||||
}
|
||||
|
||||
let duration = self.duration(presenting: presenting, interactive: interactive)
|
||||
if interactive {
|
||||
// IMPORTANT: The non-interactive animation block will not complete if adapted for interactive. The below animation block must be used!
|
||||
UIView.animate(
|
||||
withDuration: duration,
|
||||
delay: duration, // HACK: If zero, the animation briefly flashes in iOS 11.
|
||||
options: .curveLinear,
|
||||
animations: animations,
|
||||
completion: completion
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
UIView.animate(
|
||||
withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: config.usingSpringWithDamping,
|
||||
initialSpringVelocity: config.initialSpringVelocity,
|
||||
options: config.animationOptions,
|
||||
animations: animations,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension UIViewControllerContextTransitioning {
|
||||
|
||||
var isPresenting: Bool {
|
||||
return viewController(forKey: .from)?.presentedViewController === viewController(forKey: .to)
|
||||
}
|
||||
|
||||
var presentingViewController: UIViewController? {
|
||||
return viewController(forKey: isPresenting ? .from : .to)
|
||||
}
|
||||
|
||||
var presentedViewController: UIViewController? {
|
||||
return viewController(forKey: isPresenting ? .to : .from)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// SideMenuInteractiveTransitionController.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 12/28/18.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
internal final class SideMenuInteractionController: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
enum State { case
|
||||
update(progress: CGFloat),
|
||||
finish,
|
||||
cancel
|
||||
}
|
||||
|
||||
private(set) var isCancelled: Bool = false
|
||||
private(set) var isFinished: Bool = false
|
||||
|
||||
init(cancelWhenBackgrounded: Bool = true, completionCurve: UIView.AnimationCurve = .easeIn) {
|
||||
super.init()
|
||||
self.completionCurve = completionCurve
|
||||
|
||||
guard cancelWhenBackgrounded else { return }
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
||||
}
|
||||
|
||||
override func cancel() {
|
||||
isCancelled = true
|
||||
super.cancel()
|
||||
}
|
||||
|
||||
override func finish() {
|
||||
isFinished = true
|
||||
super.finish()
|
||||
}
|
||||
|
||||
override func update(_ percentComplete: CGFloat) {
|
||||
guard !isCancelled && !isFinished else { return }
|
||||
super.update(percentComplete)
|
||||
}
|
||||
|
||||
func handle(state: State) {
|
||||
switch state {
|
||||
case .update(let progress):
|
||||
update(progress)
|
||||
case .finish:
|
||||
finish()
|
||||
case .cancel:
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuInteractionController {
|
||||
|
||||
@objc func handleNotification(notification: NSNotification) {
|
||||
switch notification.name {
|
||||
case UIApplication.didEnterBackgroundNotification:
|
||||
cancel()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
+179
-624
@@ -5,369 +5,101 @@
|
||||
// Copyright © 2015 Jon Kent. All rights reserved.
|
||||
//
|
||||
|
||||
/* Example usage:
|
||||
// Define the menus
|
||||
SideMenuManager.menuLeftNavigationController = storyboard!.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as? UISideMenuNavigationController
|
||||
SideMenuManager.menuRightNavigationController = storyboard!.instantiateViewController(withIdentifier: "RightMenuNavigationController") as? UISideMenuNavigationController
|
||||
|
||||
// Enable gestures. The left and/or right menus must be set up above for these to work.
|
||||
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
|
||||
SideMenuManager.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
*/
|
||||
import UIKit
|
||||
|
||||
open class SideMenuManager : NSObject {
|
||||
|
||||
@objc public enum MenuPushStyle : Int {
|
||||
case defaultBehavior,
|
||||
popWhenPossible,
|
||||
replace,
|
||||
preserve,
|
||||
preserveAndHideBackButton,
|
||||
subMenu
|
||||
}
|
||||
|
||||
@objc public enum MenuPresentMode : Int {
|
||||
case menuSlideIn,
|
||||
viewSlideOut,
|
||||
viewSlideInOut,
|
||||
menuDissolveIn
|
||||
}
|
||||
|
||||
// Bounds which has been allocated for the app on the whole device screen
|
||||
internal static var appScreenRect: CGRect {
|
||||
let appWindowRect = UIApplication.shared.keyWindow?.bounds ?? UIWindow().bounds
|
||||
return appWindowRect
|
||||
@objcMembers
|
||||
public class SideMenuManager: NSObject {
|
||||
|
||||
final private class SideMenuPanGestureRecognizer: UIPanGestureRecognizer {}
|
||||
final private class SideMenuScreenEdgeGestureRecognizer: UIScreenEdgePanGestureRecognizer {}
|
||||
|
||||
@objc public enum PresentDirection: Int { case
|
||||
left = 1,
|
||||
right = 0
|
||||
|
||||
init(leftSide: Bool) {
|
||||
self.init(rawValue: leftSide ? 1 : 0)!
|
||||
}
|
||||
|
||||
var edge: UIRectEdge {
|
||||
switch self {
|
||||
case .left: return .left
|
||||
case .right: return .right
|
||||
}
|
||||
}
|
||||
|
||||
var name: String {
|
||||
switch self {
|
||||
case .left: return "leftMenuNavigationController"
|
||||
case .right: return "rightMenuNavigationController"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved..
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
open var menuPushStyle: MenuPushStyle = .defaultBehavior
|
||||
private var _leftMenu: Protected<Menu?> = Protected(nil) { SideMenuManager.setMenu(fromMenu: $0, toMenu: $1) }
|
||||
private var _rightMenu: Protected<Menu?> = Protected(nil) { SideMenuManager.setMenu(fromMenu: $0, toMenu: $1) }
|
||||
|
||||
/**
|
||||
The presentation mode of the menu.
|
||||
|
||||
There are four modes in MenuPresentMode:
|
||||
- menuSlideIn: Menu slides in over of the existing view.
|
||||
- viewSlideOut: The existing view slides out to reveal the menu.
|
||||
- viewSlideInOut: The existing view slides out while the menu slides in.
|
||||
- menuDissolveIn: The menu dissolves in over the existing view controller.
|
||||
*/
|
||||
open var menuPresentMode: MenuPresentMode = .viewSlideOut
|
||||
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
open var menuAllowPushOfSameClassTwice = true
|
||||
private var switching: Bool = false
|
||||
|
||||
/**
|
||||
Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width or 240 points, whichever is smaller.
|
||||
|
||||
Note that each menu's width can be overridden using the `menuWidth` property on any `UISideMenuNavigationController` instance.
|
||||
*/
|
||||
open var menuWidth: CGFloat = min(round(min((appScreenRect.width), (appScreenRect.height)) * 0.75), 240)
|
||||
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationPresentDuration: Double = 0.35
|
||||
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationDismissDuration: Double = 0.35
|
||||
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationCompleteGestureDuration: Double = 0.35
|
||||
|
||||
/// Amount to fade the existing view controller when the menu is presented. Default is 0 for no fade. Set to 1 to fade completely.
|
||||
open var menuAnimationFadeStrength: CGFloat = 0
|
||||
|
||||
/// The amount to scale the existing view controller or the menu view controller depending on the `menuPresentMode`. Default is 1 for no scaling. Less than 1 will shrink, greater than 1 will grow.
|
||||
open var menuAnimationTransformScaleFactor: CGFloat = 1
|
||||
|
||||
/// The background color behind menu animations. Depending on the animation settings this may not be visible. If `menuFadeStatusBar` is true, this color is used to fade it. Default is black.
|
||||
open var menuAnimationBackgroundColor: UIColor?
|
||||
|
||||
/// The shadow opacity around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 0.5 for 50% opacity.
|
||||
open var menuShadowOpacity: Float = 0.5
|
||||
|
||||
/// The shadow color around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is black.
|
||||
open var menuShadowColor = UIColor.black
|
||||
|
||||
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
|
||||
open var menuShadowRadius: CGFloat = 5
|
||||
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. Default is false.
|
||||
open var menuPresentingViewControllerUserInteractionEnabled: Bool = false
|
||||
|
||||
/// The strength of the parallax effect on the existing view controller. Does not apply to `menuPresentMode` when set to `ViewSlideOut`. Default is 0.
|
||||
open var menuParallaxStrength: Int = 0
|
||||
|
||||
/// Draws the `menuAnimationBackgroundColor` behind the status bar. Default is true.
|
||||
open var menuFadeStatusBar = true
|
||||
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationOptions: UIViewAnimationOptions = .curveEaseInOut
|
||||
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationUsingSpringWithDamping: CGFloat = 1
|
||||
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open var menuDismissOnPush = true
|
||||
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
open var menuAlwaysAnimate = false
|
||||
|
||||
/// Default instance of SideMenuManager.
|
||||
open static let `default` = SideMenuManager()
|
||||
internal var transition: SideMenuTransition!
|
||||
|
||||
public override init() {
|
||||
super.init()
|
||||
transition = SideMenuTransition(sideMenuManager: self)
|
||||
public static let `default` = SideMenuManager()
|
||||
|
||||
/// Default instance of SideMenuManager (objective-C).
|
||||
public class var defaultManager: SideMenuManager {
|
||||
return SideMenuManager.default
|
||||
}
|
||||
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell.
|
||||
*/
|
||||
open var menuBlurEffectStyle: UIBlurEffectStyle? {
|
||||
didSet {
|
||||
if oldValue != menuBlurEffectStyle {
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The left menu.
|
||||
open var menuLeftNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
guard menuLeftNavigationController != newValue, menuLeftNavigationController?.presentingViewController == nil else {
|
||||
return
|
||||
open var leftMenuNavigationController: SideMenuNavigationController? {
|
||||
get {
|
||||
if _leftMenu.value?.isHidden == true {
|
||||
_leftMenu.value?.leftSide = true
|
||||
}
|
||||
menuLeftNavigationController?.locked = false
|
||||
removeMenuBlurForMenu(menuLeftNavigationController)
|
||||
}
|
||||
didSet {
|
||||
guard menuLeftNavigationController != oldValue else {
|
||||
return
|
||||
}
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuLeftNavigationController cannot be modified while it's presented.")
|
||||
menuLeftNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
|
||||
setupNavigationController(menuLeftNavigationController, leftSide: true)
|
||||
return _leftMenu.value
|
||||
}
|
||||
set(menu) { _leftMenu.value = menu }
|
||||
}
|
||||
|
||||
/// The right menu.
|
||||
open var menuRightNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
guard menuRightNavigationController != newValue, menuRightNavigationController?.presentingViewController == nil else {
|
||||
return
|
||||
open var rightMenuNavigationController: SideMenuNavigationController? {
|
||||
get {
|
||||
if _rightMenu.value?.isHidden == true {
|
||||
_rightMenu.value?.leftSide = false
|
||||
}
|
||||
removeMenuBlurForMenu(menuRightNavigationController)
|
||||
}
|
||||
didSet {
|
||||
guard menuRightNavigationController != oldValue else {
|
||||
return
|
||||
}
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuRightNavigationController cannot be modified while it's presented.")
|
||||
menuRightNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
setupNavigationController(menuRightNavigationController, leftSide: false)
|
||||
return _rightMenu.value
|
||||
}
|
||||
set(menu) { _rightMenu.value = menu }
|
||||
}
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuLeftSwipeToDismissGesture)
|
||||
}
|
||||
|
||||
/**
|
||||
Adds screen edge gestures for both left and right sides to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add gestures to.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult public func addScreenEdgePanGesturesToPresent(toView view: UIView) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
return [
|
||||
addScreenEdgePanGesturesToPresent(toView: view, forMenu: .left),
|
||||
addScreenEdgePanGesturesToPresent(toView: view, forMenu: .right)
|
||||
]
|
||||
}
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuRightSwipeToDismissGesture)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setupGesture(gesture: UIPanGestureRecognizer?) {
|
||||
guard let gesture = gesture else {
|
||||
return
|
||||
}
|
||||
|
||||
gesture.addTarget(transition, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
}
|
||||
|
||||
fileprivate func setupNavigationController(_ forMenu: UISideMenuNavigationController?, leftSide: Bool) {
|
||||
guard let forMenu = forMenu else {
|
||||
return
|
||||
}
|
||||
|
||||
forMenu.transitioningDelegate = transition
|
||||
forMenu.modalPresentationStyle = .overFullScreen
|
||||
forMenu.leftSide = leftSide
|
||||
|
||||
if forMenu.sideMenuManager != self {
|
||||
#if !STFU_SIDEMENU
|
||||
if forMenu.sideMenuManager?.menuLeftNavigationController == forMenu {
|
||||
print("SideMenu Warning: \(String(describing: forMenu.self)) was already assigned to the menuLeftNavigationController of \(String(describing: forMenu.sideMenuManager!.self)). When using multiple SideMenuManagers you may want to use new instances of UISideMenuNavigationController instead of existing instances to avoid crashes if the menu is presented more than once.")
|
||||
} else if forMenu.sideMenuManager?.menuRightNavigationController == forMenu {
|
||||
print("SideMenu Warning: \(String(describing: forMenu.self)) was already assigned to the menuRightNavigationController of \(String(describing: forMenu.sideMenuManager!.self)). When using multiple SideMenuManagers you may want to use new instances of UISideMenuNavigationController instead of existing instances to avoid crashes if the menu is presented more than once.")
|
||||
}
|
||||
#endif
|
||||
forMenu.sideMenuManager = self
|
||||
}
|
||||
|
||||
forMenu.locked = true
|
||||
|
||||
if menuEnableSwipeGestures {
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
forMenu.view.addGestureRecognizer(exitPanGesture)
|
||||
if leftSide {
|
||||
menuLeftSwipeToDismissGesture = exitPanGesture
|
||||
} else {
|
||||
menuRightSwipeToDismissGesture = exitPanGesture
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures minimal lag when revealing the menu for the first time using gestures by loading the view:
|
||||
let _ = forMenu.topViewController?.view
|
||||
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
|
||||
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
|
||||
open var menuEnableSwipeGestures: Bool = true {
|
||||
didSet {
|
||||
menuLeftSwipeToDismissGesture?.view?.removeGestureRecognizer(menuLeftSwipeToDismissGesture!)
|
||||
menuRightSwipeToDismissGesture?.view?.removeGestureRecognizer(menuRightSwipeToDismissGesture!)
|
||||
setupNavigationController(menuLeftNavigationController, leftSide: true)
|
||||
setupNavigationController(menuRightNavigationController, leftSide: false)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func updateMenuBlurIfNecessary() {
|
||||
if let menuLeftNavigationController = self.menuLeftNavigationController {
|
||||
setupMenuBlurForMenu(menuLeftNavigationController)
|
||||
}
|
||||
if let menuRightNavigationController = self.menuRightNavigationController {
|
||||
setupMenuBlurForMenu(menuRightNavigationController)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setupMenuBlurForMenu(_ forMenu: UISideMenuNavigationController?) {
|
||||
removeMenuBlurForMenu(forMenu)
|
||||
|
||||
guard let forMenu = forMenu,
|
||||
let menuBlurEffectStyle = menuBlurEffectStyle,
|
||||
let view = forMenu.topViewController?.view,
|
||||
!UIAccessibilityIsReduceTransparencyEnabled() else {
|
||||
return
|
||||
}
|
||||
|
||||
if forMenu.originalMenuBackgroundColor == nil {
|
||||
forMenu.originalMenuBackgroundColor = view.backgroundColor
|
||||
}
|
||||
|
||||
let blurEffect = UIBlurEffect(style: menuBlurEffectStyle)
|
||||
let blurView = UIVisualEffectView(effect: blurEffect)
|
||||
view.backgroundColor = UIColor.clear
|
||||
if let tableViewController = forMenu.topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = blurView
|
||||
tableViewController.tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||
tableViewController.tableView.reloadData()
|
||||
} else {
|
||||
blurView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
blurView.frame = view.bounds
|
||||
view.insertSubview(blurView, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func removeMenuBlurForMenu(_ forMenu: UISideMenuNavigationController?) {
|
||||
guard let forMenu = forMenu,
|
||||
let originalMenuBackgroundColor = forMenu.originalMenuBackgroundColor,
|
||||
let view = forMenu.topViewController?.view else {
|
||||
return
|
||||
}
|
||||
|
||||
view.backgroundColor = originalMenuBackgroundColor
|
||||
forMenu.originalMenuBackgroundColor = nil
|
||||
|
||||
if let tableViewController = forMenu.topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = nil
|
||||
tableViewController.tableView.separatorEffect = nil
|
||||
tableViewController.tableView.reloadData()
|
||||
} else if let blurView = view.subviews[0] as? UIVisualEffectView {
|
||||
blurView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Adds screen edge gestures to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add gestures to.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for. If unspecified, gestures will be added for both sides.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
- Returns: The screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
var array = [UIScreenEdgePanGestureRecognizer]()
|
||||
|
||||
let newScreenEdgeGesture = { () -> UIScreenEdgePanGestureRecognizer in
|
||||
let screenEdgeGestureRecognizer = UIScreenEdgePanGestureRecognizer()
|
||||
screenEdgeGestureRecognizer.cancelsTouchesInView = true
|
||||
toView.addGestureRecognizer(screenEdgeGestureRecognizer)
|
||||
array.append(screenEdgeGestureRecognizer)
|
||||
return screenEdgeGestureRecognizer
|
||||
@discardableResult public func addScreenEdgePanGesturesToPresent(toView view: UIView, forMenu side: PresentDirection) -> UIScreenEdgePanGestureRecognizer {
|
||||
if menu(forSide: side) == nil {
|
||||
let methodName = #function // "addScreenEdgePanGesturesToPresent"
|
||||
let suggestedMethodName = "addScreenEdgePanGesturesToPresent(toView:forMenu:))"
|
||||
Print.warning(.screenGestureAdded, arguments: methodName, side.name, suggestedMethodName)
|
||||
}
|
||||
|
||||
if forMenu != .right {
|
||||
let leftScreenEdgeGestureRecognizer = newScreenEdgeGesture()
|
||||
leftScreenEdgeGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuLeftScreenEdge(_:)))
|
||||
leftScreenEdgeGestureRecognizer.edges = .left
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if menuLeftNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuLeftNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if forMenu != .left {
|
||||
let rightScreenEdgeGestureRecognizer = newScreenEdgeGesture()
|
||||
rightScreenEdgeGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuRightScreenEdge(_:)))
|
||||
rightScreenEdgeGestureRecognizer.edges = .right
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if menuRightNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddScreenEdgePanGesturesToPresent was called before menuRightNavigationController was set. The gesture will not work without a menu. Use menuAddScreenEdgePanGesturesToPresent(toView:forMenu:) to add gestures for only one menu.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return array
|
||||
return self.addScreenEdgeGesture(to: view, edge: side.edge)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,298 +109,121 @@ open class SideMenuManager : NSObject {
|
||||
|
||||
- Returns: The pan gesture added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer {
|
||||
let panGestureRecognizer = UIPanGestureRecognizer()
|
||||
panGestureRecognizer.addTarget(transition, action:#selector(SideMenuTransition.handlePresentMenuPan(_:)))
|
||||
toView.addGestureRecognizer(panGestureRecognizer)
|
||||
|
||||
if menuLeftNavigationController ?? menuRightNavigationController == nil {
|
||||
print("SideMenu Warning: menuAddPanGestureToPresent called before menuLeftNavigationController or menuRightNavigationController have been defined. Gestures will not work without a menu.")
|
||||
@discardableResult public func addPanGestureToPresent(toView view: UIView) -> UIPanGestureRecognizer {
|
||||
if leftMenuNavigationController ?? rightMenuNavigationController == nil {
|
||||
Print.warning(.panGestureAdded, arguments: #function, PresentDirection.left.name, PresentDirection.right.name, required: true)
|
||||
}
|
||||
|
||||
return panGestureRecognizer
|
||||
return addPresentPanGesture(to: view)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecations, to be removed at a future date.
|
||||
extension SideMenuManager {
|
||||
|
||||
@available(*, deprecated, renamed: "default.menuPushStyle", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPushStyle: MenuPushStyle {
|
||||
get {
|
||||
return `default`.menuPushStyle
|
||||
}
|
||||
set {
|
||||
`default`.menuPushStyle = newValue
|
||||
internal extension SideMenuManager {
|
||||
|
||||
func setMenu(_ menu: Menu?, forLeftSide leftSide: Bool) {
|
||||
switch leftSide {
|
||||
case true: leftMenuNavigationController = menu
|
||||
case false: rightMenuNavigationController = menu
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuPresentMode", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPresentMode: MenuPresentMode {
|
||||
get {
|
||||
return `default`.menuPresentMode
|
||||
|
||||
private class func setMenu(fromMenu: Menu?, toMenu: Menu?) -> Menu? {
|
||||
if fromMenu?.isHidden == false {
|
||||
Print.warning(.menuInUse, arguments: PresentDirection.left.name, required: true)
|
||||
return fromMenu
|
||||
}
|
||||
set {
|
||||
`default`.menuPresentMode = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAllowPushOfSameClassTwice", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAllowPushOfSameClassTwice: Bool {
|
||||
get {
|
||||
return `default`.menuAllowPushOfSameClassTwice
|
||||
}
|
||||
set {
|
||||
`default`.menuAllowPushOfSameClassTwice = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuWidth", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuWidth: CGFloat {
|
||||
get {
|
||||
return `default`.menuWidth
|
||||
}
|
||||
set {
|
||||
`default`.menuWidth = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationPresentDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationPresentDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationPresentDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationPresentDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationDismissDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationDismissDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationDismissDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationDismissDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationCompleteGestureDuration", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationCompleteGestureDuration: Double {
|
||||
get {
|
||||
return `default`.menuAnimationCompleteGestureDuration
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationCompleteGestureDuration = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationFadeStrength", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationFadeStrength: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationFadeStrength
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationFadeStrength = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationTransformScaleFactor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationTransformScaleFactor: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationTransformScaleFactor
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationTransformScaleFactor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationBackgroundColor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationBackgroundColor: UIColor? {
|
||||
get {
|
||||
return `default`.menuAnimationBackgroundColor
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationBackgroundColor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowOpacity", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowOpacity: Float {
|
||||
get {
|
||||
return `default`.menuShadowOpacity
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowOpacity = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowColor", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowColor: UIColor {
|
||||
get {
|
||||
return `default`.menuShadowColor
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowColor = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuShadowRadius", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuShadowRadius: CGFloat {
|
||||
get {
|
||||
return `default`.menuShadowRadius
|
||||
}
|
||||
set {
|
||||
`default`.menuShadowRadius = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuPresentingViewControllerUserInteractionEnabled", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuPresentingViewControllerUserInteractionEnabled: Bool {
|
||||
get {
|
||||
return `default`.menuPresentingViewControllerUserInteractionEnabled
|
||||
}
|
||||
set {
|
||||
`default`.menuPresentingViewControllerUserInteractionEnabled = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuParallaxStrength", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuParallaxStrength: Int {
|
||||
get {
|
||||
return `default`.menuParallaxStrength
|
||||
}
|
||||
set {
|
||||
`default`.menuParallaxStrength = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuFadeStatusBar", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuFadeStatusBar: Bool {
|
||||
get {
|
||||
return `default`.menuFadeStatusBar
|
||||
}
|
||||
set {
|
||||
`default`.menuFadeStatusBar = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationOptions", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationOptions: UIViewAnimationOptions {
|
||||
get {
|
||||
return `default`.menuAnimationOptions
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationOptions = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationUsingSpringWithDamping", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationUsingSpringWithDamping: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationUsingSpringWithDamping
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationUsingSpringWithDamping = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAnimationInitialSpringVelocity", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuAnimationInitialSpringVelocity: CGFloat {
|
||||
get {
|
||||
return `default`.menuAnimationInitialSpringVelocity
|
||||
}
|
||||
set {
|
||||
`default`.menuAnimationInitialSpringVelocity = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuDismissOnPush", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuDismissOnPush: Bool {
|
||||
get {
|
||||
return `default`.menuDismissOnPush
|
||||
}
|
||||
set {
|
||||
`default`.menuDismissOnPush = newValue
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .subMenu` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .subMenu` instead.")
|
||||
open static var menuAllowSubmenus: Bool {
|
||||
get {
|
||||
return menuPushStyle == .subMenu
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .subMenu
|
||||
}
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .popWhenPossible` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .popWhenPossible` instead.")
|
||||
open static var menuAllowPopIfPossible: Bool {
|
||||
get {
|
||||
return menuPushStyle == .popWhenPossible
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .popWhenPossible
|
||||
}
|
||||
}
|
||||
}
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .replace` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .replace` instead.")
|
||||
open static var menuReplaceOnPush: Bool {
|
||||
get {
|
||||
return menuPushStyle == .replace
|
||||
}
|
||||
set {
|
||||
if newValue {
|
||||
menuPushStyle = .replace
|
||||
}
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuBlurEffectStyle", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuBlurEffectStyle: UIBlurEffectStyle? {
|
||||
get {
|
||||
return `default`.menuBlurEffectStyle
|
||||
}
|
||||
set {
|
||||
`default`.menuBlurEffectStyle = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuLeftNavigationController", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuLeftNavigationController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return `default`.menuLeftNavigationController
|
||||
}
|
||||
set {
|
||||
`default`.menuLeftNavigationController = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuRightNavigationController", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuRightNavigationController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return `default`.menuRightNavigationController
|
||||
}
|
||||
set {
|
||||
`default`.menuRightNavigationController = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuLeftSwipeToDismissGesture", message: "SideMenuManager class methods deprecated.")
|
||||
open static weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get {
|
||||
return `default`.menuLeftSwipeToDismissGesture
|
||||
}
|
||||
set {
|
||||
`default`.menuLeftSwipeToDismissGesture = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuRightSwipeToDismissGesture", message: "SideMenuManager class methods deprecated.")
|
||||
open static weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
get {
|
||||
return `default`.menuRightSwipeToDismissGesture
|
||||
}
|
||||
set {
|
||||
`default`.menuRightSwipeToDismissGesture = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuEnableSwipeGestures", message: "SideMenuManager class methods deprecated.")
|
||||
open static var menuEnableSwipeGestures: Bool {
|
||||
get {
|
||||
return `default`.menuEnableSwipeGestures
|
||||
}
|
||||
set {
|
||||
`default`.menuEnableSwipeGestures = newValue
|
||||
}
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAddScreenEdgePanGesturesToPresent", message: "SideMenuManager class methods deprecated.")
|
||||
@discardableResult open class func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
return `default`.menuAddScreenEdgePanGesturesToPresent(toView: toView, forMenu: forMenu)
|
||||
}
|
||||
@available(*, deprecated, renamed: "default.menuAddPanGestureToPresent", message: "SideMenuManager class methods deprecated.")
|
||||
@discardableResult open class func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer {
|
||||
return `default`.menuAddPanGestureToPresent(toView: toView)
|
||||
return toMenu
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuManager {
|
||||
|
||||
@objc func handlePresentMenuScreenEdge(_ gesture: UIScreenEdgePanGestureRecognizer) {
|
||||
handleMenuPan(gesture)
|
||||
}
|
||||
|
||||
@objc func handlePresentMenuPan(_ gesture: UIPanGestureRecognizer) {
|
||||
handleMenuPan(gesture)
|
||||
}
|
||||
|
||||
func handleMenuPan(_ gesture: UIPanGestureRecognizer) {
|
||||
if let activeMenu = activeMenu {
|
||||
let width = activeMenu.menuWidth
|
||||
let distance = gesture.xTranslation / width
|
||||
switch (gesture.state) {
|
||||
case .changed:
|
||||
if gesture.canSwitch {
|
||||
switching = (distance > 0 && !activeMenu.leftSide) || (distance < 0 && activeMenu.leftSide)
|
||||
if switching {
|
||||
activeMenu.cancelMenuPan(gesture)
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
switching = false
|
||||
}
|
||||
|
||||
} else {
|
||||
let leftSide: Bool
|
||||
if let gesture = gesture as? UIScreenEdgePanGestureRecognizer {
|
||||
leftSide = gesture.edges.contains(.left)
|
||||
} else {
|
||||
// not sure which way the user is swiping yet, so do nothing
|
||||
if gesture.xTranslation == 0 { return }
|
||||
leftSide = gesture.xTranslation > 0
|
||||
}
|
||||
|
||||
guard let menu = menu(forLeftSide: leftSide) else { return }
|
||||
menu.present(from: topMostViewController, interactively: true)
|
||||
}
|
||||
|
||||
activeMenu?.handleMenuPan(gesture, true)
|
||||
}
|
||||
|
||||
var activeMenu: Menu? {
|
||||
if leftMenuNavigationController?.isHidden == false { return leftMenuNavigationController }
|
||||
if rightMenuNavigationController?.isHidden == false { return rightMenuNavigationController }
|
||||
return nil
|
||||
}
|
||||
|
||||
func menu(forSide: PresentDirection) -> Menu? {
|
||||
switch forSide {
|
||||
case .left: return leftMenuNavigationController
|
||||
case .right: return rightMenuNavigationController
|
||||
}
|
||||
}
|
||||
|
||||
func menu(forLeftSide leftSide: Bool) -> Menu? {
|
||||
return menu(forSide: leftSide ? .left : .right)
|
||||
}
|
||||
|
||||
func addScreenEdgeGesture(to view: UIView, edge: UIRectEdge) -> UIScreenEdgePanGestureRecognizer {
|
||||
if let screenEdgeGestureRecognizer = view.gestureRecognizers?.first(where: { $0 is SideMenuScreenEdgeGestureRecognizer }) as? SideMenuScreenEdgeGestureRecognizer,
|
||||
screenEdgeGestureRecognizer.edges == edge {
|
||||
screenEdgeGestureRecognizer.remove()
|
||||
}
|
||||
return SideMenuScreenEdgeGestureRecognizer(addTo: view, target: self, action: #selector(handlePresentMenuScreenEdge(_:))).with {
|
||||
$0.edges = edge
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func addPresentPanGesture(to view: UIView) -> UIPanGestureRecognizer {
|
||||
if let panGestureRecognizer = view.gestureRecognizers?.first(where: { $0 is SideMenuPanGestureRecognizer }) as? SideMenuPanGestureRecognizer {
|
||||
return panGestureRecognizer
|
||||
}
|
||||
return SideMenuPanGestureRecognizer(addTo: view, target: self, action: #selector(handlePresentMenuPan(_:)))
|
||||
}
|
||||
|
||||
var topMostViewController: UIViewController? {
|
||||
return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController
|
||||
}
|
||||
}
|
||||
|
||||
extension SideMenuManager: SideMenuNavigationControllerTransitionDelegate {
|
||||
|
||||
internal func sideMenuTransitionDidDismiss(menu: Menu) {
|
||||
defer { switching = false }
|
||||
guard switching, let switchToMenu = self.menu(forLeftSide: !menu.leftSide) else { return }
|
||||
switchToMenu.present(from: topMostViewController, interactively: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,656 @@
|
||||
//
|
||||
// SideMenuNavigationController.swift
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
// Copyright © 2016 Jon Kent. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc public enum SideMenuPushStyle: Int { case
|
||||
`default`,
|
||||
popWhenPossible,
|
||||
preserve,
|
||||
preserveAndHideBackButton,
|
||||
replace,
|
||||
subMenu
|
||||
|
||||
internal var hidesBackButton: Bool {
|
||||
switch self {
|
||||
case .preserveAndHideBackButton, .replace: return true
|
||||
case .default, .popWhenPossible, .preserve, .subMenu: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal protocol MenuModel {
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
var allowPushOfSameClassTwice: Bool { get }
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
var alwaysAnimate: Bool { get }
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell.
|
||||
*/
|
||||
var blurEffectStyle: UIBlurEffect.Style? { get }
|
||||
/// Animation curve of the remaining animation when the menu is partially dismissed with gestures. Default is .easeIn.
|
||||
var completionCurve: UIView.AnimationCurve { get }
|
||||
/// Automatically dismisses the menu when another view is presented from it.
|
||||
var dismissOnPresent: Bool { get }
|
||||
/// Automatically dismisses the menu when another view controller is pushed from it.
|
||||
var dismissOnPush: Bool { get }
|
||||
/// Automatically dismisses the menu when the screen is rotated.
|
||||
var dismissOnRotation: Bool { get }
|
||||
/// Automatically dismisses the menu when app goes to the background.
|
||||
var dismissWhenBackgrounded: Bool { get }
|
||||
/// Enable or disable a swipe gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
|
||||
var enableSwipeToDismissGesture: Bool { get }
|
||||
/// Enable or disable a tap gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
|
||||
var enableTapToDismissGesture: Bool { get }
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved..
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
var pushStyle: SideMenuPushStyle { get }
|
||||
}
|
||||
|
||||
@objc public protocol SideMenuNavigationControllerDelegate {
|
||||
@objc optional func sideMenuWillAppear(menu: SideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuDidAppear(menu: SideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuWillDisappear(menu: SideMenuNavigationController, animated: Bool)
|
||||
@objc optional func sideMenuDidDisappear(menu: SideMenuNavigationController, animated: Bool)
|
||||
}
|
||||
|
||||
internal protocol SideMenuNavigationControllerTransitionDelegate: class {
|
||||
func sideMenuTransitionDidDismiss(menu: Menu)
|
||||
}
|
||||
|
||||
public struct SideMenuSettings: Model, InitializableStruct {
|
||||
public var allowPushOfSameClassTwice: Bool = true
|
||||
public var alwaysAnimate: Bool = true
|
||||
public var animationOptions: UIView.AnimationOptions = .curveEaseInOut
|
||||
public var blurEffectStyle: UIBlurEffect.Style? = nil
|
||||
public var completeGestureDuration: Double = 0.35
|
||||
public var completionCurve: UIView.AnimationCurve = .easeIn
|
||||
public var dismissDuration: Double = 0.35
|
||||
public var dismissOnPresent: Bool = true
|
||||
public var dismissOnPush: Bool = true
|
||||
public var dismissOnRotation: Bool = true
|
||||
public var dismissWhenBackgrounded: Bool = true
|
||||
public var enableSwipeToDismissGesture: Bool = true
|
||||
public var enableTapToDismissGesture: Bool = true
|
||||
public var initialSpringVelocity: CGFloat = 1
|
||||
public var menuWidth: CGFloat = {
|
||||
let appScreenRect = UIApplication.shared.keyWindow?.bounds ?? UIWindow().bounds
|
||||
let minimumSize = min(appScreenRect.width, appScreenRect.height)
|
||||
return min(round(minimumSize * 0.75), 240)
|
||||
}()
|
||||
public var presentingViewControllerUserInteractionEnabled: Bool = false
|
||||
public var presentingViewControllerUseSnapshot: Bool = false
|
||||
public var presentDuration: Double = 0.35
|
||||
public var presentationStyle: SideMenuPresentationStyle = .viewSlideOut
|
||||
public var pushStyle: SideMenuPushStyle = .default
|
||||
public var statusBarEndAlpha: CGFloat = 0
|
||||
public var usingSpringWithDamping: CGFloat = 1
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
internal typealias Menu = SideMenuNavigationController
|
||||
typealias Model = MenuModel & PresentationModel & AnimationModel
|
||||
|
||||
@objcMembers
|
||||
open class SideMenuNavigationController: UINavigationController {
|
||||
|
||||
private lazy var _leftSide = Protected(false) { [weak self] oldValue, newValue in
|
||||
guard self?.isHidden != false else {
|
||||
Print.warning(.property, arguments: .leftSide, required: true)
|
||||
return oldValue
|
||||
}
|
||||
return newValue
|
||||
}
|
||||
|
||||
private weak var _sideMenuManager: SideMenuManager?
|
||||
private weak var foundViewController: UIViewController?
|
||||
private var originalBackgroundColor: UIColor?
|
||||
private var rotating: Bool = false
|
||||
private var transitionController: SideMenuTransitionController?
|
||||
private var transitionInteractive: Bool = false
|
||||
|
||||
/// Delegate for receiving appear and disappear related events. If `nil` the visible view controller that displays a `SideMenuNavigationController` automatically receives these events.
|
||||
public weak var sideMenuDelegate: SideMenuNavigationControllerDelegate?
|
||||
|
||||
/// The swipe to dismiss gesture.
|
||||
open private(set) weak var swipeToDismissGesture: UIPanGestureRecognizer? = nil
|
||||
/// The tap to dismiss gesture.
|
||||
open private(set) weak var tapToDismissGesture: UITapGestureRecognizer? = nil
|
||||
|
||||
open var sideMenuManager: SideMenuManager {
|
||||
get { return _sideMenuManager ?? SideMenuManager.default }
|
||||
set {
|
||||
newValue.setMenu(self, forLeftSide: leftSide)
|
||||
|
||||
if let sideMenuManager = _sideMenuManager, sideMenuManager !== newValue {
|
||||
let side = SideMenuManager.PresentDirection(leftSide: leftSide)
|
||||
Print.warning(.menuAlreadyAssigned, arguments: String(describing: self.self), side.name, String(describing: newValue))
|
||||
}
|
||||
_sideMenuManager = newValue
|
||||
}
|
||||
}
|
||||
|
||||
/// The menu settings.
|
||||
open var settings = SideMenuSettings() {
|
||||
didSet {
|
||||
setupBlur()
|
||||
if !enableSwipeToDismissGesture {
|
||||
swipeToDismissGesture?.remove()
|
||||
}
|
||||
if !enableTapToDismissGesture {
|
||||
tapToDismissGesture?.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
setup()
|
||||
}
|
||||
|
||||
public init(rootViewController: UIViewController, settings: SideMenuSettings = SideMenuSettings()) {
|
||||
self.settings = settings
|
||||
super.init(rootViewController: rootViewController)
|
||||
setup()
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
setup()
|
||||
}
|
||||
|
||||
override open func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
sideMenuManager.setMenu(self, forLeftSide: leftSide)
|
||||
}
|
||||
|
||||
override open func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if topViewController == nil {
|
||||
Print.warning(.emptyMenu)
|
||||
}
|
||||
|
||||
// Dismiss keyboard to prevent weird keyboard animations from occurring during transition
|
||||
presentingViewController?.view.endEditing(true)
|
||||
|
||||
foundViewController = nil
|
||||
activeDelegate?.sideMenuWillAppear?(menu: self, animated: animated)
|
||||
}
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// We had presented a view before, so lets dismiss ourselves as already acted upon
|
||||
if view.isHidden {
|
||||
dismiss(animated: false, completion: { [weak self] in
|
||||
self?.view.isHidden = false
|
||||
})
|
||||
} else {
|
||||
activeDelegate?.sideMenuDidAppear?(menu: self, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
defer { activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated) }
|
||||
|
||||
guard !isBeingDismissed else { return }
|
||||
|
||||
// When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
|
||||
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
|
||||
if let presentingView = presentingViewController?.view, let containerView = presentingView.superview {
|
||||
containerView.addSubview(view)
|
||||
}
|
||||
|
||||
if dismissOnPresent {
|
||||
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
|
||||
transitionController?.transition(presenting: false, animated: animated, alongsideTransition: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
|
||||
}, complete: false, completion: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
self.view.isHidden = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
// Work-around: if the menu is dismissed without animation the transition logic is never called to restore the
|
||||
// the view hierarchy leaving the screen black/empty. This is because the transition moves views within a container
|
||||
// view, but dismissing without animation removes the container view before the original hierarchy is restored.
|
||||
// This check corrects that.
|
||||
if isBeingDismissed {
|
||||
transitionController?.transition(presenting: false, animated: false)
|
||||
}
|
||||
|
||||
// Clear selection on UITableViewControllers when reappearing using custom transitions
|
||||
if let tableViewController = topViewController as? UITableViewController,
|
||||
let tableView = tableViewController.tableView,
|
||||
let indexPaths = tableView.indexPathsForSelectedRows,
|
||||
tableViewController.clearsSelectionOnViewWillAppear {
|
||||
indexPaths.forEach { tableView.deselectRow(at: $0, animated: false) }
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
|
||||
if isBeingDismissed {
|
||||
transitionController = nil
|
||||
} else if dismissOnPresent {
|
||||
view.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
// Don't bother resizing if the view isn't visible
|
||||
guard let transitionController = transitionController, !view.isHidden else { return }
|
||||
|
||||
rotating = true
|
||||
|
||||
let dismiss = self.presentingViewControllerUseSnapshot || self.dismissOnRotation
|
||||
coordinator.animate(alongsideTransition: { _ in
|
||||
if dismiss {
|
||||
transitionController.transition(presenting: false, animated: false, complete: false)
|
||||
} else {
|
||||
transitionController.layout()
|
||||
}
|
||||
}) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
if dismiss {
|
||||
self.dismissMenu(animated: false)
|
||||
}
|
||||
self.rotating = false
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
transitionController?.layout()
|
||||
}
|
||||
|
||||
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
|
||||
guard viewControllers.count > 0 else {
|
||||
// NOTE: pushViewController is called by init(rootViewController: UIViewController)
|
||||
// so we must perform the normal super method in this case
|
||||
return super.pushViewController(viewController, animated: animated)
|
||||
}
|
||||
|
||||
var alongsideTransition: (() -> Void)? = nil
|
||||
if dismissOnPush {
|
||||
alongsideTransition = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.dismissAnimation(animated: animated || self.alwaysAnimate)
|
||||
}
|
||||
}
|
||||
|
||||
let pushed = SideMenuPushCoordinator(config:
|
||||
.init(
|
||||
allowPushOfSameClassTwice: allowPushOfSameClassTwice,
|
||||
alongsideTransition: alongsideTransition,
|
||||
animated: animated,
|
||||
fromViewController: self,
|
||||
pushStyle: pushStyle,
|
||||
toViewController: viewController
|
||||
)
|
||||
).start()
|
||||
|
||||
if !pushed {
|
||||
super.pushViewController(viewController, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
override open var transitioningDelegate: UIViewControllerTransitioningDelegate? {
|
||||
get {
|
||||
guard transitionController == nil else { return transitionController }
|
||||
transitionController = SideMenuTransitionController(leftSide: leftSide, config: settings)
|
||||
transitionController?.delegate = self
|
||||
transitionController?.interactive = transitionInteractive
|
||||
transitionInteractive = false
|
||||
return transitionController
|
||||
}
|
||||
set { Print.warning(.transitioningDelegate, required: true) }
|
||||
}
|
||||
}
|
||||
|
||||
// Interface
|
||||
extension SideMenuNavigationController: Model {
|
||||
|
||||
@IBInspectable open var allowPushOfSameClassTwice: Bool {
|
||||
get { return settings.allowPushOfSameClassTwice }
|
||||
set { settings.allowPushOfSameClassTwice = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var alwaysAnimate: Bool {
|
||||
get { return settings.alwaysAnimate }
|
||||
set { settings.alwaysAnimate = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var animationOptions: UIView.AnimationOptions {
|
||||
get { return settings.animationOptions }
|
||||
set { settings.animationOptions = newValue }
|
||||
}
|
||||
|
||||
open var blurEffectStyle: UIBlurEffect.Style? {
|
||||
get { return settings.blurEffectStyle }
|
||||
set { settings.blurEffectStyle = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var completeGestureDuration: Double {
|
||||
get { return settings.completeGestureDuration }
|
||||
set { settings.completeGestureDuration = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var completionCurve: UIView.AnimationCurve {
|
||||
get { return settings.completionCurve }
|
||||
set { settings.completionCurve = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var dismissDuration: Double {
|
||||
get { return settings.dismissDuration }
|
||||
set { settings.dismissDuration = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var dismissOnPresent: Bool {
|
||||
get { return settings.dismissOnPresent }
|
||||
set { settings.dismissOnPresent = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var dismissOnPush: Bool {
|
||||
get { return settings.dismissOnPush }
|
||||
set { settings.dismissOnPush = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var dismissOnRotation: Bool {
|
||||
get { return settings.dismissOnRotation }
|
||||
set { settings.dismissOnRotation = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var dismissWhenBackgrounded: Bool {
|
||||
get { return settings.dismissWhenBackgrounded }
|
||||
set { settings.dismissWhenBackgrounded = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var enableSwipeToDismissGesture: Bool {
|
||||
get { return settings.enableSwipeToDismissGesture }
|
||||
set { settings.enableSwipeToDismissGesture = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var enableTapToDismissGesture: Bool {
|
||||
get { return settings.enableTapToDismissGesture }
|
||||
set { settings.enableTapToDismissGesture = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var initialSpringVelocity: CGFloat {
|
||||
get { return settings.initialSpringVelocity }
|
||||
set { settings.initialSpringVelocity = newValue }
|
||||
}
|
||||
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
|
||||
@IBInspectable open var leftSide: Bool {
|
||||
get { return _leftSide.value }
|
||||
set { _leftSide.value = newValue }
|
||||
}
|
||||
|
||||
/// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller.
|
||||
open override var isHidden: Bool {
|
||||
return super.isHidden
|
||||
}
|
||||
|
||||
@IBInspectable open var menuWidth: CGFloat {
|
||||
get { return settings.menuWidth }
|
||||
set { settings.menuWidth = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var presentingViewControllerUserInteractionEnabled: Bool {
|
||||
get { return settings.presentingViewControllerUserInteractionEnabled }
|
||||
set { settings.presentingViewControllerUserInteractionEnabled = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var presentingViewControllerUseSnapshot: Bool {
|
||||
get { return settings.presentingViewControllerUseSnapshot }
|
||||
set { settings.presentingViewControllerUseSnapshot = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var presentDuration: Double {
|
||||
get { return settings.presentDuration }
|
||||
set { settings.presentDuration = newValue }
|
||||
}
|
||||
|
||||
open var presentationStyle: SideMenuPresentationStyle {
|
||||
get { return settings.presentationStyle }
|
||||
set { settings.presentationStyle = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var pushStyle: SideMenuPushStyle {
|
||||
get { return settings.pushStyle }
|
||||
set { settings.pushStyle = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var statusBarEndAlpha: CGFloat {
|
||||
get { return settings.statusBarEndAlpha }
|
||||
set { settings.statusBarEndAlpha = newValue }
|
||||
}
|
||||
|
||||
@IBInspectable open var usingSpringWithDamping: CGFloat {
|
||||
get { return settings.usingSpringWithDamping }
|
||||
set { settings.usingSpringWithDamping = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
extension SideMenuNavigationController: SideMenuTransitionControllerDelegate {
|
||||
|
||||
func sideMenuTransitionController(_ transitionController: SideMenuTransitionController, didDismiss viewController: UIViewController) {
|
||||
sideMenuManager.sideMenuTransitionDidDismiss(menu: self)
|
||||
}
|
||||
|
||||
func sideMenuTransitionController(_ transitionController: SideMenuTransitionController, didPresent viewController: UIViewController) {
|
||||
swipeToDismissGesture?.remove()
|
||||
swipeToDismissGesture = addSwipeToDismissGesture(to: view.superview)
|
||||
tapToDismissGesture = addTapToDismissGesture(to: view.superview)
|
||||
}
|
||||
}
|
||||
|
||||
internal extension SideMenuNavigationController {
|
||||
|
||||
func handleMenuPan(_ gesture: UIPanGestureRecognizer, _ presenting: Bool) {
|
||||
let width = menuWidth
|
||||
let distance = gesture.xTranslation / width
|
||||
let progress = max(min(distance * factor(presenting), 1), 0)
|
||||
switch (gesture.state) {
|
||||
case .began:
|
||||
if !presenting {
|
||||
dismissMenu(interactively: true)
|
||||
}
|
||||
fallthrough
|
||||
case .changed:
|
||||
transitionController?.handle(state: .update(progress: progress))
|
||||
case .ended:
|
||||
let velocity = gesture.xVelocity * factor(presenting)
|
||||
let finished = velocity >= 100 || velocity >= -50 && abs(progress) >= 0.5
|
||||
transitionController?.handle(state: finished ? .finish : .cancel)
|
||||
default:
|
||||
transitionController?.handle(state: .cancel)
|
||||
}
|
||||
}
|
||||
|
||||
func cancelMenuPan(_ gesture: UIPanGestureRecognizer) {
|
||||
transitionController?.handle(state: .cancel)
|
||||
}
|
||||
|
||||
func dismissMenu(animated flag: Bool = true, interactively: Bool = false, completion: (() -> Void)? = nil) {
|
||||
guard !isHidden else { return }
|
||||
transitionController?.interactive = interactively
|
||||
dismiss(animated: flag, completion: completion)
|
||||
}
|
||||
|
||||
// Note: although this method is syntactically reversed it allows the interactive property to scoped privately
|
||||
func present(from viewController: UIViewController?, interactively: Bool, completion: (() -> Void)? = nil) {
|
||||
guard let viewController = viewController else { return }
|
||||
transitionInteractive = interactively
|
||||
viewController.present(self, animated: true, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuNavigationController {
|
||||
|
||||
weak var activeDelegate: SideMenuNavigationControllerDelegate? {
|
||||
guard !view.isHidden else { return nil }
|
||||
if let sideMenuDelegate = sideMenuDelegate { return sideMenuDelegate }
|
||||
return findViewController as? SideMenuNavigationControllerDelegate
|
||||
}
|
||||
|
||||
var findViewController: UIViewController? {
|
||||
foundViewController = foundViewController ?? presentingViewController?.activeViewController
|
||||
return foundViewController
|
||||
}
|
||||
|
||||
func dismissAnimation(animated: Bool) {
|
||||
transitionController?.transition(presenting: false, animated: animated, alongsideTransition: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
|
||||
}, completion: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
|
||||
self.dismiss(animated: false, completion: nil)
|
||||
self.foundViewController = nil
|
||||
})
|
||||
}
|
||||
|
||||
func setup() {
|
||||
modalPresentationStyle = .overFullScreen
|
||||
|
||||
setupBlur()
|
||||
if #available(iOS 13.0, *) {} else {
|
||||
registerForNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
func setupBlur() {
|
||||
removeBlur()
|
||||
|
||||
guard let blurEffectStyle = blurEffectStyle,
|
||||
let view = topViewController?.view,
|
||||
!UIAccessibility.isReduceTransparencyEnabled else {
|
||||
return
|
||||
}
|
||||
|
||||
originalBackgroundColor = originalBackgroundColor ?? view.backgroundColor
|
||||
|
||||
let blurEffect = UIBlurEffect(style: blurEffectStyle)
|
||||
let blurView = UIVisualEffectView(effect: blurEffect)
|
||||
view.backgroundColor = UIColor.clear
|
||||
if let tableViewController = topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = blurView
|
||||
tableViewController.tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||
tableViewController.tableView.reloadData()
|
||||
} else {
|
||||
blurView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
blurView.frame = view.bounds
|
||||
view.insertSubview(blurView, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
func removeBlur() {
|
||||
guard let originalBackgroundColor = originalBackgroundColor,
|
||||
let view = topViewController?.view else {
|
||||
return
|
||||
}
|
||||
|
||||
self.originalBackgroundColor = nil
|
||||
view.backgroundColor = originalBackgroundColor
|
||||
|
||||
if let tableViewController = topViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = nil
|
||||
tableViewController.tableView.separatorEffect = nil
|
||||
tableViewController.tableView.reloadData()
|
||||
} else if let blurView = view.subviews.first as? UIVisualEffectView {
|
||||
blurView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS, deprecated: 13.0)
|
||||
func registerForNotifications() {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
|
||||
[UIApplication.willChangeStatusBarFrameNotification,
|
||||
UIApplication.didEnterBackgroundNotification].forEach {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: $0, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS, deprecated: 13.0)
|
||||
@objc func handleNotification(notification: NSNotification) {
|
||||
guard isHidden else { return }
|
||||
|
||||
switch notification.name {
|
||||
case UIApplication.willChangeStatusBarFrameNotification:
|
||||
// Dismiss for in-call status bar changes but not rotation
|
||||
if !rotating {
|
||||
dismissMenu()
|
||||
}
|
||||
case UIApplication.didEnterBackgroundNotification:
|
||||
if dismissWhenBackgrounded {
|
||||
dismissMenu()
|
||||
}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func addSwipeToDismissGesture(to view: UIView?) -> UIPanGestureRecognizer? {
|
||||
guard enableSwipeToDismissGesture else { return nil }
|
||||
return UIPanGestureRecognizer(addTo: view, target: self, action: #selector(handleDismissMenuPan(_:)))?.with {
|
||||
$0.cancelsTouchesInView = false
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func addTapToDismissGesture(to view: UIView?) -> UITapGestureRecognizer? {
|
||||
guard enableTapToDismissGesture else { return nil }
|
||||
return UITapGestureRecognizer(addTo: view, target: self, action: #selector(handleDismissMenuTap(_:)))?.with {
|
||||
$0.cancelsTouchesInView = false
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handleDismissMenuTap(_ tap: UITapGestureRecognizer) {
|
||||
let hitTest = view.window?.hitTest(tap.location(in: view.superview), with: nil)
|
||||
guard hitTest == view.superview else { return }
|
||||
dismissMenu()
|
||||
}
|
||||
|
||||
@objc func handleDismissMenuPan(_ gesture: UIPanGestureRecognizer) {
|
||||
handleMenuPan(gesture, false)
|
||||
}
|
||||
|
||||
func factor(_ presenting: Bool) -> CGFloat {
|
||||
return presenting ? presentFactor : hideFactor
|
||||
}
|
||||
|
||||
var presentFactor: CGFloat {
|
||||
return leftSide ? 1 : -1
|
||||
}
|
||||
|
||||
var hideFactor: CGFloat {
|
||||
return -presentFactor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
//
|
||||
// BasePresentationController.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 10/20/18.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
internal protocol PresentationModel {
|
||||
/// Draws `presentStyle.backgroundColor` behind the status bar. Default is 1.
|
||||
var statusBarEndAlpha: CGFloat { get }
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. `presentingViewControllerUseSnapshot` must also set to false. Default is false.
|
||||
var presentingViewControllerUserInteractionEnabled: Bool { get }
|
||||
/// Use a snapshot for the presenting vierw controller while the menu is displayed. Useful when layout changes occur during transitions. Not recommended for apps that support rotation. Default is false.
|
||||
var presentingViewControllerUseSnapshot: Bool { get }
|
||||
/// The presentation style of the menu.
|
||||
var presentationStyle: SideMenuPresentationStyle { get }
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero.
|
||||
var menuWidth: CGFloat { get }
|
||||
}
|
||||
|
||||
internal protocol SideMenuPresentationControllerDelegate: class {
|
||||
func sideMenuPresentationControllerDidTap(_ presentationController: SideMenuPresentationController)
|
||||
func sideMenuPresentationController(_ presentationController: SideMenuPresentationController, didPanWith gesture: UIPanGestureRecognizer)
|
||||
}
|
||||
|
||||
internal final class SideMenuPresentationController {
|
||||
|
||||
private let config: PresentationModel
|
||||
private weak var containerView: UIView?
|
||||
private var interactivePopGestureRecognizerEnabled: Bool?
|
||||
private var clipsToBounds: Bool?
|
||||
private let leftSide: Bool
|
||||
private weak var presentedViewController: UIViewController?
|
||||
private weak var presentingViewController: UIViewController?
|
||||
|
||||
private lazy var snapshotView: UIView? = {
|
||||
guard config.presentingViewControllerUseSnapshot,
|
||||
let view = presentingViewController?.view.snapshotView(afterScreenUpdates: true) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var statusBarView: UIView? = {
|
||||
guard config.statusBarEndAlpha > .leastNonzeroMagnitude else { return nil }
|
||||
|
||||
return UIView {
|
||||
$0.backgroundColor = config.presentationStyle.backgroundColor
|
||||
$0.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
$0.isUserInteractionEnabled = false
|
||||
}
|
||||
}()
|
||||
|
||||
required init(config: PresentationModel, leftSide: Bool, presentedViewController: UIViewController, presentingViewController: UIViewController, containerView: UIView) {
|
||||
self.config = config
|
||||
self.containerView = containerView
|
||||
self.leftSide = leftSide
|
||||
self.presentedViewController = presentedViewController
|
||||
self.presentingViewController = presentingViewController
|
||||
}
|
||||
|
||||
deinit {
|
||||
guard presentedViewController?.isHidden == false else { return }
|
||||
|
||||
// Presentations must be reversed to preserve user experience
|
||||
dismissalTransitionWillBegin()
|
||||
dismissalTransition()
|
||||
dismissalTransitionDidEnd(true)
|
||||
}
|
||||
|
||||
func containerViewWillLayoutSubviews() {
|
||||
guard let containerView = containerView,
|
||||
let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
presentedViewController.view.untransform {
|
||||
presentedViewController.view.frame = frameOfPresentedViewInContainerView
|
||||
}
|
||||
presentingViewController.view.untransform {
|
||||
presentingViewController.view.frame = frameOfPresentingViewInContainerView
|
||||
snapshotView?.frame = presentingViewController.view.bounds
|
||||
}
|
||||
|
||||
guard let statusBarView = statusBarView else { return }
|
||||
|
||||
var statusBarFrame: CGRect = self.statusBarFrame
|
||||
statusBarFrame.size.height -= containerView.frame.minY
|
||||
statusBarView.frame = statusBarFrame
|
||||
}
|
||||
|
||||
func presentationTransitionWillBegin() {
|
||||
guard let containerView = containerView,
|
||||
let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
if let snapshotView = snapshotView {
|
||||
presentingViewController.view.addSubview(snapshotView)
|
||||
}
|
||||
|
||||
presentingViewController.view.isUserInteractionEnabled = config.presentingViewControllerUserInteractionEnabled
|
||||
containerView.backgroundColor = config.presentationStyle.backgroundColor
|
||||
|
||||
layerViews()
|
||||
|
||||
if let statusBarView = statusBarView {
|
||||
containerView.addSubview(statusBarView)
|
||||
}
|
||||
|
||||
dismissalTransition()
|
||||
config.presentationStyle.presentationTransitionWillBegin(to: presentedViewController, from: presentingViewController)
|
||||
}
|
||||
|
||||
func presentationTransition() {
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
transition(
|
||||
to: presentedViewController,
|
||||
from: presentingViewController,
|
||||
alpha: config.presentationStyle.presentingEndAlpha,
|
||||
statusBarAlpha: config.statusBarEndAlpha,
|
||||
scale: config.presentationStyle.presentingScaleFactor,
|
||||
translate: config.presentationStyle.presentingTranslateFactor
|
||||
)
|
||||
|
||||
config.presentationStyle.presentationTransition(to: presentedViewController, from: presentingViewController)
|
||||
}
|
||||
|
||||
func presentationTransitionDidEnd(_ completed: Bool) {
|
||||
guard completed else {
|
||||
snapshotView?.removeFromSuperview()
|
||||
dismissalTransitionDidEnd(!completed)
|
||||
return
|
||||
}
|
||||
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
addParallax(to: presentingViewController.view)
|
||||
|
||||
if let topNavigationController = presentingViewController as? UINavigationController {
|
||||
interactivePopGestureRecognizerEnabled = interactivePopGestureRecognizerEnabled ?? topNavigationController.interactivePopGestureRecognizer?.isEnabled
|
||||
topNavigationController.interactivePopGestureRecognizer?.isEnabled = false
|
||||
}
|
||||
|
||||
containerViewWillLayoutSubviews()
|
||||
config.presentationStyle.presentationTransitionDidEnd(to: presentedViewController, from: presentingViewController, completed)
|
||||
}
|
||||
|
||||
func dismissalTransitionWillBegin() {
|
||||
snapshotView?.removeFromSuperview()
|
||||
presentationTransition()
|
||||
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
config.presentationStyle.dismissalTransitionWillBegin(to: presentedViewController, from: presentingViewController)
|
||||
}
|
||||
|
||||
func dismissalTransition() {
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
transition(
|
||||
to: presentingViewController,
|
||||
from: presentedViewController,
|
||||
alpha: config.presentationStyle.menuStartAlpha,
|
||||
statusBarAlpha: 0,
|
||||
scale: config.presentationStyle.menuScaleFactor,
|
||||
translate: config.presentationStyle.menuTranslateFactor
|
||||
)
|
||||
|
||||
config.presentationStyle.dismissalTransition(to: presentedViewController, from: presentingViewController)
|
||||
}
|
||||
|
||||
func dismissalTransitionDidEnd(_ completed: Bool) {
|
||||
guard completed else {
|
||||
if let snapshotView = snapshotView, let presentingViewController = presentingViewController {
|
||||
presentingViewController.view.addSubview(snapshotView)
|
||||
}
|
||||
presentationTransitionDidEnd(!completed)
|
||||
return
|
||||
}
|
||||
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
statusBarView?.removeFromSuperview()
|
||||
removeStyles(from: presentingViewController.containerViewController.view)
|
||||
|
||||
if let interactivePopGestureRecognizerEnabled = interactivePopGestureRecognizerEnabled,
|
||||
let topNavigationController = presentingViewController as? UINavigationController {
|
||||
topNavigationController.interactivePopGestureRecognizer?.isEnabled = interactivePopGestureRecognizerEnabled
|
||||
}
|
||||
|
||||
presentingViewController.view.isUserInteractionEnabled = true
|
||||
config.presentationStyle.dismissalTransitionDidEnd(to: presentedViewController, from: presentingViewController, completed)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuPresentationController {
|
||||
|
||||
var statusBarFrame: CGRect {
|
||||
if #available(iOS 13.0, *) {
|
||||
return containerView?.window?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
|
||||
} else {
|
||||
return UIApplication.shared.statusBarFrame
|
||||
}
|
||||
}
|
||||
|
||||
var frameOfPresentedViewInContainerView: CGRect {
|
||||
guard let containerView = containerView else { return .zero }
|
||||
var rect = containerView.bounds
|
||||
rect.origin.x = leftSide ? 0 : rect.width - config.menuWidth
|
||||
rect.size.width = config.menuWidth
|
||||
return rect
|
||||
}
|
||||
|
||||
var frameOfPresentingViewInContainerView: CGRect {
|
||||
guard let containerView = containerView else { return .zero }
|
||||
var rect = containerView.frame
|
||||
if containerView.superview != nil, containerView.frame.minY > .ulpOfOne {
|
||||
let statusBarOffset = statusBarFrame.height - rect.minY
|
||||
rect.origin.y = statusBarOffset
|
||||
rect.size.height -= statusBarOffset
|
||||
}
|
||||
return rect
|
||||
}
|
||||
|
||||
func transition(to: UIViewController, from: UIViewController, alpha: CGFloat, statusBarAlpha: CGFloat, scale: CGFloat, translate: CGFloat) {
|
||||
containerViewWillLayoutSubviews()
|
||||
|
||||
to.view.transform = .identity
|
||||
to.view.alpha = 1
|
||||
|
||||
let x = (leftSide ? 1 : -1) * config.menuWidth * translate
|
||||
from.view.alpha = alpha
|
||||
from.view.transform = CGAffineTransform
|
||||
.identity
|
||||
.translatedBy(x: x, y: 0)
|
||||
.scaledBy(x: scale, y: scale)
|
||||
|
||||
statusBarView?.alpha = statusBarAlpha
|
||||
}
|
||||
|
||||
func layerViews() {
|
||||
guard let presentedViewController = presentedViewController,
|
||||
let presentingViewController = presentingViewController
|
||||
else { return }
|
||||
|
||||
statusBarView?.layer.zPosition = 2
|
||||
|
||||
if config.presentationStyle.menuOnTop {
|
||||
addShadow(to: presentedViewController.view)
|
||||
presentedViewController.view.layer.zPosition = 1
|
||||
} else {
|
||||
addShadow(to: presentingViewController.view)
|
||||
presentedViewController.view.layer.zPosition = -1
|
||||
}
|
||||
}
|
||||
|
||||
func addShadow(to view: UIView) {
|
||||
view.layer.shadowColor = config.presentationStyle.onTopShadowColor.cgColor
|
||||
view.layer.shadowRadius = config.presentationStyle.onTopShadowRadius
|
||||
view.layer.shadowOpacity = config.presentationStyle.onTopShadowOpacity
|
||||
view.layer.shadowOffset = config.presentationStyle.onTopShadowOffset
|
||||
clipsToBounds = clipsToBounds ?? view.clipsToBounds
|
||||
view.clipsToBounds = false
|
||||
}
|
||||
|
||||
func addParallax(to view: UIView) {
|
||||
var effects: [UIInterpolatingMotionEffect] = []
|
||||
|
||||
let x = config.presentationStyle.presentingParallaxStrength.width
|
||||
if x > 0 {
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -x
|
||||
horizontal.maximumRelativeValue = x
|
||||
effects.append(horizontal)
|
||||
}
|
||||
|
||||
let y = config.presentationStyle.presentingParallaxStrength.height
|
||||
if y > 0 {
|
||||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
||||
vertical.minimumRelativeValue = -y
|
||||
vertical.maximumRelativeValue = y
|
||||
effects.append(vertical)
|
||||
}
|
||||
|
||||
if effects.count > 0 {
|
||||
let group = UIMotionEffectGroup()
|
||||
group.motionEffects = effects
|
||||
view.motionEffects.removeAll()
|
||||
view.addMotionEffect(group)
|
||||
}
|
||||
}
|
||||
|
||||
func removeStyles(from view: UIView) {
|
||||
view.motionEffects.removeAll()
|
||||
view.layer.shadowOpacity = 0
|
||||
view.layer.shadowOpacity = 0
|
||||
view.clipsToBounds = clipsToBounds ?? true
|
||||
clipsToBounds = false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// SideMenuPresentStyle.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 7/2/19.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers
|
||||
open class SideMenuPresentationStyle: InitializableClass {
|
||||
/// Background color behind the views and status bar color
|
||||
open var backgroundColor: UIColor = .black
|
||||
/// The starting alpha value of the menu before it appears
|
||||
open var menuStartAlpha: CGFloat = 1
|
||||
/// Whether or not the menu is on top. If false, the presenting view is on top. Shadows are applied to the view on top.
|
||||
open var menuOnTop: Bool = false
|
||||
/// The amount the menu is translated along the x-axis. Zero is stationary, negative values are off-screen, positive values are on screen.
|
||||
open var menuTranslateFactor: CGFloat = 0
|
||||
/// The amount the menu is scaled. Less than one shrinks the view, larger than one grows the view.
|
||||
open var menuScaleFactor: CGFloat = 1
|
||||
/// The color of the shadow applied to the top most view.
|
||||
open var onTopShadowColor: UIColor = .black
|
||||
/// The radius of the shadow applied to the top most view.
|
||||
open var onTopShadowRadius: CGFloat = 5
|
||||
/// The opacity of the shadow applied to the top most view.
|
||||
open var onTopShadowOpacity: Float = 0
|
||||
/// The offset of the shadow applied to the top most view.
|
||||
open var onTopShadowOffset: CGSize = .zero
|
||||
/// The ending alpha of the presenting view when the menu is fully displayed.
|
||||
open var presentingEndAlpha: CGFloat = 1
|
||||
/// The amount the presenting view is translated along the x-axis. Zero is stationary, negative values are off-screen, positive values are on screen.
|
||||
open var presentingTranslateFactor: CGFloat = 0
|
||||
/// The amount the presenting view is scaled. Less than one shrinks the view, larger than one grows the view.
|
||||
open var presentingScaleFactor: CGFloat = 1
|
||||
/// The strength of the parallax effect on the presenting view once the menu is displayed.
|
||||
open var presentingParallaxStrength: CGSize = .zero
|
||||
|
||||
required public init() {}
|
||||
|
||||
/// This method is called just before the presentation transition begins. Use this to setup any animations. The super method does not need to be called.
|
||||
open func presentationTransitionWillBegin(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called during the presentation animation. Use this to animate anything alongside the menu animation. The super method does not need to be called.
|
||||
open func presentationTransition(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called when the presentation transition ends. Use this to finish any animations. The super method does not need to be called.
|
||||
open func presentationTransitionDidEnd(to presentedViewController: UIViewController, from presentingViewController: UIViewController, _ completed: Bool) {}
|
||||
/// This method is called just before the dismissal transition begins. Use this to setup any animations. The super method does not need to be called.
|
||||
open func dismissalTransitionWillBegin(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called during the dismissal animation. Use this to animate anything alongside the menu animation. The super method does not need to be called.
|
||||
open func dismissalTransition(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called when the dismissal transition ends. Use this to finish any animations. The super method does not need to be called.
|
||||
open func dismissalTransitionDidEnd(to presentedViewController: UIViewController, from presentingViewController: UIViewController, _ completed: Bool) {}
|
||||
}
|
||||
|
||||
public extension SideMenuPresentationStyle {
|
||||
/// Menu slides in over the existing view.
|
||||
static var menuSlideIn: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuOnTop = true
|
||||
$0.menuTranslateFactor = -1
|
||||
}
|
||||
}
|
||||
/// The existing view slides out to reveal the menu underneath.
|
||||
static var viewSlideOut: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.presentingTranslateFactor = 1
|
||||
}
|
||||
}
|
||||
/// The existing view slides out while the menu slides in.
|
||||
static var viewSlideOutMenuIn: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuTranslateFactor = -1
|
||||
$0.presentingTranslateFactor = 1
|
||||
}
|
||||
}
|
||||
/// The menu dissolves in over the existing view.
|
||||
static var menuDissolveIn: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuStartAlpha = 0
|
||||
$0.menuOnTop = true
|
||||
}
|
||||
}
|
||||
/// The existing view slides out while the menu partially slides in.
|
||||
static var viewSlideOutMenuPartialIn: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuTranslateFactor = -0.5
|
||||
$0.presentingTranslateFactor = 1
|
||||
}
|
||||
}
|
||||
/// The existing view slides out while the menu slides out from under it.
|
||||
static var viewSlideOutMenuOut: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuTranslateFactor = 1
|
||||
$0.presentingTranslateFactor = 1
|
||||
}
|
||||
}
|
||||
/// The existing view slides out while the menu partially slides out from under it.
|
||||
static var viewSlideOutMenuPartialOut: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.menuTranslateFactor = 0.5
|
||||
$0.presentingTranslateFactor = 1
|
||||
}
|
||||
}
|
||||
/// The existing view slides out and shrinks to reveal the menu underneath.
|
||||
static var viewSlideOutMenuZoom: SideMenuPresentationStyle {
|
||||
return SideMenuPresentationStyle {
|
||||
$0.presentingTranslateFactor = 1
|
||||
$0.menuScaleFactor = 0.95
|
||||
$0.menuOnTop = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// PushCoordinator.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 9/4/19.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol CoordinatorModel {
|
||||
var animated: Bool { get }
|
||||
var fromViewController: UIViewController { get }
|
||||
var toViewController: UIViewController { get }
|
||||
}
|
||||
|
||||
protocol Coordinator {
|
||||
associatedtype Model: CoordinatorModel
|
||||
|
||||
init(config: Model)
|
||||
@discardableResult func start() -> Bool
|
||||
}
|
||||
|
||||
internal final class SideMenuPushCoordinator: Coordinator {
|
||||
|
||||
struct Model: CoordinatorModel {
|
||||
var allowPushOfSameClassTwice: Bool
|
||||
var alongsideTransition: (() -> Void)?
|
||||
var animated: Bool
|
||||
var fromViewController: UIViewController
|
||||
var pushStyle: SideMenuPushStyle
|
||||
var toViewController: UIViewController
|
||||
}
|
||||
|
||||
private let config: Model
|
||||
|
||||
init(config: Model) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
@discardableResult func start() -> Bool {
|
||||
guard config.pushStyle != .subMenu,
|
||||
let fromNavigationController = config.fromViewController as? UINavigationController else {
|
||||
return false
|
||||
}
|
||||
let toViewController = config.toViewController
|
||||
let presentingViewController = fromNavigationController.presentingViewController
|
||||
let splitViewController = presentingViewController as? UISplitViewController
|
||||
let tabBarController = presentingViewController as? UITabBarController
|
||||
let potentialNavigationController = (splitViewController?.viewControllers.first ?? tabBarController?.selectedViewController) ?? presentingViewController
|
||||
guard let navigationController = potentialNavigationController as? UINavigationController else {
|
||||
Print.warning(.cannotPush, arguments: String(describing: potentialNavigationController.self), required: true)
|
||||
return false
|
||||
}
|
||||
|
||||
// To avoid overlapping dismiss & pop/push calls, create a transaction block where the menu
|
||||
// is dismissed after showing the appropriate screen
|
||||
CATransaction.begin()
|
||||
defer { CATransaction.commit() }
|
||||
UIView.animationsEnabled { [weak self] in
|
||||
self?.config.alongsideTransition?()
|
||||
}
|
||||
|
||||
if let lastViewController = navigationController.viewControllers.last,
|
||||
!config.allowPushOfSameClassTwice && type(of: lastViewController) == type(of: toViewController) {
|
||||
return false
|
||||
}
|
||||
|
||||
toViewController.navigationItem.hidesBackButton = config.pushStyle.hidesBackButton
|
||||
|
||||
switch config.pushStyle {
|
||||
|
||||
case .default:
|
||||
navigationController.pushViewController(toViewController, animated: config.animated)
|
||||
return true
|
||||
|
||||
// subMenu handled earlier
|
||||
case .subMenu:
|
||||
return false
|
||||
|
||||
case .popWhenPossible:
|
||||
for subViewController in navigationController.viewControllers.reversed() {
|
||||
if type(of: subViewController) == type(of: toViewController) {
|
||||
navigationController.popToViewController(subViewController, animated: config.animated)
|
||||
return true
|
||||
}
|
||||
}
|
||||
navigationController.pushViewController(toViewController, animated: config.animated)
|
||||
return true
|
||||
|
||||
case .preserve, .preserveAndHideBackButton:
|
||||
var viewControllers = navigationController.viewControllers
|
||||
let filtered = viewControllers.filter { preservedViewController in type(of: preservedViewController) == type(of: toViewController) }
|
||||
guard let preservedViewController = filtered.last else {
|
||||
navigationController.pushViewController(toViewController, animated: config.animated)
|
||||
return true
|
||||
}
|
||||
viewControllers = viewControllers.filter { subViewController in subViewController !== preservedViewController }
|
||||
viewControllers.append(preservedViewController)
|
||||
navigationController.setViewControllers(viewControllers, animated: config.animated)
|
||||
return true
|
||||
|
||||
case .replace:
|
||||
navigationController.setViewControllers([toViewController], animated: config.animated)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,583 +0,0 @@
|
||||
//
|
||||
// SideMenuTransition.swift
|
||||
// Pods
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
//
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
fileprivate var presenting = false
|
||||
fileprivate var interactive = false
|
||||
fileprivate weak var originalSuperview: UIView?
|
||||
fileprivate weak var activeGesture: UIGestureRecognizer?
|
||||
fileprivate var switchMenus = false {
|
||||
didSet {
|
||||
if switchMenus {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
fileprivate var menuWidth: CGFloat {
|
||||
get {
|
||||
let overriddenWidth = menuViewController?.menuWidth ?? 0
|
||||
if overriddenWidth > CGFloat.ulpOfOne {
|
||||
return overriddenWidth
|
||||
}
|
||||
return sideMenuManager.menuWidth
|
||||
}
|
||||
}
|
||||
internal weak var sideMenuManager: SideMenuManager!
|
||||
internal weak var mainViewController: UIViewController?
|
||||
internal weak var menuViewController: UISideMenuNavigationController? {
|
||||
get {
|
||||
return presentDirection == .left ? sideMenuManager.menuLeftNavigationController : sideMenuManager.menuRightNavigationController
|
||||
}
|
||||
}
|
||||
internal var presentDirection: UIRectEdge = .left
|
||||
internal weak var tapView: UIView? {
|
||||
didSet {
|
||||
guard let tapView = tapView else {
|
||||
return
|
||||
}
|
||||
|
||||
tapView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
let exitTapGesture = UITapGestureRecognizer()
|
||||
exitTapGesture.addTarget(self, action: #selector(SideMenuTransition.handleHideMenuTap(_:)))
|
||||
tapView.addGestureRecognizer(exitPanGesture)
|
||||
tapView.addGestureRecognizer(exitTapGesture)
|
||||
}
|
||||
}
|
||||
internal weak var statusBarView: UIView? {
|
||||
didSet {
|
||||
guard let statusBarView = statusBarView else {
|
||||
return
|
||||
}
|
||||
|
||||
statusBarView.backgroundColor = sideMenuManager.menuAnimationBackgroundColor ?? UIColor.black
|
||||
statusBarView.isUserInteractionEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
required public init(sideMenuManager: SideMenuManager) {
|
||||
super.init()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector:#selector(handleNotification), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector:#selector(handleNotification), name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
self.sideMenuManager = sideMenuManager
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
fileprivate static var visibleViewController: UIViewController? {
|
||||
get {
|
||||
return getVisibleViewController(forViewController: UIApplication.shared.keyWindow?.rootViewController)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class func getVisibleViewController(forViewController: UIViewController?) -> UIViewController? {
|
||||
if let navigationController = forViewController as? UINavigationController {
|
||||
return getVisibleViewController(forViewController: navigationController.visibleViewController)
|
||||
}
|
||||
if let tabBarController = forViewController as? UITabBarController {
|
||||
return getVisibleViewController(forViewController: tabBarController.selectedViewController)
|
||||
}
|
||||
if let splitViewController = forViewController as? UISplitViewController {
|
||||
return getVisibleViewController(forViewController: splitViewController.viewControllers.last)
|
||||
}
|
||||
if let presentedViewController = forViewController?.presentedViewController {
|
||||
return getVisibleViewController(forViewController: presentedViewController)
|
||||
}
|
||||
|
||||
return forViewController
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuLeftScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = .left
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuRightScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = .right
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
@objc internal func handlePresentMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
pan.isEnabled = false
|
||||
pan.isEnabled = true
|
||||
return
|
||||
} else if pan.state != .began && pan.state != .changed {
|
||||
activeGesture = nil
|
||||
}
|
||||
|
||||
// how much distance have we panned in reference to the parent view?
|
||||
guard let view = mainViewController?.view ?? pan.view else {
|
||||
return
|
||||
}
|
||||
|
||||
let transform = view.transform
|
||||
view.transform = .identity
|
||||
let translation = pan.translation(in: pan.view!)
|
||||
view.transform = transform
|
||||
|
||||
// do some math to translate this to a percentage based value
|
||||
if !interactive {
|
||||
if translation.x == 0 {
|
||||
return // not sure which way the user is swiping yet, so do nothing
|
||||
}
|
||||
|
||||
if !(pan is UIScreenEdgePanGestureRecognizer) {
|
||||
presentDirection = translation.x > 0 ? .left : .right
|
||||
}
|
||||
|
||||
if let menuViewController = menuViewController, let visibleViewController = SideMenuTransition.visibleViewController {
|
||||
interactive = true
|
||||
visibleViewController.present(menuViewController, animated: true, completion: nil)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let direction: CGFloat = presentDirection == .left ? 1 : -1
|
||||
let distance = translation.x / menuWidth
|
||||
// now lets deal with different states that the gesture recognizer sends
|
||||
switch (pan.state) {
|
||||
case .began, .changed:
|
||||
if pan is UIScreenEdgePanGestureRecognizer {
|
||||
update(min(distance * direction, 1))
|
||||
} else if distance > 0 && presentDirection == .right && sideMenuManager.menuLeftNavigationController != nil {
|
||||
presentDirection = .left
|
||||
switchMenus = true
|
||||
} else if distance < 0 && presentDirection == .left && sideMenuManager.menuRightNavigationController != nil {
|
||||
presentDirection = .right
|
||||
switchMenus = true
|
||||
} else {
|
||||
update(min(distance * direction, 1))
|
||||
}
|
||||
default:
|
||||
interactive = false
|
||||
view.transform = .identity
|
||||
let velocity = pan.velocity(in: pan.view!).x * direction
|
||||
view.transform = transform
|
||||
if velocity >= 100 || velocity >= -50 && abs(distance) >= 0.5 {
|
||||
// bug workaround: animation briefly resets after call to finishInteractiveTransition() but before animateTransition completion is called.
|
||||
if ProcessInfo().operatingSystemVersion.majorVersion == 8 && percentComplete > 1 - CGFloat.ulpOfOne {
|
||||
update(0.9999)
|
||||
}
|
||||
finish()
|
||||
} else {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func handleHideMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
pan.isEnabled = false
|
||||
pan.isEnabled = true
|
||||
return
|
||||
}
|
||||
|
||||
let translation = pan.translation(in: pan.view!)
|
||||
let direction:CGFloat = presentDirection == .left ? -1 : 1
|
||||
let distance = translation.x / menuWidth * direction
|
||||
|
||||
switch (pan.state) {
|
||||
|
||||
case .began:
|
||||
interactive = true
|
||||
mainViewController?.dismiss(animated: true, completion: nil)
|
||||
case .changed:
|
||||
update(max(min(distance, 1), 0))
|
||||
default:
|
||||
interactive = false
|
||||
let velocity = pan.velocity(in: pan.view!).x * direction
|
||||
if velocity >= 100 || velocity >= -50 && distance >= 0.5 {
|
||||
// bug workaround: animation briefly resets after call to finishInteractiveTransition() but before animateTransition completion is called.
|
||||
if ProcessInfo().operatingSystemVersion.majorVersion == 8 && percentComplete > 1 - CGFloat.ulpOfOne {
|
||||
update(0.9999)
|
||||
}
|
||||
finish()
|
||||
activeGesture = nil
|
||||
} else {
|
||||
cancel()
|
||||
activeGesture = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc internal func handleHideMenuTap(_ tap: UITapGestureRecognizer) {
|
||||
menuViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@discardableResult internal func hideMenuStart() -> SideMenuTransition {
|
||||
let menuView = menuViewController?.view
|
||||
let mainView = mainViewController?.view
|
||||
|
||||
mainView?.transform = .identity
|
||||
mainView?.alpha = 1
|
||||
mainView?.frame.origin = .zero
|
||||
menuView?.transform = .identity
|
||||
menuView?.frame.origin.y = 0
|
||||
menuView?.frame.size.width = menuWidth
|
||||
menuView?.frame.size.height = mainView?.frame.height ?? 0 // in case status bar height changed
|
||||
var statusBarFrame = UIApplication.shared.statusBarFrame
|
||||
let statusBarOffset = SideMenuManager.appScreenRect.size.height - (mainView?.frame.maxY ?? 0)
|
||||
// For in-call status bar, height is normally 40, which overlaps view. Instead, calculate height difference
|
||||
// of view and set height to fill in remaining space.
|
||||
if statusBarOffset >= CGFloat.ulpOfOne {
|
||||
statusBarFrame.size.height = statusBarOffset
|
||||
}
|
||||
statusBarView?.frame = statusBarFrame
|
||||
statusBarView?.alpha = 0
|
||||
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
|
||||
case .viewSlideOut:
|
||||
menuView?.alpha = 1 - sideMenuManager.menuAnimationFadeStrength
|
||||
menuView?.frame.origin.x = presentDirection == .left ? 0 : (mainView?.frame.width ?? 0) - menuWidth
|
||||
menuView?.transform = CGAffineTransform(scaleX: sideMenuManager.menuAnimationTransformScaleFactor, y: sideMenuManager.menuAnimationTransformScaleFactor)
|
||||
|
||||
case .viewSlideInOut:
|
||||
menuView?.alpha = 1
|
||||
menuView?.frame.origin.x = presentDirection == .left ? -menuView!.frame.width : mainView!.frame.width
|
||||
|
||||
case .menuSlideIn:
|
||||
menuView?.alpha = 1
|
||||
menuView?.frame.origin.x = presentDirection == .left ? -menuView!.frame.width : mainView!.frame.width
|
||||
|
||||
case .menuDissolveIn:
|
||||
menuView?.alpha = 0
|
||||
menuView?.frame.origin.x = presentDirection == .left ? 0 : mainView!.frame.width - menuWidth
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func hideMenuComplete() -> SideMenuTransition {
|
||||
let menuView = menuViewController?.view
|
||||
let mainView = mainViewController?.view
|
||||
|
||||
tapView?.removeFromSuperview()
|
||||
statusBarView?.removeFromSuperview()
|
||||
mainView?.motionEffects.removeAll()
|
||||
mainView?.layer.shadowOpacity = 0
|
||||
menuView?.layer.shadowOpacity = 0
|
||||
if let topNavigationController = mainViewController as? UINavigationController {
|
||||
topNavigationController.interactivePopGestureRecognizer!.isEnabled = true
|
||||
}
|
||||
if let originalSuperview = originalSuperview, let mainView = mainViewController?.view {
|
||||
originalSuperview.addSubview(mainView)
|
||||
let y = originalSuperview.bounds.height - mainView.frame.size.height
|
||||
mainView.frame.origin.y = max(y, 0)
|
||||
}
|
||||
|
||||
originalSuperview = nil
|
||||
mainViewController = nil
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func presentMenuStart() -> SideMenuTransition {
|
||||
let menuView = menuViewController?.view
|
||||
let mainView = mainViewController?.view
|
||||
|
||||
menuView?.alpha = 1
|
||||
menuView?.transform = .identity
|
||||
menuView?.frame.size.width = menuWidth
|
||||
let size = SideMenuManager.appScreenRect.size
|
||||
menuView?.frame.origin.x = presentDirection == .left ? 0 : size.width - menuWidth
|
||||
mainView?.transform = .identity
|
||||
mainView?.frame.size.width = size.width
|
||||
let statusBarOffset = size.height - (menuView?.bounds.height ?? 0)
|
||||
mainView?.bounds.size.height = size.height - max(statusBarOffset, 0)
|
||||
mainView?.frame.origin.y = 0
|
||||
var statusBarFrame = UIApplication.shared.statusBarFrame
|
||||
// For in-call status bar, height is normally 40, which overlaps view. Instead, calculate height difference
|
||||
// of view and set height to fill in remaining space.
|
||||
if statusBarOffset >= CGFloat.ulpOfOne {
|
||||
statusBarFrame.size.height = statusBarOffset
|
||||
}
|
||||
tapView?.transform = .identity
|
||||
tapView?.bounds = mainView!.bounds
|
||||
statusBarView?.frame = statusBarFrame
|
||||
statusBarView?.alpha = 1
|
||||
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
mainView?.layer.shadowColor = sideMenuManager.menuShadowColor.cgColor
|
||||
mainView?.layer.shadowRadius = sideMenuManager.menuShadowRadius
|
||||
mainView?.layer.shadowOpacity = sideMenuManager.menuShadowOpacity
|
||||
mainView?.layer.shadowOffset = CGSize(width: 0, height: 0)
|
||||
let direction:CGFloat = presentDirection == .left ? 1 : -1
|
||||
mainView?.frame.origin.x = direction * (menuView!.frame.width)
|
||||
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
if sideMenuManager.menuBlurEffectStyle == nil {
|
||||
menuView?.layer.shadowColor = sideMenuManager.menuShadowColor.cgColor
|
||||
menuView?.layer.shadowRadius = sideMenuManager.menuShadowRadius
|
||||
menuView?.layer.shadowOpacity = sideMenuManager.menuShadowOpacity
|
||||
menuView?.layer.shadowOffset = CGSize(width: 0, height: 0)
|
||||
}
|
||||
mainView?.frame.origin.x = 0
|
||||
}
|
||||
|
||||
if sideMenuManager.menuPresentMode != .viewSlideOut {
|
||||
mainView?.transform = CGAffineTransform(scaleX: sideMenuManager.menuAnimationTransformScaleFactor, y: sideMenuManager.menuAnimationTransformScaleFactor)
|
||||
if sideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
tapView?.transform = mainView!.transform
|
||||
}
|
||||
mainView?.alpha = 1 - sideMenuManager.menuAnimationFadeStrength
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult internal func presentMenuComplete() -> SideMenuTransition {
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .menuSlideIn, .menuDissolveIn, .viewSlideInOut:
|
||||
if let mainView = mainViewController?.view, sideMenuManager.menuParallaxStrength != 0 {
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -sideMenuManager.menuParallaxStrength
|
||||
horizontal.maximumRelativeValue = sideMenuManager.menuParallaxStrength
|
||||
|
||||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
||||
vertical.minimumRelativeValue = -sideMenuManager.menuParallaxStrength
|
||||
vertical.maximumRelativeValue = sideMenuManager.menuParallaxStrength
|
||||
|
||||
let group = UIMotionEffectGroup()
|
||||
group.motionEffects = [horizontal, vertical]
|
||||
mainView.addMotionEffect(group)
|
||||
}
|
||||
case .viewSlideOut: break;
|
||||
}
|
||||
if let topNavigationController = mainViewController as? UINavigationController {
|
||||
topNavigationController.interactivePopGestureRecognizer!.isEnabled = false
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
@objc internal func handleNotification(notification: NSNotification) {
|
||||
guard menuViewController?.presentedViewController == nil &&
|
||||
menuViewController?.presentingViewController != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
if let originalSuperview = originalSuperview, let mainViewController = mainViewController {
|
||||
originalSuperview.addSubview(mainViewController.view)
|
||||
}
|
||||
|
||||
if notification.name == NSNotification.Name.UIApplicationDidEnterBackground {
|
||||
hideMenuStart().hideMenuComplete()
|
||||
menuViewController?.dismiss(animated: false, completion: nil)
|
||||
return
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: sideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
self.hideMenuStart()
|
||||
}) { (finished) -> Void in
|
||||
self.hideMenuComplete()
|
||||
self.menuViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SideMenuTransition: UIViewControllerAnimatedTransitioning {
|
||||
|
||||
// animate a change from one viewcontroller to another
|
||||
open func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
|
||||
|
||||
// get reference to our fromView, toView and the container view that we should perform the transition in
|
||||
let container = transitionContext.containerView
|
||||
// prevent any other menu gestures from firing
|
||||
container.isUserInteractionEnabled = false
|
||||
|
||||
if let menuBackgroundColor = sideMenuManager.menuAnimationBackgroundColor {
|
||||
container.backgroundColor = menuBackgroundColor
|
||||
}
|
||||
|
||||
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
|
||||
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
|
||||
|
||||
// assign references to our menu view controller and the 'bottom' view controller from the tuple
|
||||
// remember that our menuViewController will alternate between the from and to view controller depending if we're presenting or dismissing
|
||||
mainViewController = presenting ? fromViewController : toViewController
|
||||
|
||||
let menuView = menuViewController!.view!
|
||||
let topView = mainViewController!.view!
|
||||
|
||||
// prepare menu items to slide in
|
||||
if presenting {
|
||||
originalSuperview = topView.superview
|
||||
|
||||
// add the both views to our view controller
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
container.addSubview(menuView)
|
||||
container.addSubview(topView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
container.addSubview(topView)
|
||||
container.addSubview(menuView)
|
||||
}
|
||||
|
||||
if sideMenuManager.menuFadeStatusBar {
|
||||
let statusBarView = UIView()
|
||||
self.statusBarView = statusBarView
|
||||
container.addSubview(statusBarView)
|
||||
}
|
||||
|
||||
hideMenuStart()
|
||||
}
|
||||
|
||||
let animate = {
|
||||
if self.presenting {
|
||||
self.presentMenuStart()
|
||||
} else {
|
||||
self.hideMenuStart()
|
||||
}
|
||||
}
|
||||
|
||||
let complete = {
|
||||
container.isUserInteractionEnabled = true
|
||||
|
||||
// tell our transitionContext object that we've finished animating
|
||||
if transitionContext.transitionWasCancelled {
|
||||
let viewControllerForPresentedMenu = self.mainViewController
|
||||
|
||||
if self.presenting {
|
||||
self.hideMenuComplete()
|
||||
} else {
|
||||
self.presentMenuComplete()
|
||||
}
|
||||
|
||||
transitionContext.completeTransition(false)
|
||||
|
||||
if self.switchMenus {
|
||||
self.switchMenus = false
|
||||
viewControllerForPresentedMenu?.present(self.menuViewController!, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if self.presenting {
|
||||
self.presentMenuComplete()
|
||||
transitionContext.completeTransition(true)
|
||||
switch self.sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
container.addSubview(topView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
container.insertSubview(topView, at: 0)
|
||||
}
|
||||
if !self.sideMenuManager.menuPresentingViewControllerUserInteractionEnabled {
|
||||
let tapView = UIView()
|
||||
container.insertSubview(tapView, aboveSubview: topView)
|
||||
tapView.bounds = container.bounds
|
||||
tapView.center = topView.center
|
||||
if self.sideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
tapView.transform = topView.transform
|
||||
}
|
||||
self.tapView = tapView
|
||||
}
|
||||
if let statusBarView = self.statusBarView {
|
||||
container.bringSubview(toFront: statusBarView)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.hideMenuComplete()
|
||||
transitionContext.completeTransition(true)
|
||||
menuView.removeFromSuperview()
|
||||
}
|
||||
|
||||
// perform the animation!
|
||||
let duration = transitionDuration(using: transitionContext)
|
||||
if interactive {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: duration, // HACK: If zero, the animation briefly flashes in iOS 11. UIViewPropertyAnimators (iOS 10+) may resolve this.
|
||||
options: .curveLinear,
|
||||
animations: {
|
||||
animate()
|
||||
}, completion: { (finished) in
|
||||
complete()
|
||||
})
|
||||
} else {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
animate()
|
||||
}) { (finished) -> Void in
|
||||
complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return how many seconds the transiton animation will take
|
||||
open func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
|
||||
if interactive {
|
||||
return sideMenuManager.menuAnimationCompleteGestureDuration
|
||||
}
|
||||
return presenting ? sideMenuManager.menuAnimationPresentDuration : sideMenuManager.menuAnimationDismissDuration
|
||||
}
|
||||
|
||||
open override func update(_ percentComplete: CGFloat) {
|
||||
guard !switchMenus else {
|
||||
return
|
||||
}
|
||||
|
||||
super.update(percentComplete)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SideMenuTransition: UIViewControllerTransitioningDelegate {
|
||||
|
||||
// return the animator when presenting a viewcontroller
|
||||
// rememeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
|
||||
open func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
self.presenting = true
|
||||
presentDirection = presented == sideMenuManager.menuLeftNavigationController ? .left : .right
|
||||
return self
|
||||
}
|
||||
|
||||
// return the animator used when dismissing from a viewcontroller
|
||||
open func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
presenting = false
|
||||
return self
|
||||
}
|
||||
|
||||
open func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
// if our interactive flag is true, return the transition manager object
|
||||
// otherwise return nil
|
||||
return interactive ? self : nil
|
||||
}
|
||||
|
||||
open func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
return interactive ? self : nil
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// SideMenuTransitioningDelegate.swift
|
||||
// SideMenu
|
||||
//
|
||||
// Created by Jon Kent on 8/29/19.
|
||||
// Copyright © 2019 jonkykong. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
internal protocol SideMenuTransitionControllerDelegate: class {
|
||||
func sideMenuTransitionController(_ transitionController: SideMenuTransitionController, didDismiss viewController: UIViewController)
|
||||
func sideMenuTransitionController(_ transitionController: SideMenuTransitionController, didPresent viewController: UIViewController)
|
||||
}
|
||||
|
||||
internal final class SideMenuTransitionController: NSObject, UIViewControllerTransitioningDelegate {
|
||||
|
||||
typealias Model = MenuModel & AnimationModel & PresentationModel
|
||||
|
||||
private let leftSide: Bool
|
||||
private let config: Model
|
||||
private var animationController: SideMenuAnimationController?
|
||||
private weak var interactionController: SideMenuInteractionController?
|
||||
|
||||
var interactive: Bool = false
|
||||
weak var delegate: SideMenuTransitionControllerDelegate?
|
||||
|
||||
init(leftSide: Bool, config: Model) {
|
||||
self.leftSide = leftSide
|
||||
self.config = config
|
||||
super.init()
|
||||
}
|
||||
|
||||
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
animationController = SideMenuAnimationController(
|
||||
config: config,
|
||||
leftSide: leftSide,
|
||||
delegate: self)
|
||||
return animationController
|
||||
}
|
||||
|
||||
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||
return animationController
|
||||
}
|
||||
|
||||
func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
return interactionController(using: animator)
|
||||
}
|
||||
|
||||
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
return interactionController(using: animator)
|
||||
}
|
||||
|
||||
internal func handle(state: SideMenuInteractionController.State) {
|
||||
interactionController?.handle(state: state)
|
||||
}
|
||||
|
||||
func layout() {
|
||||
animationController?.layout()
|
||||
}
|
||||
|
||||
func transition(presenting: Bool, animated: Bool = true, interactive: Bool = false, alongsideTransition: (() -> Void)? = nil, complete: Bool = true, completion: ((Bool) -> Void)? = nil) {
|
||||
animationController?.transition(
|
||||
presenting: presenting,
|
||||
animated: animated,
|
||||
interactive: interactive,
|
||||
alongsideTransition: alongsideTransition,
|
||||
complete: complete, completion: completion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension SideMenuTransitionController: SideMenuAnimationControllerDelegate {
|
||||
|
||||
internal func sideMenuAnimationController(_ animationController: SideMenuAnimationController, didDismiss viewController: UIViewController) {
|
||||
delegate?.sideMenuTransitionController(self, didDismiss: viewController)
|
||||
}
|
||||
|
||||
internal func sideMenuAnimationController(_ animationController: SideMenuAnimationController, didPresent viewController: UIViewController) {
|
||||
delegate?.sideMenuTransitionController(self, didPresent: viewController)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SideMenuTransitionController {
|
||||
|
||||
func interactionController(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
|
||||
guard interactive else { return nil }
|
||||
interactive = false
|
||||
let interactionController = SideMenuInteractionController(cancelWhenBackgrounded: config.dismissWhenBackgrounded, completionCurve: config.completionCurve)
|
||||
self.interactionController = interactionController
|
||||
return interactionController
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
//
|
||||
// UISideMenuNavigationController.swift
|
||||
//
|
||||
// Created by Jon Kent on 1/14/16.
|
||||
// Copyright © 2016 Jon Kent. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc public protocol UISideMenuNavigationControllerDelegate: class {
|
||||
func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool)
|
||||
}
|
||||
|
||||
// This makes adherance to the protocol optional:
|
||||
extension UIViewController {
|
||||
func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool) {}
|
||||
func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool) {}
|
||||
func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) {}
|
||||
func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool) {}
|
||||
}
|
||||
|
||||
open class UISideMenuNavigationController: UINavigationController {
|
||||
|
||||
fileprivate weak var foundDelegate: UISideMenuNavigationControllerDelegate?
|
||||
fileprivate weak var activeDelegate: UISideMenuNavigationControllerDelegate? {
|
||||
get {
|
||||
guard !view.isHidden else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sideMenuDelegate ?? foundDelegate ?? findDelegate(forViewController: presentingViewController)
|
||||
}
|
||||
}
|
||||
fileprivate func findDelegate(forViewController: UIViewController?) -> UISideMenuNavigationControllerDelegate? {
|
||||
if let navigationController = forViewController as? UINavigationController {
|
||||
return findDelegate(forViewController: navigationController.topViewController)
|
||||
}
|
||||
if let tabBarController = forViewController as? UITabBarController {
|
||||
return findDelegate(forViewController: tabBarController.selectedViewController)
|
||||
}
|
||||
if let splitViewController = forViewController as? UISplitViewController {
|
||||
return findDelegate(forViewController: splitViewController.viewControllers.last)
|
||||
}
|
||||
|
||||
foundDelegate = forViewController as? UISideMenuNavigationControllerDelegate
|
||||
return foundDelegate
|
||||
}
|
||||
fileprivate var usingInterfaceBuilder = false
|
||||
internal var locked = false
|
||||
internal var originalMenuBackgroundColor: UIColor?
|
||||
internal var transition: SideMenuTransition {
|
||||
get {
|
||||
return sideMenuManager.transition
|
||||
}
|
||||
}
|
||||
|
||||
/// Delegate for receiving appear and disappear related events. If `nil` the visible view controller that displays a `UISideMenuNavigationController` automatically receives these events.
|
||||
weak var sideMenuDelegate: UISideMenuNavigationControllerDelegate?
|
||||
|
||||
/// SideMenuManager instance associated with this menu. Default is `SideMenuManager.default`. This property cannot be changed after the menu has loaded.
|
||||
open weak var sideMenuManager: SideMenuManager! = SideMenuManager.default {
|
||||
didSet {
|
||||
if locked && oldValue != nil {
|
||||
print("SideMenu Warning: a menu's sideMenuManager property cannot be changed after it has loaded.")
|
||||
sideMenuManager = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `sideMenuManager.menuWidth` is used. This property cannot be changed while the isHidden property is false.
|
||||
@IBInspectable open var menuWidth: CGFloat = 0 {
|
||||
didSet {
|
||||
if !isHidden && oldValue != menuWidth {
|
||||
print("SideMenu Warning: a menu's width property can only be changed when it is hidden.")
|
||||
menuWidth = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
|
||||
@IBInspectable open var leftSide: Bool = false {
|
||||
didSet {
|
||||
if locked && leftSide != oldValue {
|
||||
print("SideMenu Warning: a menu's leftSide property cannot be changed after it has loaded.")
|
||||
leftSide = oldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller.
|
||||
open var isHidden: Bool {
|
||||
get {
|
||||
return self.presentingViewController == nil
|
||||
}
|
||||
}
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
// This override prevents newbie developers from creating black/blank menus and opening newbie issues.
|
||||
// If you would like to remove this override, define STFU_SIDEMENU in the Active Compilation Conditions of your .plist file.
|
||||
// Sorry for the inconvenience experienced developers :(
|
||||
@available(*, unavailable, renamed: "init(rootViewController:)")
|
||||
public init() {
|
||||
fatalError("init is not available")
|
||||
}
|
||||
|
||||
public override init(rootViewController: UIViewController) {
|
||||
super.init(rootViewController: rootViewController)
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
#endif
|
||||
|
||||
open override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
usingInterfaceBuilder = true
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
if !locked && usingInterfaceBuilder {
|
||||
if leftSide {
|
||||
sideMenuManager.menuLeftNavigationController = self
|
||||
} else {
|
||||
sideMenuManager.menuRightNavigationController = self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Dismiss keyboard to prevent weird keyboard animations from occurring during transition
|
||||
presentingViewController?.view.endEditing(true)
|
||||
|
||||
foundDelegate = nil
|
||||
activeDelegate?.sideMenuWillAppear(menu: self, animated: animated)
|
||||
}
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// We had presented a view before, so lets dismiss ourselves as already acted upon
|
||||
if view.isHidden {
|
||||
transition.hideMenuComplete()
|
||||
dismiss(animated: false, completion: { () -> Void in
|
||||
self.view.isHidden = false
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuDidAppear(menu: self, animated: animated)
|
||||
|
||||
#if !STFU_SIDEMENU
|
||||
if topViewController == nil {
|
||||
print("SideMenu Warning: the menu doesn't have a view controller to show! UISideMenuNavigationController needs a view controller to display just like a UINavigationController.")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
override open func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
|
||||
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
|
||||
if !isBeingDismissed {
|
||||
guard let sideMenuManager = sideMenuManager else {
|
||||
return
|
||||
}
|
||||
|
||||
if let mainView = transition.mainViewController?.view {
|
||||
switch sideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
mainView.superview?.insertSubview(view, belowSubview: mainView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
if let tapView = transition.tapView {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: tapView)
|
||||
} else {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: mainView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
|
||||
UIView.animate(withDuration: animated ? sideMenuManager.menuAnimationDismissDuration : 0,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
self.transition.hideMenuStart()
|
||||
self.activeDelegate?.sideMenuWillDisappear(menu: self, animated: animated)
|
||||
}) { (finished) -> Void in
|
||||
self.activeDelegate?.sideMenuDidDisappear(menu: self, animated: animated)
|
||||
self.view.isHidden = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuWillDisappear(menu: self, animated: animated)
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
// Work-around: if the menu is dismissed without animation the transition logic is never called to restore the
|
||||
// the view hierarchy leaving the screen black/empty. This is because the transition moves views within a container
|
||||
// view, but dismissing without animation removes the container view before the original hierarchy is restored.
|
||||
// This check corrects that.
|
||||
if let sideMenuDelegate = activeDelegate as? UIViewController, sideMenuDelegate.view.window == nil {
|
||||
transition.hideMenuStart().hideMenuComplete()
|
||||
}
|
||||
|
||||
activeDelegate?.sideMenuDidDisappear(menu: self, animated: animated)
|
||||
|
||||
// Clear selecton on UITableViewControllers when reappearing using custom transitions
|
||||
guard let tableViewController = topViewController as? UITableViewController,
|
||||
let tableView = tableViewController.tableView,
|
||||
let indexPaths = tableView.indexPathsForSelectedRows,
|
||||
tableViewController.clearsSelectionOnViewWillAppear else {
|
||||
return
|
||||
}
|
||||
|
||||
for indexPath in indexPaths {
|
||||
tableView.deselectRow(at: indexPath, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
// Don't bother resizing if the view isn't visible
|
||||
guard !view.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
NotificationCenter.default.removeObserver(self.transition, name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
coordinator.animate(alongsideTransition: { (context) in
|
||||
self.transition.presentMenuStart()
|
||||
}) { (context) in
|
||||
NotificationCenter.default.addObserver(self.transition, selector:#selector(SideMenuTransition.handleNotification), name: NSNotification.Name.UIApplicationWillChangeStatusBarFrame, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
|
||||
guard let sideMenuManager = sideMenuManager, viewControllers.count > 0 && sideMenuManager.menuPushStyle != .subMenu else {
|
||||
// NOTE: pushViewController is called by init(rootViewController: UIViewController)
|
||||
// so we must perform the normal super method in this case.
|
||||
super.pushViewController(viewController, animated: animated)
|
||||
return
|
||||
}
|
||||
|
||||
let splitViewController = presentingViewController as? UISplitViewController
|
||||
let tabBarController = presentingViewController as? UITabBarController
|
||||
let potentialNavigationController = (splitViewController?.viewControllers.first ?? tabBarController?.selectedViewController) ?? presentingViewController
|
||||
guard let navigationController = potentialNavigationController as? UINavigationController else {
|
||||
print("SideMenu Warning: attempt to push a View Controller from \(String(describing: potentialNavigationController.self)) where its navigationController == nil. It must be embedded in a Navigation Controller for this to work.")
|
||||
return
|
||||
}
|
||||
|
||||
let activeDelegate = self.activeDelegate
|
||||
foundDelegate = nil
|
||||
|
||||
// To avoid overlapping dismiss & pop/push calls, create a transaction block where the menu
|
||||
// is dismissed after showing the appropriate screen
|
||||
CATransaction.begin()
|
||||
if sideMenuManager.menuDismissOnPush {
|
||||
let animated = animated || sideMenuManager.menuAlwaysAnimate
|
||||
|
||||
CATransaction.setCompletionBlock( { () -> Void in
|
||||
activeDelegate?.sideMenuDidDisappear(menu: self, animated: animated)
|
||||
if !animated {
|
||||
self.transition.hideMenuStart().hideMenuComplete()
|
||||
}
|
||||
self.dismiss(animated: animated, completion: nil)
|
||||
})
|
||||
|
||||
if animated {
|
||||
let areAnimationsEnabled = UIView.areAnimationsEnabled
|
||||
UIView.setAnimationsEnabled(true)
|
||||
UIView.animate(withDuration: sideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: sideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: sideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: sideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
activeDelegate?.sideMenuWillDisappear(menu: self, animated: animated)
|
||||
self.transition.hideMenuStart()
|
||||
})
|
||||
UIView.setAnimationsEnabled(areAnimationsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
if let lastViewController = navigationController.viewControllers.last, !sideMenuManager.menuAllowPushOfSameClassTwice && type(of: lastViewController) == type(of: viewController) {
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
|
||||
switch sideMenuManager.menuPushStyle {
|
||||
case .subMenu, .defaultBehavior: break // .subMenu handled earlier, .defaultBehavior falls through to end
|
||||
case .popWhenPossible:
|
||||
for subViewController in navigationController.viewControllers.reversed() {
|
||||
if type(of: subViewController) == type(of: viewController) {
|
||||
navigationController.popToViewController(subViewController, animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
}
|
||||
case .preserve, .preserveAndHideBackButton:
|
||||
var viewControllers = navigationController.viewControllers
|
||||
let filtered = viewControllers.filter { preservedViewController in type(of: preservedViewController) == type(of: viewController) }
|
||||
if let preservedViewController = filtered.last {
|
||||
viewControllers = viewControllers.filter { subViewController in subViewController !== preservedViewController }
|
||||
if sideMenuManager.menuPushStyle == .preserveAndHideBackButton {
|
||||
preservedViewController.navigationItem.hidesBackButton = true
|
||||
}
|
||||
viewControllers.append(preservedViewController)
|
||||
navigationController.setViewControllers(viewControllers, animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
if sideMenuManager.menuPushStyle == .preserveAndHideBackButton {
|
||||
viewController.navigationItem.hidesBackButton = true
|
||||
}
|
||||
case .replace:
|
||||
viewController.navigationItem.hidesBackButton = true
|
||||
navigationController.setViewControllers([viewController], animated: animated)
|
||||
CATransaction.commit()
|
||||
return
|
||||
}
|
||||
|
||||
navigationController.pushViewController(viewController, animated: animated)
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,17 +10,17 @@ import UIKit
|
||||
|
||||
open class UITableViewVibrantCell: UITableViewCell {
|
||||
|
||||
fileprivate var vibrancyView:UIVisualEffectView = UIVisualEffectView()
|
||||
fileprivate var vibrancySelectedBackgroundView:UIVisualEffectView = UIVisualEffectView()
|
||||
fileprivate var defaultSelectedBackgroundView:UIView?
|
||||
open var blurEffectStyle: UIBlurEffectStyle? {
|
||||
private var vibrancyView: UIVisualEffectView = UIVisualEffectView()
|
||||
private var vibrancySelectedBackgroundView: UIVisualEffectView = UIVisualEffectView()
|
||||
private var defaultSelectedBackgroundView: UIView?
|
||||
open var blurEffectStyle: UIBlurEffect.Style? {
|
||||
didSet {
|
||||
updateBlur()
|
||||
}
|
||||
}
|
||||
|
||||
// For registering with UITableView without subclassing otherwise dequeuing instance of the cell causes an exception
|
||||
public override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ open class UITableViewVibrantCell: UITableViewCell {
|
||||
// shouldn't be needed but backgroundColor is set to white on iPad:
|
||||
backgroundColor = UIColor.clear
|
||||
|
||||
if let blurEffectStyle = blurEffectStyle, !UIAccessibilityIsReduceTransparencyEnabled() {
|
||||
if let blurEffectStyle = blurEffectStyle, !UIAccessibility.isReduceTransparencyEnabled {
|
||||
let blurEffect = UIBlurEffect(style: blurEffectStyle)
|
||||
vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
use_frameworks!
|
||||
platform :ios, '10.0'
|
||||
|
||||
target 'Example' do
|
||||
pod "SideMenu", :path => "."
|
||||
|
||||
target 'ExampleTests'
|
||||
end
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
PODS:
|
||||
- SideMenu (2.0.5)
|
||||
- SideMenu (6.4.9)
|
||||
|
||||
DEPENDENCIES:
|
||||
- SideMenu (from `.`)
|
||||
@@ -9,8 +9,8 @@ EXTERNAL SOURCES:
|
||||
:path: "."
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
SideMenu: 0ecfd407b24e7d36c57fc50ca7f5d7cedb7c8841
|
||||
SideMenu: 8ef57a3cfc024a2d3fc1c036c7fe98537baec9e0
|
||||
|
||||
PODFILE CHECKSUM: 58fed701dc13a7835ed36507e7cf19fa22035003
|
||||
PODFILE CHECKSUM: 863f183ea1ab6f64dc8553590349c586faf8e4a1
|
||||
|
||||
COCOAPODS: 1.1.1
|
||||
COCOAPODS: 1.9.3
|
||||
|
||||
+6
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "SideMenu",
|
||||
"version": "2.0.5",
|
||||
"version": "6.4.9",
|
||||
"summary": "Simple side menu control for iOS in Swift inspired by Facebook. Right and Left sides. No coding required.",
|
||||
"description": "SideMenu is a simple and versatile side menu control. It's highly customizable, but can also be implemented in storyboard without a single line of code. The are three standard animation styles to choose from along with several other options for further customization if desired. Just type SideMenuManager.menu... and code completion will show you everything you can customize.",
|
||||
"homepage": "https://github.com/jonkykong/SideMenu",
|
||||
@@ -19,10 +19,12 @@
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/jonkykong/SideMenu.git",
|
||||
"tag": "2.0.5"
|
||||
"tag": "6.4.9"
|
||||
},
|
||||
"platforms": {
|
||||
"ios": "8.0"
|
||||
"ios": "10.0"
|
||||
},
|
||||
"source_files": "Pod/Classes/**/*"
|
||||
"swift_versions": "5.0",
|
||||
"source_files": "Pod/Classes/**/*",
|
||||
"swift_version": "5.0"
|
||||
}
|
||||
|
||||
Generated
+4
-4
@@ -1,5 +1,5 @@
|
||||
PODS:
|
||||
- SideMenu (2.0.5)
|
||||
- SideMenu (6.4.9)
|
||||
|
||||
DEPENDENCIES:
|
||||
- SideMenu (from `.`)
|
||||
@@ -9,8 +9,8 @@ EXTERNAL SOURCES:
|
||||
:path: "."
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
SideMenu: 0ecfd407b24e7d36c57fc50ca7f5d7cedb7c8841
|
||||
SideMenu: 8ef57a3cfc024a2d3fc1c036c7fe98537baec9e0
|
||||
|
||||
PODFILE CHECKSUM: 58fed701dc13a7835ed36507e7cf19fa22035003
|
||||
PODFILE CHECKSUM: 863f183ea1ab6f64dc8553590349c586faf8e4a1
|
||||
|
||||
COCOAPODS: 1.1.1
|
||||
COCOAPODS: 1.9.3
|
||||
|
||||
Generated
+399
-498
File diff suppressed because it is too large
Load Diff
-26
@@ -1,26 +0,0 @@
|
||||
# Acknowledgements
|
||||
This application makes use of the following third party libraries:
|
||||
|
||||
## SideMenu
|
||||
|
||||
Copyright (c) 2015 Jonathan Kent <contact@jonkent.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Generated by CocoaPods - https://cocoapods.org
|
||||
Pods/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-acknowledgements.plist
Generated
-58
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreferenceSpecifiers</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>This application makes use of the following third party libraries:</string>
|
||||
<key>Title</key>
|
||||
<string>Acknowledgements</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2015 Jonathan Kent <contact@jonkent.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>MIT</string>
|
||||
<key>Title</key>
|
||||
<string>SideMenu</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Generated by CocoaPods - https://cocoapods.org</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>StringsTable</key>
|
||||
<string>Acknowledgements</string>
|
||||
<key>Title</key>
|
||||
<string>Acknowledgements</string>
|
||||
</dict>
|
||||
</plist>
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_Pods_Example_ExampleTests : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_Pods_Example_ExampleTests
|
||||
@end
|
||||
Generated
-91
@@ -1,91 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
|
||||
|
||||
install_framework()
|
||||
{
|
||||
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
|
||||
local source="${BUILT_PRODUCTS_DIR}/$1"
|
||||
elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
|
||||
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
|
||||
elif [ -r "$1" ]; then
|
||||
local source="$1"
|
||||
fi
|
||||
|
||||
local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
if [ -L "${source}" ]; then
|
||||
echo "Symlinked..."
|
||||
source="$(readlink "${source}")"
|
||||
fi
|
||||
|
||||
# use filter instead of exclude so missing patterns dont' throw errors
|
||||
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
|
||||
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
|
||||
|
||||
local basename
|
||||
basename="$(basename -s .framework "$1")"
|
||||
binary="${destination}/${basename}.framework/${basename}"
|
||||
if ! [ -r "$binary" ]; then
|
||||
binary="${destination}/${basename}"
|
||||
fi
|
||||
|
||||
# Strip invalid architectures so "fat" simulator / device frameworks work on device
|
||||
if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
|
||||
strip_invalid_archs "$binary"
|
||||
fi
|
||||
|
||||
# Resign the code if required by the build settings to avoid unstable apps
|
||||
code_sign_if_enabled "${destination}/$(basename "$1")"
|
||||
|
||||
# Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
|
||||
if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
|
||||
local swift_runtime_libs
|
||||
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
|
||||
for lib in $swift_runtime_libs; do
|
||||
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
|
||||
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
|
||||
code_sign_if_enabled "${destination}/${lib}"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Signs a framework with the provided identity
|
||||
code_sign_if_enabled() {
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
# Use the current code_sign_identitiy
|
||||
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
||||
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\""
|
||||
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Strip invalid architectures
|
||||
strip_invalid_archs() {
|
||||
binary="$1"
|
||||
# Get architectures for current file
|
||||
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
|
||||
stripped=""
|
||||
for arch in $archs; do
|
||||
if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
|
||||
# Strip non-valid architectures in-place
|
||||
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
|
||||
stripped="$stripped $arch"
|
||||
fi
|
||||
done
|
||||
if [[ "$stripped" ]]; then
|
||||
echo "Stripped $binary of architectures:$stripped"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "$BUILT_PRODUCTS_DIR/SideMenu/SideMenu.framework"
|
||||
fi
|
||||
if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "$BUILT_PRODUCTS_DIR/SideMenu/SideMenu.framework"
|
||||
fi
|
||||
Generated
-96
@@ -1,96 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
|
||||
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
|
||||
> "$RESOURCES_TO_COPY"
|
||||
|
||||
XCASSET_FILES=()
|
||||
|
||||
case "${TARGETED_DEVICE_FAMILY}" in
|
||||
1,2)
|
||||
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
|
||||
;;
|
||||
1)
|
||||
TARGET_DEVICE_ARGS="--target-device iphone"
|
||||
;;
|
||||
2)
|
||||
TARGET_DEVICE_ARGS="--target-device ipad"
|
||||
;;
|
||||
*)
|
||||
TARGET_DEVICE_ARGS="--target-device mac"
|
||||
;;
|
||||
esac
|
||||
|
||||
install_resource()
|
||||
{
|
||||
if [[ "$1" = /* ]] ; then
|
||||
RESOURCE_PATH="$1"
|
||||
else
|
||||
RESOURCE_PATH="${PODS_ROOT}/$1"
|
||||
fi
|
||||
if [[ ! -e "$RESOURCE_PATH" ]] ; then
|
||||
cat << EOM
|
||||
error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
|
||||
EOM
|
||||
exit 1
|
||||
fi
|
||||
case $RESOURCE_PATH in
|
||||
*.storyboard)
|
||||
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
|
||||
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
|
||||
;;
|
||||
*.xib)
|
||||
echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
|
||||
ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
|
||||
;;
|
||||
*.framework)
|
||||
echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
;;
|
||||
*.xcdatamodel)
|
||||
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
|
||||
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
|
||||
;;
|
||||
*.xcdatamodeld)
|
||||
echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
|
||||
xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
|
||||
;;
|
||||
*.xcmappingmodel)
|
||||
echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
|
||||
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
|
||||
;;
|
||||
*.xcassets)
|
||||
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
|
||||
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
|
||||
;;
|
||||
*)
|
||||
echo "$RESOURCE_PATH"
|
||||
echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
|
||||
mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
fi
|
||||
rm -f "$RESOURCES_TO_COPY"
|
||||
|
||||
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
|
||||
then
|
||||
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
|
||||
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
|
||||
while read line; do
|
||||
if [[ $line != "${PODS_ROOT}*" ]]; then
|
||||
XCASSET_FILES+=("$line")
|
||||
fi
|
||||
done <<<"$OTHER_XCASSETS"
|
||||
|
||||
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||
fi
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
|
||||
FOUNDATION_EXPORT double Pods_Example_ExampleTestsVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char Pods_Example_ExampleTestsVersionString[];
|
||||
|
||||
Generated
-11
@@ -1,11 +0,0 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SideMenu"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SideMenu/SideMenu.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SideMenu"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
framework module Pods_Example_ExampleTests {
|
||||
umbrella header "Pods-Example-ExampleTests-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
Generated
-11
@@ -1,11 +0,0 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SideMenu"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SideMenu/SideMenu.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SideMenu"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
+133
-17
@@ -1,11 +1,33 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
function on_error {
|
||||
echo "$(realpath -mq "${0}"):$1: error: Unexpected failure"
|
||||
}
|
||||
trap 'on_error $LINENO' ERR
|
||||
|
||||
if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then
|
||||
# If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy
|
||||
# frameworks to, so exit 0 (signalling the script phase was successful).
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
|
||||
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
|
||||
|
||||
# Used as a return value for each invocation of `strip_invalid_archs` function.
|
||||
STRIP_BINARY_RETVAL=0
|
||||
|
||||
# This protects against multiple targets copying the same framework dependency at the same time. The solution
|
||||
# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
|
||||
RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
|
||||
|
||||
# Copies and strips a vendored framework
|
||||
install_framework()
|
||||
{
|
||||
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
|
||||
@@ -19,19 +41,24 @@ install_framework()
|
||||
local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
|
||||
|
||||
if [ -L "${source}" ]; then
|
||||
echo "Symlinked..."
|
||||
source="$(readlink "${source}")"
|
||||
echo "Symlinked..."
|
||||
source="$(readlink "${source}")"
|
||||
fi
|
||||
|
||||
# use filter instead of exclude so missing patterns dont' throw errors
|
||||
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
|
||||
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
|
||||
# Use filter instead of exclude so missing patterns don't throw errors.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
|
||||
|
||||
local basename
|
||||
basename="$(basename -s .framework "$1")"
|
||||
binary="${destination}/${basename}.framework/${basename}"
|
||||
|
||||
if ! [ -r "$binary" ]; then
|
||||
binary="${destination}/${basename}"
|
||||
elif [ -L "${binary}" ]; then
|
||||
echo "Destination binary is symlinked..."
|
||||
dirname="$(dirname "${binary}")"
|
||||
binary="${dirname}/$(readlink "${binary}")"
|
||||
fi
|
||||
|
||||
# Strip invalid architectures so "fat" simulator / device frameworks work on device
|
||||
@@ -45,7 +72,7 @@ install_framework()
|
||||
# Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
|
||||
if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
|
||||
local swift_runtime_libs
|
||||
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
|
||||
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u)
|
||||
for lib in $swift_runtime_libs; do
|
||||
echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
|
||||
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
|
||||
@@ -54,38 +81,127 @@ install_framework()
|
||||
fi
|
||||
}
|
||||
|
||||
# Copies and strips a vendored dSYM
|
||||
install_dsym() {
|
||||
local source="$1"
|
||||
warn_missing_arch=${2:-true}
|
||||
if [ -r "$source" ]; then
|
||||
# Copy the dSYM into the targets temp dir.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}"
|
||||
|
||||
local basename
|
||||
basename="$(basename -s .dSYM "$source")"
|
||||
binary_name="$(ls "$source/Contents/Resources/DWARF")"
|
||||
binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}"
|
||||
|
||||
# Strip invalid architectures so "fat" simulator / device frameworks work on device
|
||||
if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then
|
||||
strip_invalid_archs "$binary" "$warn_missing_arch"
|
||||
fi
|
||||
|
||||
if [[ $STRIP_BINARY_RETVAL == 1 ]]; then
|
||||
# Move the stripped file into its final destination.
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
|
||||
else
|
||||
# The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
|
||||
touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Copies the bcsymbolmap files of a vendored framework
|
||||
install_bcsymbolmap() {
|
||||
local bcsymbolmap_path="$1"
|
||||
local destination="${BUILT_PRODUCTS_DIR}"
|
||||
echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}""
|
||||
rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"
|
||||
}
|
||||
|
||||
# Signs a framework with the provided identity
|
||||
code_sign_if_enabled() {
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
# Use the current code_sign_identitiy
|
||||
if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
|
||||
# Use the current code_sign_identity
|
||||
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
|
||||
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\""
|
||||
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1"
|
||||
local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'"
|
||||
|
||||
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
|
||||
code_sign_cmd="$code_sign_cmd &"
|
||||
fi
|
||||
echo "$code_sign_cmd"
|
||||
eval "$code_sign_cmd"
|
||||
fi
|
||||
}
|
||||
|
||||
# Strip invalid architectures
|
||||
strip_invalid_archs() {
|
||||
binary="$1"
|
||||
# Get architectures for current file
|
||||
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
|
||||
warn_missing_arch=${2:-true}
|
||||
# Get architectures for current target binary
|
||||
binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)"
|
||||
# Intersect them with the architectures we are building for
|
||||
intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)"
|
||||
# If there are no archs supported by this binary then warn the user
|
||||
if [[ -z "$intersected_archs" ]]; then
|
||||
if [[ "$warn_missing_arch" == "true" ]]; then
|
||||
echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)."
|
||||
fi
|
||||
STRIP_BINARY_RETVAL=0
|
||||
return
|
||||
fi
|
||||
stripped=""
|
||||
for arch in $archs; do
|
||||
if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
|
||||
for arch in $binary_archs; do
|
||||
if ! [[ "${ARCHS}" == *"$arch"* ]]; then
|
||||
# Strip non-valid architectures in-place
|
||||
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
|
||||
lipo -remove "$arch" -output "$binary" "$binary"
|
||||
stripped="$stripped $arch"
|
||||
fi
|
||||
done
|
||||
if [[ "$stripped" ]]; then
|
||||
echo "Stripped $binary of architectures:$stripped"
|
||||
fi
|
||||
STRIP_BINARY_RETVAL=1
|
||||
}
|
||||
|
||||
install_artifact() {
|
||||
artifact="$1"
|
||||
base="$(basename "$artifact")"
|
||||
case $base in
|
||||
*.framework)
|
||||
install_framework "$artifact"
|
||||
;;
|
||||
*.dSYM)
|
||||
# Suppress arch warnings since XCFrameworks will include many dSYM files
|
||||
install_dsym "$artifact" "false"
|
||||
;;
|
||||
*.bcsymbolmap)
|
||||
install_bcsymbolmap "$artifact"
|
||||
;;
|
||||
*)
|
||||
echo "error: Unrecognized artifact "$artifact""
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
copy_artifacts() {
|
||||
file_list="$1"
|
||||
while read artifact; do
|
||||
install_artifact "$artifact"
|
||||
done <$file_list
|
||||
}
|
||||
|
||||
ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt"
|
||||
if [ -r "${ARTIFACT_LIST_FILE}" ]; then
|
||||
copy_artifacts "${ARTIFACT_LIST_FILE}"
|
||||
fi
|
||||
|
||||
if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "$BUILT_PRODUCTS_DIR/SideMenu/SideMenu.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework"
|
||||
fi
|
||||
if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "$BUILT_PRODUCTS_DIR/SideMenu/SideMenu.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework"
|
||||
fi
|
||||
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
|
||||
wait
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SideMenu"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu/SideMenu.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SideMenu/SideMenu.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SideMenu"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SideMenu"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/SideMenu/SideMenu.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SideMenu/SideMenu.framework/Headers"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "SideMenu"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
PODS_ROOT = ${SRCROOT}/Pods
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>6.4.9</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,4 +1,12 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+6
-5
@@ -1,9 +1,10 @@
|
||||
CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SideMenu
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SideMenu
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_BUILD_DIR = $BUILD_DIR
|
||||
PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/..
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
|
||||
@@ -1,22 +1,42 @@
|
||||
# ▤ SideMenu
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](https://circleci.com/gh/jonkykong/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
|
||||
### If you like SideMenu, give it a ★ at the top right of its [GitHub](https://github.com/jonkykong/SideMenu) page.
|
||||
#### Using SideMenu in your app? [Send](mailto:yo@massappeal.co?subject=SideMenu%20in%20action!) me a link to your app in the app store!
|
||||
### If you like SideMenu, give it a ★ at the top right of this page.
|
||||
#### SideMenu needs your help! If you're a skilled iOS developer and want to help maintain this repository and answer issues asked by the community, please [send me an email](mailto:yo@massappeal.co?subject=I%20Want%20To%20Help!).
|
||||
|
||||
> Hi, I'm Jon Kent and I am an iOS designer, developer, and mobile strategist. I love coffee and play the drums.
|
||||
> * [**Hire me**](mailto:yo@massappeal.co?subject=Let's%20build%20something%20amazing) to help you make cool stuff. *Note: If you're having a problem with SideMenu, please open an [issue](https://github.com/jonkykong/SideMenu/issues/new) and do not email me.*
|
||||
> * Check out my [website](http://massappeal.co) to see some of my other projects.
|
||||
> * Building and maintaining this free library takes time. Help keep me awake and buy me a coffee ☕️ via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=contact%40jonkent%2eme&lc=US¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted).
|
||||
> * Building and maintaining this **free** library takes a lot of my time and **saves you time**. Please consider paying it forward by supporting me with a small amount to my [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=contact%40jonkent%2eme&lc=US¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). (only **13** people have donated since 12/23/15 but **thank you** to those who have!)
|
||||
|
||||
* **[Overview](#overview)**
|
||||
* [Preview Samples](#preview-samples)
|
||||
* **[Requirements](#requirements)**
|
||||
* **[Installation](#installation)**
|
||||
* [CocoaPods](#cocoapods)
|
||||
* [Carthage](#carthage)
|
||||
* [Swift Package Manager](#swift-package-manager)
|
||||
* **[Usage](#usage)**
|
||||
* [Code-less Storyboard Implementation](#code-less-storyboard-implementation)
|
||||
* [Code Implementation](#code-implementation)
|
||||
* **[Customization](#customization)**
|
||||
* [SideMenuManager](#sidemenumanager)
|
||||
* [SideMenuNavigationController](#sidemenunavigationcontroller)
|
||||
* [SideMenuNavigationControllerDelegate](#sidemenunavigationcontrollerdelegate)
|
||||
* [Advanced](#advanced)
|
||||
* [Known Issues](#known-issues)
|
||||
* [Thank You](#thank-you)
|
||||
* [License](#license)
|
||||
|
||||
## Overview
|
||||
|
||||
SideMenu is a simple and versatile side menu control written in Swift.
|
||||
- [x] **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
|
||||
- [x] Four standard animation styles to choose from (there's even a parallax effect if you want to get weird).
|
||||
- [x] Eight standard animation styles to choose from (there's even a parallax effect if you want to get weird).
|
||||
- [x] Highly customizable without needing to write tons of custom code.
|
||||
- [x] Supports continuous swiping between side menus on boths sides in a single gesture.
|
||||
- [x] Global menu configuration. Set-up once and be done for all screens.
|
||||
@@ -28,10 +48,12 @@ Check out the example project to see it in action!
|
||||
### Preview Samples
|
||||
| Slide Out | Slide In | Dissolve | Slide In + Out |
|
||||
| --- | --- | --- | --- |
|
||||
|  |  |  |  |
|
||||
|  |  |  |  |
|
||||
|
||||
## Requirements
|
||||
- [x] iOS 8 or higher.
|
||||
- [x] Xcode 11.
|
||||
- [x] Swift 5.
|
||||
- [x] iOS 10 or higher.
|
||||
|
||||
## Installation
|
||||
### CocoaPods
|
||||
@@ -46,13 +68,16 @@ To integrate SideMenu into your Xcode project using CocoaPods, specify it in you
|
||||
|
||||
```ruby
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
platform :ios, '10.0'
|
||||
use_frameworks!
|
||||
|
||||
pod 'SideMenu'
|
||||
|
||||
# For Swift 3 (no longer maintained), use:
|
||||
# pod 'SideMenu', '~> 2.3.4'
|
||||
# For Swift 5 use:
|
||||
# pod 'SideMenu', '~> 6.0'
|
||||
|
||||
# For Swift 4.2 (no longer maintained) use:
|
||||
# pod 'SideMenu', '~> 5.0'
|
||||
```
|
||||
|
||||
Then, run the following command:
|
||||
@@ -78,16 +103,28 @@ To integrate SideMenu into your Xcode project using Carthage, specify it in your
|
||||
github "jonkykong/SideMenu" "master"
|
||||
```
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but SideMenu does support its use on supported platforms.
|
||||
|
||||
Once you have your Swift package set up, adding SideMenu as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/jonkykong/SideMenu.git", from: "6.0.0")
|
||||
]
|
||||
```
|
||||
|
||||
## Usage
|
||||
### Code-less Storyboard Implementation
|
||||
1. Create a Navigation Controller for a side menu. Set the `Custom Class` of the Navigation Controller to be `UISideMenuNavigationController` in the **Identity Inspector**. Set the `Module` to `SideMenu` (ignore this step if you've manually added SideMenu to your project). Create a Root View Controller for the Navigation Controller (shown as a UITableViewController below). Set up any Triggered Segues you want in that view controller.
|
||||

|
||||
1. Create a Navigation Controller for a side menu. Set the `Custom Class` of the Navigation Controller to be `SideMenuNavigationController` in the **Identity Inspector**. Set the `Module` to `SideMenu` (ignore this step if you've manually added SideMenu to your project). Create a Root View Controller for the Navigation Controller (shown as a UITableViewController below). Set up any Triggered Segues you want in that view controller.
|
||||

|
||||
|
||||
2. Set the `Left Side` property of the `UISideMenuNavigationController` to On if you want it to appear from the left side of the screen, or Off/Default if you want it to appear from the right side.
|
||||

|
||||
2. Set the `Left Side` property of the `SideMenuNavigationController` to On if you want it to appear from the left side of the screen, or Off/Default if you want it to appear from the right side.
|
||||

|
||||
|
||||
3. Add a UIButton or UIBarButton to a view controller that you want to display the menu from. Set that button's Triggered Segues action to modally present the Navigation Controller from step 1.
|
||||

|
||||

|
||||
|
||||
That's it. *Note: you can only enable gestures in code.*
|
||||
### Code Implementation
|
||||
@@ -96,218 +133,198 @@ First:
|
||||
import SideMenu
|
||||
```
|
||||
|
||||
In your view controller's `viewDidLoad` event, do something like this (**IMPORTANT: If you're seeing a black menu when you use gestures, read this section carefully!**):
|
||||
From a button, do something like this:
|
||||
``` swift
|
||||
// Define the menu
|
||||
let menu = SideMenuNavigationController(rootViewController: YourViewController)
|
||||
// SideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
|
||||
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
|
||||
// let menu = storyboard!.instantiateViewController(withIdentifier: "RightMenu") as! SideMenuNavigationController
|
||||
present(menu, animated: true, completion: nil)
|
||||
```
|
||||
|
||||
To dismiss a menu programmatically, do something like this:
|
||||
``` swift
|
||||
dismiss(animated: true, completion: nil)
|
||||
```
|
||||
|
||||
To use gestures you have to use the `SideMenuManager`. In your `AppDelegate` do something like this:
|
||||
``` swift
|
||||
// Define the menus
|
||||
let menuLeftNavigationController = UISideMenuNavigationController(rootViewController: YourViewController)
|
||||
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
|
||||
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
|
||||
// let menuLeftNavigationController = storyboard!.instantiateViewController(withIdentifier: "LeftMenuNavigationController") as! UISideMenuNavigationController
|
||||
SideMenuManager.default.menuLeftNavigationController = menuLeftNavigationController
|
||||
let leftMenuNavigationController = SideMenuNavigationController(rootViewController: YourViewController)
|
||||
SideMenuManager.default.leftMenuNavigationController = leftMenuNavigationController
|
||||
|
||||
let menuRightNavigationController = UISideMenuNavigationController(rootViewController: YourViewController)
|
||||
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration
|
||||
// of it here like setting its viewControllers. If you're using storyboards, you'll want to do something like:
|
||||
// let menuRightNavigationController = storyboard!.instantiateViewController(withIdentifier: "RightMenuNavigationController") as! UISideMenuNavigationController
|
||||
SideMenuManager.default.menuRightNavigationController = menuRightNavigationController
|
||||
let rightMenuNavigationController = SideMenuNavigationController(rootViewController: YourViewController)
|
||||
SideMenuManager.default.rightMenuNavigationController = rightMenuNavigationController
|
||||
|
||||
// Enable gestures. The left and/or right menus must be set up above for these to work.
|
||||
// Setup gestures: the left and/or right menus must be set up (above) for these to work.
|
||||
// Note that these continue to work on the Navigation Controller independent of the view controller it displays!
|
||||
SideMenuManager.default.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
```
|
||||
Then from a button, do something like this:
|
||||
``` swift
|
||||
present(SideMenuManager.default.menuLeftNavigationController!, animated: true, completion: nil)
|
||||
SideMenuManager.default.addPanGestureToPresent(toView: self.navigationController!.navigationBar)
|
||||
SideMenuManager.default.addScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
|
||||
|
||||
// Similarly, to dismiss a menu programmatically, you would do this:
|
||||
dismiss(animated: true, completion: nil)
|
||||
// (Optional) Prevent status bar area from turning black when menu appears:
|
||||
leftMenuNavigationController.statusBarEndAlpha = 0
|
||||
// Copy all settings to the other menu
|
||||
rightMenuNavigationController.settings = leftMenuNavigationController.settings
|
||||
```
|
||||
That's it.
|
||||
### Customization
|
||||
#### SideMenuManager
|
||||
Just type ` SideMenuManager.default.menu...` and code completion will show you everything you can customize (defaults are shown below for reference):
|
||||
`SideMenuManager` supports the following:
|
||||
``` swift
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved..
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
open var menuPushStyle: MenuPushStyle = .defaultBehavior
|
||||
|
||||
/**
|
||||
The presentation mode of the menu.
|
||||
|
||||
There are four modes in MenuPresentMode:
|
||||
- menuSlideIn: Menu slides in over of the existing view.
|
||||
- viewSlideOut: The existing view slides out to reveal the menu.
|
||||
- viewSlideInOut: The existing view slides out while the menu slides in.
|
||||
- menuDissolveIn: The menu dissolves in over the existing view controller.
|
||||
*/
|
||||
open var menuPresentMode: MenuPresentMode = .viewSlideOut
|
||||
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
open var menuAllowPushOfSameClassTwice = true
|
||||
|
||||
/**
|
||||
Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width.
|
||||
|
||||
Note that each menu's width can be overridden using the `menuWidth` property on any `UISideMenuNavigationController` instance.
|
||||
*/
|
||||
open var menuWidth: CGFloat = max(round(min((appScreenRect.width), (appScreenRect.height)) * 0.75), 240)
|
||||
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationPresentDuration: Double = 0.35
|
||||
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationDismissDuration: Double = 0.35
|
||||
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
open var menuAnimationCompleteGestureDuration: Double = 0.35
|
||||
|
||||
/// Amount to fade the existing view controller when the menu is presented. Default is 0 for no fade. Set to 1 to fade completely.
|
||||
open var menuAnimationFadeStrength: CGFloat = 0
|
||||
|
||||
/// The amount to scale the existing view controller or the menu view controller depending on the `menuPresentMode`. Default is 1 for no scaling. Less than 1 will shrink, greater than 1 will grow.
|
||||
open var menuAnimationTransformScaleFactor: CGFloat = 1
|
||||
|
||||
/// The background color behind menu animations. Depending on the animation settings this may not be visible. If `menuFadeStatusBar` is true, this color is used to fade it. Default is black.
|
||||
open var menuAnimationBackgroundColor: UIColor?
|
||||
|
||||
/// The shadow opacity around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 0.5 for 50% opacity.
|
||||
open var menuShadowOpacity: Float = 0.5
|
||||
|
||||
/// The shadow color around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is black.
|
||||
open var menuShadowColor = UIColor.black
|
||||
|
||||
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
|
||||
open var menuShadowRadius: CGFloat = 5
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
|
||||
open var menuEnableSwipeGestures: Bool = true
|
||||
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. Default is false.
|
||||
open var menuPresentingViewControllerUserInteractionEnabled: Bool = false
|
||||
|
||||
/// The strength of the parallax effect on the existing view controller. Does not apply to `menuPresentMode` when set to `ViewSlideOut`. Default is 0.
|
||||
open var menuParallaxStrength: Int = 0
|
||||
|
||||
/// Draws the `menuAnimationBackgroundColor` behind the status bar. Default is true.
|
||||
open var menuFadeStatusBar = true
|
||||
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationOptions: UIViewAnimationOptions = .curveEaseInOut
|
||||
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationUsingSpringWithDamping: CGFloat = 1
|
||||
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open var menuDismissOnPush = true
|
||||
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
open var menuAlwaysAnimate = false
|
||||
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell and set the `blurEffectStyle` of each cell to SideMenuManager.default.menuBlurEffectStyle.
|
||||
*/
|
||||
open var menuBlurEffectStyle: UIBlurEffectStyle?
|
||||
|
||||
/// The left menu.
|
||||
open var menuLeftNavigationController: UISideMenuNavigationController?
|
||||
|
||||
open var leftMenuNavigationController: SideMenuNavigationController?
|
||||
/// The right menu.
|
||||
open var menuRightNavigationController: UISideMenuNavigationController?
|
||||
|
||||
public var rightMenuNavigationController: SideMenuNavigationController?
|
||||
/**
|
||||
Adds screen edge gestures to a view to present a menu.
|
||||
Adds screen edge gestures for both left and right sides to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add gestures to.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for. If unspecified, gestures will be added for both sides.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddScreenEdgePanGesturesToPresent(toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer]
|
||||
- Parameter toView: The view to add gestures to.
|
||||
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult public func addScreenEdgePanGesturesToPresent(toView view: UIView) -> [UIScreenEdgePanGestureRecognizer]
|
||||
/**
|
||||
Adds a pan edge gesture to a view to present menus.
|
||||
Adds screen edge gestures to a view to present a menu.
|
||||
|
||||
- Parameter toView: The view to add a pan gesture to.
|
||||
- Parameter toView: The view to add gestures to.
|
||||
- Parameter forMenu: The menu (left or right) you want to add a gesture for.
|
||||
|
||||
- Returns: The pan gesture added to `toView`.
|
||||
*/
|
||||
@discardableResult open func menuAddPanGestureToPresent(toView: UIView) -> UIPanGestureRecognizer
|
||||
- Returns: The screen edge gestures added to `toView`.
|
||||
*/
|
||||
@discardableResult public func addScreenEdgePanGesturesToPresent(toView view: UIView, forMenu side: PresentDirection) -> UIScreenEdgePanGestureRecognizer
|
||||
/**
|
||||
Adds a pan edge gesture to a view to present menus.
|
||||
|
||||
- Parameter toView: The view to add a pan gesture to.
|
||||
|
||||
- Returns: The pan gesture added to `toView`.
|
||||
*/
|
||||
@discardableResult public func addPanGestureToPresent(toView view: UIView) -> UIPanGestureRecognizer
|
||||
```
|
||||
#### UISideMenuNavigationController
|
||||
`UISideMenuNavigationController` supports the following customizations and properties:
|
||||
#### SideMenuNavigationController
|
||||
`SideMenuNavigationController` supports the following:
|
||||
``` swift
|
||||
/// SideMenuManager instance associated with this menu. Default is `SideMenuManager.default`. This property cannot be changed after the menu has loaded.
|
||||
open weak var sideMenuManager: SideMenuManager! = SideMenuManager.default
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `sideMenuManager.menuWidth` is used. This property cannot be changed while the isHidden property is false.
|
||||
@IBInspectable open var menuWidth: CGFloat = 0
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
var allowPushOfSameClassTwice: Bool = true
|
||||
/// Forces menus to always animate when appearing or disappearing, regardless of a pushed view controller's animation.
|
||||
var alwaysAnimate: Bool = true
|
||||
/// The animation options when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var animationOptions: UIView.AnimationOptions = .curveEaseInOut
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell.
|
||||
*/
|
||||
var blurEffectStyle: UIBlurEffect.Style? = nil
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
var completeGestureDuration: Double = 0.35
|
||||
/// Animation curve of the remaining animation when the menu is partially dismissed with gestures. Default is .easeIn.
|
||||
var completionCurve: UIView.AnimationCurve = .curveEaseInOut
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
var dismissDuration: Double = 0.35
|
||||
/// Automatically dismisses the menu when another view is presented from it.
|
||||
var dismissOnPresent: Bool = true
|
||||
/// Automatically dismisses the menu when another view controller is pushed from it.
|
||||
var dismissOnPush: Bool = true
|
||||
/// Automatically dismisses the menu when the screen is rotated.
|
||||
var dismissOnRotation: Bool = true
|
||||
/// Automatically dismisses the menu when app goes to the background.
|
||||
var dismissWhenBackgrounded: Bool = true
|
||||
/// Enable or disable a swipe gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
|
||||
var enableSwipeToDismissGesture: Bool = true
|
||||
/// Enable or disable a tap gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
|
||||
var enableTapToDismissGesture: Bool = true
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var initialSpringVelocity: CGFloat = 1
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
|
||||
@IBInspectable open var leftSide: Bool = false
|
||||
var leftSide: Bool = false
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero.
|
||||
var menuWidth: CGFloat = 240
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
var presentDuration: Double = 0.35
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. `presentingViewControllerUseSnapshot` must also set to false. Default is false.
|
||||
var presentingViewControllerUserInteractionEnabled: Bool = false
|
||||
/// Use a snapshot for the presenting vierw controller while the menu is displayed. Useful when layout changes occur during transitions. Not recommended for apps that support rotation. Default is false.
|
||||
var presentingViewControllerUseSnapshot: Bool = false
|
||||
/// The presentation style of the menu.
|
||||
var presentationStyle: SideMenuPresentStyle = .viewSlideOut
|
||||
/**
|
||||
The push style of the menu.
|
||||
|
||||
There are six modes in MenuPushStyle:
|
||||
- defaultBehavior: The view controller is pushed onto the stack.
|
||||
- popWhenPossible: If a view controller already in the stack is of the same class as the pushed view controller, the stack is instead popped back to the existing view controller. This behavior can help users from getting lost in a deep navigation stack.
|
||||
- preserve: If a view controller already in the stack is of the same class as the pushed view controller, the existing view controller is pushed to the end of the stack. This behavior is similar to a UITabBarController.
|
||||
- preserveAndHideBackButton: Same as .preserve and back buttons are automatically hidden.
|
||||
- replace: Any existing view controllers are released from the stack and replaced with the pushed view controller. Back buttons are automatically hidden. This behavior is ideal if view controllers require a lot of memory or their state doesn't need to be preserved..
|
||||
- subMenu: Unlike all other behaviors that push using the menu's presentingViewController, this behavior pushes view controllers within the menu. Use this behavior if you want to display a sub menu.
|
||||
*/
|
||||
var pushStyle: MenuPushStyle = .default
|
||||
/// Draws `presentationStyle.backgroundColor` behind the status bar. Default is 0.
|
||||
var statusBarEndAlpha: CGFloat = 0
|
||||
/// The animation spring damping when a menu is displayed. Ignored when displayed with a gesture.
|
||||
var usingSpringWithDamping: CGFloat = 1
|
||||
/// Indicates if the menu is anywhere in the view hierarchy, even if covered by another view controller.
|
||||
open var isHidden: Bool
|
||||
var isHidden: Bool
|
||||
```
|
||||
#### UISideMenuNavigationControllerDelegate
|
||||
To receive notifications when a menu is displayed from a view controller, have it adhere to the `UISideMenuNavigationControllerDelegate` protocol:
|
||||
#### SideMenuPresentStyle
|
||||
There are 8 pre-defined `SideMenuPresentStyle` options:
|
||||
``` swift
|
||||
extension MyViewController: UISideMenuNavigationControllerDelegate {
|
||||
/// Menu slides in over the existing view.
|
||||
static let menuSlideIn: SideMenuPresentStyle
|
||||
/// The existing view slides out to reveal the menu underneath.
|
||||
static let viewSlideOut: SideMenuPresentStyle
|
||||
/// The existing view slides out while the menu slides in.
|
||||
static let viewSlideOutMenuIn: SideMenuPresentStyle
|
||||
/// The menu dissolves in over the existing view.
|
||||
static let menuDissolveIn: SideMenuPresentStyle
|
||||
/// The existing view slides out while the menu partially slides in.
|
||||
static let viewSlideOutMenuPartialIn: SideMenuPresentStyle
|
||||
/// The existing view slides out while the menu slides out from under it.
|
||||
static let viewSlideOutMenuOut: SideMenuPresentStyle
|
||||
/// The existing view slides out while the menu partially slides out from under it.
|
||||
static let viewSlideOutMenuPartialOut: SideMenuPresentStyle
|
||||
/// The existing view slides out and shrinks to reveal the menu underneath.
|
||||
static let viewSlideOutMenuZoom: SideMenuPresentStyle
|
||||
```
|
||||
#### SideMenuNavigationControllerDelegate
|
||||
To receive notifications when a menu is displayed from a view controller, have it adhere to the `SideMenuNavigationControllerDelegate` protocol:
|
||||
``` swift
|
||||
extension MyViewController: SideMenuNavigationControllerDelegate {
|
||||
|
||||
func sideMenuWillAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuWillAppear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidAppear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuDidAppear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Appeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuWillDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuWillDisappear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappearing! (animated: \(animated))")
|
||||
}
|
||||
|
||||
func sideMenuDidDisappear(menu: UISideMenuNavigationController, animated: Bool) {
|
||||
func sideMenuDidDisappear(menu: SideMenuNavigationController, animated: Bool) {
|
||||
print("SideMenu Disappeared! (animated: \(animated))")
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
*Note: setting the `sideMenuDelegate` property on `UISideMenuNavigationController` is optional. If your view controller adheres to the protocol then the methods will be called automatically.*
|
||||
*Note: setting the `sideMenuDelegate` property on `SideMenuNavigationController` is optional. If your view controller adheres to the protocol then the methods will be called automatically.*
|
||||
### Advanced
|
||||
For simplicity, `SideMenuManager.default` serves as the primary instance as most projects will only need one menu across all screens. If you need to show a different SideMenu, such as from a modal view controller presented from a previous SideMenu, do the following:
|
||||
<details>
|
||||
<summary>Click for Details</summary>
|
||||
|
||||
#### Multiple SideMenuManagers
|
||||
For simplicity, `SideMenuManager.default` serves as the primary instance as most projects will only need one menu across all screens. If you need to show a different SideMenu using gestures, such as from a modal view controller presented from a previous SideMenu, do the following:
|
||||
1. Declare a variable containing your custom `SideMenuManager` instance. You may want it to define it globally and configure it in your app delegate if menus will be used on multiple screens.
|
||||
``` swift
|
||||
let customSideMenuManager = SideMenuManager()
|
||||
```
|
||||
2. Setup and display menus with your custom instance the same as you would with the `SideMenuManager.default` instance.
|
||||
3. If using Storyboards, subclass your instance of `UISideMenuNavigationController` and set its `sideMenuManager` property to your custom instance. This must be done before `viewDidLoad` is called:
|
||||
3. If using Storyboards, subclass your instance of `SideMenuNavigationController` and set its `sideMenuManager` property to your custom instance. This must be done before `viewDidLoad` is called:
|
||||
``` swift
|
||||
class MySideMenuNavigationController: UISideMenuNavigationController {
|
||||
class MySideMenuNavigationController: SideMenuNavigationController {
|
||||
|
||||
let customSideMenuManager = SideMenuManager()
|
||||
|
||||
@@ -316,21 +333,71 @@ class MySideMenuNavigationController: UISideMenuNavigationController {
|
||||
|
||||
sideMenuManager = customSideMenuManager
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
Alternatively, you can set `sideMenuManager` from the view controller that segues to your UISideMenuNavigationController:
|
||||
Alternatively, you can set `sideMenuManager` from the view controller that segues to your SideMenuNavigationController:
|
||||
``` swift
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if let sideMenuNavigationController = segue.destination as? UISideMenuNavigationController {
|
||||
if let sideMenuNavigationController = segue.destination as? SideMenuNavigationController {
|
||||
sideMenuNavigationController.sideMenuManager = customSideMenuManager
|
||||
}
|
||||
}
|
||||
```
|
||||
*Important: displaying SideMenu instances directly over each other is not supported. Use `menuPushStyle = .subMenu` instead.*
|
||||
*Important: displaying SideMenu instances directly over each other is not supported. Use `menuPushStyle = .subMenu` to display multi-level menus instead.*
|
||||
|
||||
### SideMenuPresentationStyle
|
||||
If you want to create your own custom presentation style, create a subclass of `SideMenuPresentationStyle` and set your menu's `presentationStyle` to it:
|
||||
```swift
|
||||
class MyPresentStyle: SideMenuPresentationStyle {
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
/// Background color behind the views and status bar color
|
||||
backgroundColor = .black
|
||||
/// The starting alpha value of the menu before it appears
|
||||
menuStartAlpha = 1
|
||||
/// Whether or not the menu is on top. If false, the presenting view is on top. Shadows are applied to the view on top.
|
||||
menuOnTop = false
|
||||
/// The amount the menu is translated along the x-axis. Zero is stationary, negative values are off-screen, positive values are on screen.
|
||||
menuTranslateFactor = 0
|
||||
/// The amount the menu is scaled. Less than one shrinks the view, larger than one grows the view.
|
||||
menuScaleFactor = 1
|
||||
/// The color of the shadow applied to the top most view.
|
||||
onTopShadowColor = .black
|
||||
/// The radius of the shadow applied to the top most view.
|
||||
onTopShadowRadius = 5
|
||||
/// The opacity of the shadow applied to the top most view.
|
||||
onTopShadowOpacity = 0
|
||||
/// The offset of the shadow applied to the top most view.
|
||||
onTopShadowOffset = .zero
|
||||
/// The ending alpha of the presenting view when the menu is fully displayed.
|
||||
presentingEndAlpha = 1
|
||||
/// The amount the presenting view is translated along the x-axis. Zero is stationary, negative values are off-screen, positive values are on screen.
|
||||
presentingTranslateFactor = 0
|
||||
/// The amount the presenting view is scaled. Less than one shrinks the view, larger than one grows the view.
|
||||
presentingScaleFactor = 1
|
||||
/// The strength of the parallax effect on the presenting view once the menu is displayed.
|
||||
presentingParallaxStrength = .zero
|
||||
}
|
||||
|
||||
/// This method is called just before the presentation transition begins. Use this to setup any animations. The super method does not need to be called.
|
||||
override func presentationTransitionWillBegin(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called during the presentation animation. Use this to animate anything alongside the menu animation. The super method does not need to be called.
|
||||
override func presentationTransition(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called when the presentation transition ends. Use this to finish any animations. The super method does not need to be called.
|
||||
override func presentationTransitionDidEnd(to presentedViewController: UIViewController, from presentingViewController: UIViewController, _ completed: Bool) {}
|
||||
/// This method is called just before the dismissal transition begins. Use this to setup any animations. The super method does not need to be called.
|
||||
override func dismissalTransitionWillBegin(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called during the dismissal animation. Use this to animate anything alongside the menu animation. The super method does not need to be called.
|
||||
override func dismissalTransition(to presentedViewController: UIViewController, from presentingViewController: UIViewController) {}
|
||||
/// This method is called when the dismissal transition ends. Use this to finish any animations. The super method does not need to be called.
|
||||
override func dismissalTransitionDidEnd(to presentedViewController: UIViewController, from presentingViewController: UIViewController, _ completed: Bool) {}
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
## Known Issues
|
||||
* Issue [#258](https://github.com/jonkykong/SideMenu/issues/258).
|
||||
* Don't try to change the status bar appearance when presenting a menu. When used with quick gestures/animations, it causes the presentation animation to not complete properly and locks the UI. This was fixed in iOS 9.3. See [radar 21961293](http://www.openradar.me/21961293) for more information.
|
||||
* Issue [#258](https://github.com/jonkykong/SideMenu/issues/258). Using `presentingViewControllerUseSnapshot` can help preserve the experience.
|
||||
|
||||
## Thank You
|
||||
A special thank you to everyone that has [contributed](https://github.com/jonkykong/SideMenu/graphs/contributors) to this library to make it better. Your support is appreciated!
|
||||
|
||||
+3
-2
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "SideMenu"
|
||||
s.version = "3.1.4"
|
||||
s.version = "6.5.0"
|
||||
s.summary = "Simple side menu control for iOS in Swift inspired by Facebook. Right and Left sides. No coding required."
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
@@ -28,7 +28,8 @@ Pod::Spec.new do |s|
|
||||
s.source = { :git => "https://github.com/jonkykong/SideMenu.git", :tag => s.version.to_s }
|
||||
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.ios.deployment_target = '10.0'
|
||||
s.swift_version = '5.0'
|
||||
|
||||
s.source_files = 'Pod/Classes/**/*'
|
||||
# s.resource_bundles = {
|
||||
|
||||
+237
-221
@@ -7,68 +7,93 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
108F6C478E56A4CA081F8E09 /* Pods_Example_ExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52C8DD7BE43A8987854CA726 /* Pods_Example_ExampleTests.framework */; };
|
||||
456193561EADC00AC505B531 /* Pods_ExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1435FAD2F735E43F383BE96 /* Pods_ExampleTests.framework */; };
|
||||
65FF1B3E1DE321D8007B0845 /* SideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 65FF1B3D1DE321D8007B0845 /* SideMenu.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
055AE0A193A9EA88D3279D68 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38DA39CCF181EA30E4346328 /* Pods_Example.framework */; };
|
||||
7B48A0D61DCB2487002990A1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B48A0D51DCB2487002990A1 /* AppDelegate.swift */; };
|
||||
7B48A0DD1DCB2487002990A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7B48A0DC1DCB2487002990A1 /* Assets.xcassets */; };
|
||||
7B48A0EB1DCB2487002990A1 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B48A0EA1DCB2487002990A1 /* Tests.swift */; };
|
||||
7B48A0F61DCB2518002990A1 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B48A0F31DCB2518002990A1 /* MainViewController.swift */; };
|
||||
7B48A0F71DCB2518002990A1 /* PresentedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B48A0F41DCB2518002990A1 /* PresentedViewController.swift */; };
|
||||
7B48A0F81DCB2518002990A1 /* SideMenuTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B48A0F51DCB2518002990A1 /* SideMenuTableViewController.swift */; };
|
||||
7B552D5D1DCC65830010301C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B552D5C1DCC65830010301C /* Launch Screen.storyboard */; };
|
||||
7B5FA9B61DCB269700278DF6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B5FA9B51DCB269700278DF6 /* Main.storyboard */; };
|
||||
8461A2D31E145A08001DA4F8 /* SideMenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8461A2CF1E145A08001DA4F8 /* SideMenuManager.swift */; };
|
||||
8461A2D41E145A08001DA4F8 /* SideMenuTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8461A2D01E145A08001DA4F8 /* SideMenuTransition.swift */; };
|
||||
8461A2D51E145A08001DA4F8 /* UISideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8461A2D11E145A08001DA4F8 /* UISideMenuNavigationController.swift */; };
|
||||
8461A2D61E145A08001DA4F8 /* UITableViewVibrantCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8461A2D21E145A08001DA4F8 /* UITableViewVibrantCell.swift */; };
|
||||
8432CC0422FFBCF5003D2BBD /* ExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432CC0322FFBCF5003D2BBD /* ExampleTests.swift */; };
|
||||
849F7B9623210C9A005DEB6A /* UITableViewVibrantCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8823210C9A005DEB6A /* UITableViewVibrantCell.swift */; };
|
||||
849F7B9723210C9A005DEB6A /* SideMenuTransitionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8923210C9A005DEB6A /* SideMenuTransitionController.swift */; };
|
||||
849F7B9823210C9A005DEB6A /* SideMenuAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8A23210C9A005DEB6A /* SideMenuAnimationController.swift */; };
|
||||
849F7B9923210C9A005DEB6A /* SideMenuInteractionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8B23210C9A005DEB6A /* SideMenuInteractionController.swift */; };
|
||||
849F7B9A23210C9A005DEB6A /* Initializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8C23210C9A005DEB6A /* Initializable.swift */; };
|
||||
849F7B9B23210C9A005DEB6A /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8D23210C9A005DEB6A /* Extensions.swift */; };
|
||||
849F7B9C23210C9A005DEB6A /* SideMenuPresentationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8E23210C9A005DEB6A /* SideMenuPresentationStyle.swift */; };
|
||||
849F7B9D23210C9A005DEB6A /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B8F23210C9A005DEB6A /* SideMenuNavigationController.swift */; };
|
||||
849F7B9E23210C9A005DEB6A /* SideMenuPushCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9023210C9A005DEB6A /* SideMenuPushCoordinator.swift */; };
|
||||
849F7B9F23210C9A005DEB6A /* Deprecations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9123210C9A005DEB6A /* Deprecations.swift */; };
|
||||
849F7BA023210C9A005DEB6A /* Print.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9223210C9A005DEB6A /* Print.swift */; };
|
||||
849F7BA123210C9A005DEB6A /* SideMenuPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9323210C9A005DEB6A /* SideMenuPresentationController.swift */; };
|
||||
849F7BA223210C9A005DEB6A /* SideMenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9423210C9A005DEB6A /* SideMenuManager.swift */; };
|
||||
849F7BA323210C9A005DEB6A /* Protected.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849F7B9523210C9A005DEB6A /* Protected.swift */; };
|
||||
849F7BA423225F7F005DEB6A /* SideMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = 849F7B67232104BD005DEB6A /* SideMenu.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84B489B51DD469B000D6CB43 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 84B489B21DD469B000D6CB43 /* LICENSE */; };
|
||||
84B489B71DD469B000D6CB43 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 84B489B41DD469B000D6CB43 /* README.md */; };
|
||||
84B489BA1DD469DA00D6CB43 /* SideMenu.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 84B489B91DD469DA00D6CB43 /* SideMenu.podspec */; };
|
||||
ACD6DAED90DE36FEA68CDF38 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47896ABC5C8830D88945A8D3 /* Pods_Example.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
7B48A0E71DCB2487002990A1 /* PBXContainerItemProxy */ = {
|
||||
8432CC0622FFBCF5003D2BBD /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7B9DC8FB1DC6E8C1000D4007 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 7B48A0D21DCB2487002990A1;
|
||||
remoteInfo = Example;
|
||||
};
|
||||
84418E042362E364002DE07F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7B9DC8FB1DC6E8C1000D4007 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 7B9DC9031DC6E8C1000D4007;
|
||||
remoteInfo = SideMenu;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1F17B9D56ADA958C611FAA83 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
281FB58A39C022692CEEBF0D /* Pods-Example-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-ExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
47896ABC5C8830D88945A8D3 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
52C8DD7BE43A8987854CA726 /* Pods_Example_ExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example_ExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
65FF1B3D1DE321D8007B0845 /* SideMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SideMenu.h; path = SideMenu/SideMenu.h; sourceTree = "<group>"; };
|
||||
38DA39CCF181EA30E4346328 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7B48A0D31DCB2487002990A1 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7B48A0D51DCB2487002990A1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7B48A0DC1DCB2487002990A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
7B48A0E11DCB2487002990A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
7B48A0E61DCB2487002990A1 /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7B48A0EA1DCB2487002990A1 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = "<group>"; };
|
||||
7B48A0EC1DCB2487002990A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
7B48A0F31DCB2518002990A1 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
||||
7B48A0F41DCB2518002990A1 /* PresentedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresentedViewController.swift; sourceTree = "<group>"; };
|
||||
7B48A0F51DCB2518002990A1 /* SideMenuTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuTableViewController.swift; sourceTree = "<group>"; };
|
||||
7B552D5C1DCC65830010301C /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
|
||||
7B5FA9B51DCB269700278DF6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
|
||||
7B9DC9041DC6E8C1000D4007 /* SideMenu.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SideMenu.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8461A2CF1E145A08001DA4F8 /* SideMenuManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuManager.swift; path = Pod/Classes/SideMenuManager.swift; sourceTree = "<group>"; };
|
||||
8461A2D01E145A08001DA4F8 /* SideMenuTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuTransition.swift; path = Pod/Classes/SideMenuTransition.swift; sourceTree = "<group>"; };
|
||||
8461A2D11E145A08001DA4F8 /* UISideMenuNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UISideMenuNavigationController.swift; path = Pod/Classes/UISideMenuNavigationController.swift; sourceTree = "<group>"; };
|
||||
8461A2D21E145A08001DA4F8 /* UITableViewVibrantCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UITableViewVibrantCell.swift; path = Pod/Classes/UITableViewVibrantCell.swift; sourceTree = "<group>"; };
|
||||
8432CC0122FFBCF4003D2BBD /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8432CC0322FFBCF5003D2BBD /* ExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleTests.swift; sourceTree = "<group>"; };
|
||||
8432CC0522FFBCF5003D2BBD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
849F7B67232104BD005DEB6A /* SideMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SideMenu.h; path = SideMenu/SideMenu.h; sourceTree = "<group>"; };
|
||||
849F7B8823210C9A005DEB6A /* UITableViewVibrantCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UITableViewVibrantCell.swift; path = Pod/Classes/UITableViewVibrantCell.swift; sourceTree = "<group>"; };
|
||||
849F7B8923210C9A005DEB6A /* SideMenuTransitionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuTransitionController.swift; path = Pod/Classes/SideMenuTransitionController.swift; sourceTree = "<group>"; };
|
||||
849F7B8A23210C9A005DEB6A /* SideMenuAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuAnimationController.swift; path = Pod/Classes/SideMenuAnimationController.swift; sourceTree = "<group>"; };
|
||||
849F7B8B23210C9A005DEB6A /* SideMenuInteractionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuInteractionController.swift; path = Pod/Classes/SideMenuInteractionController.swift; sourceTree = "<group>"; };
|
||||
849F7B8C23210C9A005DEB6A /* Initializable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Initializable.swift; path = Pod/Classes/Initializable.swift; sourceTree = "<group>"; };
|
||||
849F7B8D23210C9A005DEB6A /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Extensions.swift; path = Pod/Classes/Extensions.swift; sourceTree = "<group>"; };
|
||||
849F7B8E23210C9A005DEB6A /* SideMenuPresentationStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuPresentationStyle.swift; path = Pod/Classes/SideMenuPresentationStyle.swift; sourceTree = "<group>"; };
|
||||
849F7B8F23210C9A005DEB6A /* SideMenuNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuNavigationController.swift; path = Pod/Classes/SideMenuNavigationController.swift; sourceTree = "<group>"; };
|
||||
849F7B9023210C9A005DEB6A /* SideMenuPushCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuPushCoordinator.swift; path = Pod/Classes/SideMenuPushCoordinator.swift; sourceTree = "<group>"; };
|
||||
849F7B9123210C9A005DEB6A /* Deprecations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Deprecations.swift; path = Pod/Classes/Deprecations.swift; sourceTree = "<group>"; };
|
||||
849F7B9223210C9A005DEB6A /* Print.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Print.swift; path = Pod/Classes/Print.swift; sourceTree = "<group>"; };
|
||||
849F7B9323210C9A005DEB6A /* SideMenuPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuPresentationController.swift; path = Pod/Classes/SideMenuPresentationController.swift; sourceTree = "<group>"; };
|
||||
849F7B9423210C9A005DEB6A /* SideMenuManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SideMenuManager.swift; path = Pod/Classes/SideMenuManager.swift; sourceTree = "<group>"; };
|
||||
849F7B9523210C9A005DEB6A /* Protected.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Protected.swift; path = Pod/Classes/Protected.swift; sourceTree = "<group>"; };
|
||||
84B489B21DD469B000D6CB43 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
84B489B41DD469B000D6CB43 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
84B489B91DD469DA00D6CB43 /* SideMenu.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SideMenu.podspec; sourceTree = "<group>"; };
|
||||
84B489B91DD469DA00D6CB43 /* SideMenu.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SideMenu.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
|
||||
84FFB98523556C1600E241DA /* SideMenu.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SideMenu.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
84FFB98723556C4400E241DA /* SideMenu.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SideMenu.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C5943C005BBB10263AFAC91E /* Pods-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C7DA85E73FE6228663AD9236 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C9E09E1C686BF24AD4976EA7 /* Pods-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
CAE41BBB5F14E59C1FA0A821 /* Pods-Example-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-ExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
D1435FAD2F735E43F383BE96 /* Pods_ExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -76,16 +101,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
ACD6DAED90DE36FEA68CDF38 /* Pods_Example.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7B48A0E31DCB2487002990A1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
456193561EADC00AC505B531 /* Pods_ExampleTests.framework in Frameworks */,
|
||||
108F6C478E56A4CA081F8E09 /* Pods_Example_ExampleTests.framework in Frameworks */,
|
||||
055AE0A193A9EA88D3279D68 /* Pods_Example.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -96,12 +112,21 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8432CBFE22FFBCF4003D2BBD /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
65FF1B391DE31DA3007B0845 /* SupportingFiles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7B48A0E11DCB2487002990A1 /* Info.plist */,
|
||||
7B48A0DC1DCB2487002990A1 /* Assets.xcassets */,
|
||||
);
|
||||
name = SupportingFiles;
|
||||
sourceTree = "<group>";
|
||||
@@ -109,11 +134,21 @@
|
||||
65FF1B3F1DE33097007B0845 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8461A2CF1E145A08001DA4F8 /* SideMenuManager.swift */,
|
||||
8461A2D01E145A08001DA4F8 /* SideMenuTransition.swift */,
|
||||
8461A2D11E145A08001DA4F8 /* UISideMenuNavigationController.swift */,
|
||||
8461A2D21E145A08001DA4F8 /* UITableViewVibrantCell.swift */,
|
||||
65FF1B3D1DE321D8007B0845 /* SideMenu.h */,
|
||||
849F7B67232104BD005DEB6A /* SideMenu.h */,
|
||||
849F7B9123210C9A005DEB6A /* Deprecations.swift */,
|
||||
849F7B8D23210C9A005DEB6A /* Extensions.swift */,
|
||||
849F7B8C23210C9A005DEB6A /* Initializable.swift */,
|
||||
849F7B9223210C9A005DEB6A /* Print.swift */,
|
||||
849F7B9523210C9A005DEB6A /* Protected.swift */,
|
||||
849F7B8A23210C9A005DEB6A /* SideMenuAnimationController.swift */,
|
||||
849F7B8B23210C9A005DEB6A /* SideMenuInteractionController.swift */,
|
||||
849F7B9423210C9A005DEB6A /* SideMenuManager.swift */,
|
||||
849F7B8F23210C9A005DEB6A /* SideMenuNavigationController.swift */,
|
||||
849F7B9323210C9A005DEB6A /* SideMenuPresentationController.swift */,
|
||||
849F7B8E23210C9A005DEB6A /* SideMenuPresentationStyle.swift */,
|
||||
849F7B9023210C9A005DEB6A /* SideMenuPushCoordinator.swift */,
|
||||
849F7B8923210C9A005DEB6A /* SideMenuTransitionController.swift */,
|
||||
849F7B8823210C9A005DEB6A /* UITableViewVibrantCell.swift */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
@@ -128,31 +163,20 @@
|
||||
7B48A0F41DCB2518002990A1 /* PresentedViewController.swift */,
|
||||
7B552D5C1DCC65830010301C /* Launch Screen.storyboard */,
|
||||
7B5FA9B51DCB269700278DF6 /* Main.storyboard */,
|
||||
7B48A0DC1DCB2487002990A1 /* Assets.xcassets */,
|
||||
7B48A0E11DCB2487002990A1 /* Info.plist */,
|
||||
);
|
||||
path = Example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7B48A0E91DCB2487002990A1 /* ExampleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7B48A0EA1DCB2487002990A1 /* Tests.swift */,
|
||||
7B48A0EC1DCB2487002990A1 /* Info.plist */,
|
||||
);
|
||||
path = ExampleTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7B9DC8FA1DC6E8C1000D4007 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
65FF1B3F1DE33097007B0845 /* Source */,
|
||||
84B489B81DD469B900D6CB43 /* Podspec Metadata */,
|
||||
7B48A0D41DCB2487002990A1 /* Example */,
|
||||
7B48A0E91DCB2487002990A1 /* ExampleTests */,
|
||||
8432CC0222FFBCF5003D2BBD /* ExampleTests */,
|
||||
7B9DC9051DC6E8C1000D4007 /* Products */,
|
||||
9FB98148377EAEC00E35AC14 /* Pods */,
|
||||
9C94EEEBD250FF394115AAFC /* Frameworks */,
|
||||
84FFB98323556BD900E241DA /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -161,11 +185,20 @@
|
||||
children = (
|
||||
7B9DC9041DC6E8C1000D4007 /* SideMenu.framework */,
|
||||
7B48A0D31DCB2487002990A1 /* Example.app */,
|
||||
7B48A0E61DCB2487002990A1 /* ExampleTests.xctest */,
|
||||
8432CC0122FFBCF4003D2BBD /* ExampleTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8432CC0222FFBCF5003D2BBD /* ExampleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8432CC0322FFBCF5003D2BBD /* ExampleTests.swift */,
|
||||
8432CC0522FFBCF5003D2BBD /* Info.plist */,
|
||||
);
|
||||
path = ExampleTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84B489B81DD469B900D6CB43 /* Podspec Metadata */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -176,12 +209,12 @@
|
||||
name = "Podspec Metadata";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9C94EEEBD250FF394115AAFC /* Frameworks */ = {
|
||||
84FFB98323556BD900E241DA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
47896ABC5C8830D88945A8D3 /* Pods_Example.framework */,
|
||||
D1435FAD2F735E43F383BE96 /* Pods_ExampleTests.framework */,
|
||||
52C8DD7BE43A8987854CA726 /* Pods_Example_ExampleTests.framework */,
|
||||
84FFB98723556C4400E241DA /* SideMenu.framework */,
|
||||
84FFB98523556C1600E241DA /* SideMenu.framework */,
|
||||
38DA39CCF181EA30E4346328 /* Pods_Example.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -206,7 +239,7 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
65FF1B3E1DE321D8007B0845 /* SideMenu.h in Headers */,
|
||||
849F7BA423225F7F005DEB6A /* SideMenu.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -222,38 +255,17 @@
|
||||
7B48A0D01DCB2487002990A1 /* Frameworks */,
|
||||
7B48A0D11DCB2487002990A1 /* Resources */,
|
||||
558DEC0A930F44C17D50F99B /* [CP] Embed Pods Frameworks */,
|
||||
890CFF790C4292F1DC8AA122 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
84418E052362E364002DE07F /* PBXTargetDependency */,
|
||||
);
|
||||
name = Example;
|
||||
productName = Example;
|
||||
productReference = 7B48A0D31DCB2487002990A1 /* Example.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
7B48A0E51DCB2487002990A1 /* ExampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7B48A0F21DCB2487002990A1 /* Build configuration list for PBXNativeTarget "ExampleTests" */;
|
||||
buildPhases = (
|
||||
189AEFF809982E08C107BDD8 /* [CP] Check Pods Manifest.lock */,
|
||||
7B48A0E21DCB2487002990A1 /* Sources */,
|
||||
7B48A0E31DCB2487002990A1 /* Frameworks */,
|
||||
7B48A0E41DCB2487002990A1 /* Resources */,
|
||||
A5F2AF9B69C815BBA71DAD09 /* [CP] Embed Pods Frameworks */,
|
||||
3625CA9A4E129791488E06FE /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
7B48A0E81DCB2487002990A1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleTests;
|
||||
productName = ExampleTests;
|
||||
productReference = 7B48A0E61DCB2487002990A1 /* ExampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
7B9DC9031DC6E8C1000D4007 /* SideMenu */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7B9DC90C1DC6E8C1000D4007 /* Build configuration list for PBXNativeTarget "SideMenu" */;
|
||||
@@ -272,32 +284,51 @@
|
||||
productReference = 7B9DC9041DC6E8C1000D4007 /* SideMenu.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
8432CC0022FFBCF4003D2BBD /* ExampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8432CC0822FFBCF5003D2BBD /* Build configuration list for PBXNativeTarget "ExampleTests" */;
|
||||
buildPhases = (
|
||||
8432CBFD22FFBCF4003D2BBD /* Sources */,
|
||||
8432CBFE22FFBCF4003D2BBD /* Frameworks */,
|
||||
8432CBFF22FFBCF4003D2BBD /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
8432CC0722FFBCF5003D2BBD /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleTests;
|
||||
productName = ExampleTests;
|
||||
productReference = 8432CC0122FFBCF4003D2BBD /* ExampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
7B9DC8FB1DC6E8C1000D4007 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0800;
|
||||
LastUpgradeCheck = 0900;
|
||||
LastSwiftUpdateCheck = 1030;
|
||||
LastUpgradeCheck = 0930;
|
||||
ORGANIZATIONNAME = jonkykong;
|
||||
TargetAttributes = {
|
||||
7B48A0D21DCB2487002990A1 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0900;
|
||||
DevelopmentTeam = QTJ767UH3L;
|
||||
LastSwiftMigration = 1020;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
7B48A0E51DCB2487002990A1 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 7B48A0D21DCB2487002990A1;
|
||||
};
|
||||
7B9DC9031DC6E8C1000D4007 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0900;
|
||||
LastSwiftMigration = 1030;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
8432CC0022FFBCF4003D2BBD = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
DevelopmentTeam = QTJ767UH3L;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 7B48A0D21DCB2487002990A1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 7B9DC8FE1DC6E8C1000D4007 /* Build configuration list for PBXProject "SideMenu" */;
|
||||
@@ -305,6 +336,7 @@
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
@@ -315,7 +347,7 @@
|
||||
targets = (
|
||||
7B9DC9031DC6E8C1000D4007 /* SideMenu */,
|
||||
7B48A0D21DCB2487002990A1 /* Example */,
|
||||
7B48A0E51DCB2487002990A1 /* ExampleTests */,
|
||||
8432CC0022FFBCF4003D2BBD /* ExampleTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -331,13 +363,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7B48A0E41DCB2487002990A1 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7B9DC9021DC6E8C1000D4007 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -348,82 +373,32 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8432CBFF22FFBCF4003D2BBD /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
189AEFF809982E08C107BDD8 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../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";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3625CA9A4E129791488E06FE /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
558DEC0A930F44C17D50F99B /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/SideMenu/SideMenu.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SideMenu.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
890CFF790C4292F1DC8AA122 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A5F2AF9B69C815BBA71DAD09 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-frameworks.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
B96CD08B77E6CAC7B3180AE2 /* [CP] Check Pods Manifest.lock */ = {
|
||||
@@ -432,13 +407,16 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../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";
|
||||
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";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
@@ -455,32 +433,47 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7B48A0E21DCB2487002990A1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7B48A0EB1DCB2487002990A1 /* Tests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7B9DC8FF1DC6E8C1000D4007 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8461A2D51E145A08001DA4F8 /* UISideMenuNavigationController.swift in Sources */,
|
||||
8461A2D41E145A08001DA4F8 /* SideMenuTransition.swift in Sources */,
|
||||
8461A2D61E145A08001DA4F8 /* UITableViewVibrantCell.swift in Sources */,
|
||||
8461A2D31E145A08001DA4F8 /* SideMenuManager.swift in Sources */,
|
||||
849F7B9923210C9A005DEB6A /* SideMenuInteractionController.swift in Sources */,
|
||||
849F7B9B23210C9A005DEB6A /* Extensions.swift in Sources */,
|
||||
849F7BA323210C9A005DEB6A /* Protected.swift in Sources */,
|
||||
849F7B9F23210C9A005DEB6A /* Deprecations.swift in Sources */,
|
||||
849F7B9A23210C9A005DEB6A /* Initializable.swift in Sources */,
|
||||
849F7BA223210C9A005DEB6A /* SideMenuManager.swift in Sources */,
|
||||
849F7B9E23210C9A005DEB6A /* SideMenuPushCoordinator.swift in Sources */,
|
||||
849F7BA123210C9A005DEB6A /* SideMenuPresentationController.swift in Sources */,
|
||||
849F7B9C23210C9A005DEB6A /* SideMenuPresentationStyle.swift in Sources */,
|
||||
849F7B9823210C9A005DEB6A /* SideMenuAnimationController.swift in Sources */,
|
||||
849F7BA023210C9A005DEB6A /* Print.swift in Sources */,
|
||||
849F7B9723210C9A005DEB6A /* SideMenuTransitionController.swift in Sources */,
|
||||
849F7B9623210C9A005DEB6A /* UITableViewVibrantCell.swift in Sources */,
|
||||
849F7B9D23210C9A005DEB6A /* SideMenuNavigationController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8432CBFD22FFBCF4003D2BBD /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8432CC0422FFBCF5003D2BBD /* ExampleTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
7B48A0E81DCB2487002990A1 /* PBXTargetDependency */ = {
|
||||
8432CC0722FFBCF5003D2BBD /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 7B48A0D21DCB2487002990A1 /* Example */;
|
||||
targetProxy = 7B48A0E71DCB2487002990A1 /* PBXContainerItemProxy */;
|
||||
targetProxy = 8432CC0622FFBCF5003D2BBD /* PBXContainerItemProxy */;
|
||||
};
|
||||
84418E052362E364002DE07F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 7B9DC9031DC6E8C1000D4007 /* SideMenu */;
|
||||
targetProxy = 84418E042362E364002DE07F /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
@@ -489,13 +482,13 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1F17B9D56ADA958C611FAA83 /* Pods-Example.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.Example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -503,43 +496,13 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C7DA85E73FE6228663AD9236 /* Pods-Example.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.Example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
7B48A0EF1DCB2487002990A1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 281FB58A39C022692CEEBF0D /* Pods-Example-ExampleTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7B48A0F01DCB2487002990A1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = CAE41BBB5F14E59C1FA0A821 /* Pods-Example-ExampleTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -556,6 +519,7 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -563,6 +527,7 @@
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
@@ -575,6 +540,7 @@
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
@@ -591,12 +557,13 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -616,6 +583,7 @@
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -623,6 +591,7 @@
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
@@ -635,6 +604,7 @@
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
@@ -645,10 +615,11 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -667,14 +638,13 @@
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SideMenu/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "$(SRCROOT)/SideMenu/module.modulemap";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.SideMenu;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -689,13 +659,59 @@
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = SideMenu/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "$(SRCROOT)/SideMenu/module.modulemap";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.SideMenu;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8432CC0922FFBCF5003D2BBD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = QTJ767UH3L;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.massappeal.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = Example;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8432CC0A22FFBCF5003D2BBD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = QTJ767UH3L;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.massappeal.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = Example;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -711,15 +727,6 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7B48A0F21DCB2487002990A1 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7B48A0EF1DCB2487002990A1 /* Debug */,
|
||||
7B48A0F01DCB2487002990A1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7B9DC8FE1DC6E8C1000D4007 /* Build configuration list for PBXProject "SideMenu" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@@ -738,6 +745,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8432CC0822FFBCF5003D2BBD /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8432CC0922FFBCF5003D2BBD /* Debug */,
|
||||
8432CC0A22FFBCF5003D2BBD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 7B9DC8FB1DC6E8C1000D4007 /* Project object */;
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "C4A0A7D8591B67FB75E2E8D215E3735B"
|
||||
BuildableName = "SideMenu.framework"
|
||||
BlueprintName = "SideMenu"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7B48A0D21DCB2487002990A1"
|
||||
BuildableName = "Example.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:SideMenu.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7B48A0D21DCB2487002990A1"
|
||||
BuildableName = "Example.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:SideMenu.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8432CC0022FFBCF4003D2BBD"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:SideMenu.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7B48A0D21DCB2487002990A1"
|
||||
BuildableName = "Example.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:SideMenu.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7B48A0D21DCB2487002990A1"
|
||||
BuildableName = "Example.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:SideMenu.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0900"
|
||||
LastUpgradeVersion = "0930"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,7 +26,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
@@ -37,7 +36,6 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 135 KiB |
Reference in New Issue
Block a user