Compare commits

...
133 Commits
Author SHA1 Message Date
Felix Mau 385d133dfc 🔖 :: Bump version 2022-09-12 21:05:54 +02:00
Felix Mau 901fadaffb ⬆️ :: Update dev-dependencies 2022-09-12 20:53:10 +02:00
Felix Mau 097b26b5ad 🐛 :: Explicitly set deployment target for GradientLoadingBar in Pods project, as this will be read by Carthage 2022-09-12 20:38:48 +02:00
Felix Mau 066064280b 🐛 :: Remove shared scheme for Example
https://www.amerhukic.com/how-to-add-carthage-support-in-existing-cocoapod-project
2022-09-12 20:37:17 +02:00
Felix Mau c6a9fdb124 🔖 :: Bump version 2022-09-11 21:40:50 +02:00
Felix Mau 8090a3502a 🐛 :: Add missing import statement 2022-09-11 21:22:57 +02:00
Felix Mau 9e7d80e3d2 ♻️ :: Update snapshot tests to iOS 15.5 2022-09-09 14:47:53 +02:00
Felix Mau c6ed57a24e 💚 :: Increase timeout for CI 2022-09-09 14:29:15 +02:00
Felix Mau 999a3497de Merge branch 'main' into task/dependency-update 2022-09-09 13:51:49 +02:00
Felix Mau 4b2987dc79 :: Adapt tests 2022-09-09 13:51:39 +02:00
Felix Mau b209ecae78 Merge branch 'main' into task/dependency-update 2022-09-09 13:42:23 +02:00
Felix Mau e58c15c381 ♻️ :: Rename SafeAreaDevice to NotchDevice as the iPhone 14 Pro (Max) has a safe area without a notch 2022-09-09 13:42:12 +02:00
Felix Mau 345a874a04 ✏️ :: Fix typo 2022-09-08 22:29:58 +02:00
Felix Mau 47166ac314 🔖 :: Bump version 2022-09-08 19:41:10 +02:00
Felix Mau 707793be13 :: Adapt tests 2022-09-08 19:25:17 +02:00
Felix Mau 2b19e431ec ♻️ :: Prefer nil over .unknown enum case 2022-09-08 19:24:13 +02:00
Felix Mau 4521bc8622 :: Adapt tests 2022-09-08 19:23:42 +02:00
Felix Mau 77b7a5929e :: Add support for iOS 14 2022-09-08 19:23:25 +02:00
Felix Mau 3c145963e9 Merge branch 'main' into task/dependency-update 2022-09-08 12:25:34 +02:00
Felix Mau fcb33e68f7 🔖 :: Bump version 2022-09-08 12:23:55 +02:00
Felix Mau e82081460a 🐛 :: Fixed incorrect layout of NotchGradientLoadingBar when using "iPhone 12 Mini" or "iPhone 13 Mini" 2022-09-08 11:39:34 +02:00
Felix Mau 4de6fd74ec ⬆️ :: Update dev-dependencies 2022-09-07 18:18:09 +02:00
Felix Mau 49cf8c9ba2 ♻️ :: Use Mac OS 12, required by SwiftLint 0.49
> SwiftLint now requires Swift 5.6 or higher to build, and macOS 12 or higher to run.

https://github.com/realm/SwiftLint/blob/main/CHANGELOG.md#0490-asynchronous-defuzzer
2022-09-07 18:16:38 +02:00
Felix MandGitHub 5aa2f5d5ba Enhance BezierPath of NotchGradientLoadingBar (#31)
* ♻️ :: Enhance bezierpath

* ⬆️ :: Update fastlane plugin

* ⬆️ :: Update dev-dependencies

*  :: Adapt snapshot tests

* Revert "⬆️ :: Update dev-dependencies"

This reverts commit 45328c27ea.
2022-09-07 18:15:15 +02:00
Felix MandGitHub 9779449ab4 Merge pull request #30 from fxm90/feature/adapt-uikit-animation-to-swiftui-variant
Adapt UIKit animation implementation to SwiftUI variant
2022-09-07 17:50:46 +02:00
Felix Mau 60ccf4b1d2 🎨 :: Format code 2022-09-07 16:53:59 +02:00
Felix Mau ee6c985326 📝 :: Update documentation 2022-09-07 16:53:45 +02:00
Felix Mau f9b72b1621 ⬆️ :: Update dependencies 2022-08-22 20:20:35 +02:00
Felix Mau 84e1d0f2a4 📝 :: Update documentation 2022-08-22 20:19:18 +02:00
Felix Mau 85fa8e3851 :: Add test for GradientActivityIndicatorViewModel.SizeUpdate 2022-08-18 22:05:19 +02:00
Felix Mau 0ec26dfee9 🚚 :: Restructure test cases
They are now in folders with the same name as the features
2022-08-18 21:56:44 +02:00
Felix Mau d979f65b80 ♻️ :: Extract logic into SizeUpdate struct 2022-08-18 19:01:46 +02:00
Felix Mau 01c7df73f0 ♻️ :: Prefer property over method call 2022-08-18 18:56:06 +02:00
Felix Mau a7c82024d0 ♻️ :: Prefer private extension 2022-08-18 18:55:35 +02:00
Felix Mau 0b6424f4a8 📝 :: Update documentation 2022-08-18 18:55:21 +02:00
Felix Mau bfcdca3efb Revert "♻️ :: Reduce view updates by subscribing distinct"
This reverts commit fa7e30c44f.
2022-08-18 18:54:52 +02:00
Felix Mau 3c82b1464c ♻️ :: Fix snapshot tests 2022-08-17 22:50:03 +02:00
Felix Mau ea234f73bb ♻️ :: Fix snapshot tests 2022-08-15 22:18:55 +02:00
Felix Mau 0bfd932196 ♻️ :: Adapt tests 2022-08-15 21:33:58 +02:00
Felix Mau fa7e30c44f ♻️ :: Reduce view updates by subscribing distinct 2022-08-15 21:29:54 +02:00
Felix Mau 38115a2827 ♻️ :: Refactor to non stored property, to avoid duplicate data 2022-08-15 21:29:33 +02:00
Felix Mau 596692c2d4 Merge branch 'main' into feature/adapt-uikit-animation-to-swiftui-variant
# Conflicts:
#	GradientLoadingBar/Feature/GradientActivityIndicatorView/GradientActivityIndicatorViewModel.swift
2022-08-14 18:29:09 +02:00
Felix Mau 68c39399c4 🎨 :: Format code 2022-08-14 18:25:02 +02:00
Felix Mau 8a85860ba1 ⬆️ :: Update dev-dependencies 2022-08-14 18:24:14 +02:00
Felix Mau 24b380bf50 Merge branch 'main' into feature/adapt-uikit-animation-to-swiftui-variant
# Conflicts:
#	Example/Podfile.lock
#	Example/Pods/Manifest.lock
#	Example/Pods/SwiftFormat/CommandLineTool/swiftformat
2022-07-18 20:10:47 +02:00
Felix Mau c4294823e7 ⬆️ :: Update dev-dependencies 2022-07-18 20:09:54 +02:00
Felix Mau c319b42a49 ⬆️ :: Update dependencies 2022-05-28 12:02:47 +02:00
Felix Mau 2addd9fa7d ♻️ :: Enhance test cases 2022-05-20 15:40:16 +02:00
Felix Mau 8fb9963150 ♻️ :: Fix typo in test method 2022-05-20 15:34:57 +02:00
Felix Mau 68a53add0c 📝 :: Update documentation 2022-05-20 15:25:35 +02:00
Felix Mau b786421871 ♻️ :: Adapt constants 2022-05-20 15:03:37 +02:00
Felix Mau 4e52985153 ♻️ :: Adapt documentation 2022-05-20 14:57:30 +02:00
Felix Mau ae24582345 Merge branch 'main' into feature/adapt-uikit-animation-to-swiftui-variant 2022-05-12 21:49:55 +02:00
Felix Mau 61d787e1d6 🔖 :: Bump version 2022-05-10 18:39:25 +02:00
Felix Mau 5c45b2e9f5 :: Adapt tests 2022-05-10 18:35:56 +02:00
Felix Mau ff7c892079 🐛 :: Fix size of NotchGradientLoadingBar for "iPhone 11 Pro" and "iPhone 11 Pro Max"
fixes #29
2022-05-10 18:34:32 +02:00
Felix Mau 5f48a38dca Merge branch 'main' into feature/adapt-uikit-animation-to-swiftui-variant 2022-05-06 14:59:54 +01:00
Felix Mau 104d4c8f60 🔖 :: Bump version 2022-05-06 14:58:40 +01:00
Felix Mau 0e0b31ffbe 🐛 :: Fix incorrect path 2022-05-06 14:40:17 +01:00
Felix Mau 244e1eba94 ♻️ :: Add shared scheme GradientLoadingBar 2022-05-02 11:25:49 +01:00
Felix Mau 4e5aaae570 🐛 :: Fix invalid version 2022-05-02 11:25:30 +01:00
Felix Mau dfc9049be2 Merge branch 'feature/add-support-for-swiftui' into feature/adapt-uikit-animation-to-swiftui-variant 2022-04-29 18:49:04 +01:00
Felix Mau c0f27a3e48 ♻️ :: Remove outdated code 2022-04-29 18:43:44 +01:00
Felix Mau 54a413d986 🐛 :: Fix xcodebuild errors when running pod lib lint 2022-04-29 18:40:10 +01:00
Felix Mau 3d24237307 ♻️ :: Reduce precision to fix flaky tests on CI 2022-04-29 18:24:09 +01:00
Felix Mau 7c02e472d7 ♻️ :: Reduce precision to fix flaky tests on CI 2022-04-29 18:16:51 +01:00
Felix Mau 00275d6778 Merge branch 'feature/add-support-for-swiftui' into feature/adapt-uikit-animation-to-swiftui-variant 2022-04-29 18:07:42 +01:00
Felix Mau 1b41081034 🎨 :: Format code 2022-04-29 18:06:32 +01:00
Felix Mau f6a959a4b5 📝 :: Update documentation 2022-04-29 18:05:09 +01:00
Felix Mau ffdc50eada 🎨 :: Format code 2022-04-29 18:05:00 +01:00
Felix Mau 2ae619db5a Merge branch 'main' into feature/add-support-for-swiftui
# Conflicts:
#	Example/Gemfile.lock
2022-04-29 17:51:05 +01:00
Felix Mau 587e6d0095 ⬆️ :: Update dev-dependencies 2022-04-28 08:58:19 +01:00
Felix Mau 9012d6ec6a 🐛 :: Fix invalid comparison url 2022-04-28 08:55:58 +01:00
Felix Mau 8730c614de Merge branch 'feature/add-support-for-swiftui' into feature/adapt-uikit-animation-to-swiftui-variant
# Conflicts:
#	Example/ExampleTests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift
#	GradientLoadingBar/Feature/GradientActivityIndicatorView/GradientActivityIndicatorViewModel.swift
2022-04-28 08:50:51 +01:00
Felix Mau f7486690ac :: Update snapshot tests 2022-04-28 08:49:33 +01:00
Felix Mau 846005af52 ♻️ :: Update // MARK: - statements 2022-04-28 08:49:17 +01:00
Felix Mau cd14d3cfee ⬆️ :: Update dev-dependencies 2022-04-28 08:48:18 +01:00
Felix Mau 9ae07a9601 ♻️ :: Simplified tests 2022-04-27 18:57:29 +02:00
Felix Mau f0e4a7ec26 🐛 :: Update incorrect navigation title 2022-04-27 18:50:46 +02:00
Felix Mau 3d8e5c32fc :: Update snapshot tests 2022-04-27 18:49:13 +02:00
Felix Mau 240150d8c8 🎨 :: Format code 2022-04-27 18:48:31 +02:00
Felix Mau 6a80af2cd7 Merge branch 'feature/add-support-for-swiftui' into feature/adapt-uikit-animation-to-swiftui-variant
# Conflicts:
#	Example/ExampleTests/ViewModel/GradientActivityIndicatorViewModelTestCase.swift
#	GradientLoadingBar/Feature/GradientActivityIndicatorView/GradientActivityIndicatorViewModel.swift
2022-04-27 18:42:50 +02:00
Felix Mau b981df3519 ♻️ :: Update example application 2022-04-15 18:40:44 +02:00
Felix Mau 6c9c0ab1e1 📝 :: Add documentation 2022-04-12 21:39:57 +02:00
Felix Mau 563e8c6ecf Merge branch 'main' into feature/adapt-uikit-animation-to-swiftui-variant 2022-03-27 10:10:37 +02:00
Felix Mau 6980c0e3c3 ♻️ :: Remove outdated code 2022-03-27 10:10:20 +02:00
Felix Mau 94106389e2 Merge branch 'main' into feature/add-support-for-swiftui
# Conflicts:
#	Example/Podfile.lock
#	Example/Pods/Manifest.lock
#	GradientLoadingBar/Feature/NotchGradientLoadingBar/NotchGradientLoadingBarController.swift
2022-03-27 10:08:28 +02:00
Felix Mau b2279955a2 🔖 :: Bump version 2022-03-27 10:03:10 +02:00
Felix Mau 0b99b7853b 🐛 :: Fix invalid masking on iPhone 11 2022-03-27 09:47:08 +02:00
Felix Mau bc6575e9db ♻️ :: Improve safe area device check 2022-03-27 09:46:35 +02:00
Felix Mau 7b586da85b :: Adapt tests 2022-03-23 21:07:46 +01:00
Felix Mau 66467cf4d9 ♻️ :: Adapt UIKit variant to SwiftUI variant, by animating the gradient layer frame 2022-03-23 21:07:35 +01:00
Felix Mau 8e7650dd46 🚚 :: Use feature based folder structure 2022-03-23 09:57:13 +01:00
Felix Mau 8b257545ee ♻️ :: Rename property 2022-03-23 09:32:35 +01:00
Felix Mau 285d8ef2d4 :: Adapt snapshot tests 2022-03-23 09:32:19 +01:00
Felix Mau 090a59959f :: Add tests for new view-model 2022-03-22 20:07:27 +01:00
Felix Mau 67f356caf0 ♻️ :: Extract view logic into view model 2022-03-22 16:32:29 +01:00
Felix Mau 85a61b4433 🐛 :: Fix glitch in animation due to incorrect gradient size 2022-03-21 22:03:16 +01:00
Felix Mau f44ab07301 🚚 :: Rename tests 2022-03-20 08:11:23 +01:00
Felix Mau ae1ff09572 📝 :: Update documentation 2022-03-20 08:04:54 +01:00
Felix Mau e654161db3 🎨 :: Format code 2022-03-20 08:04:43 +01:00
Felix Mau df93f889b5 ♻️ :: Move numbers to configuration values 2022-03-20 08:04:14 +01:00
Felix Mau 63f66740c9 💚 :: Fix CI build 2022-03-16 20:34:22 +01:00
Felix Mau 80e113d194 ⬆️ :: Update gems 2022-03-16 20:30:06 +01:00
Felix Mau 91fdbbfeb6 ⬆️ :: Run pod install to resolve merge conflicts correctly 2022-03-16 17:45:31 +01:00
Felix Mau 555b5309a9 Merge branch 'main' into feature/add-support-for-swiftui
# Conflicts:
#	Example/ExampleTests/ViewModel/NotchGradientLoadingBarViewModelTestCase.swift
#	Example/Podfile.lock
#	Example/Pods/Manifest.lock
#	GradientLoadingBar/NotchGradientLoadingBarController.swift
2022-03-16 17:42:48 +01:00
Felix Mau cafd394cb7 🔖 :: Bump version 2022-03-16 17:30:49 +01:00
Felix Mau e558c54cb7 📝 :: Update documentation 2022-03-16 17:24:27 +01:00
Felix Mau 9382248471 :: Fix tests 2022-03-11 15:25:20 +01:00
Felix Mau 44307a6b7a 📝 :: Update documentation 2022-03-11 15:24:04 +01:00
Felix Mau f54023a6b9 🎨 :: Format code 2022-03-11 15:19:48 +01:00
Felix Mau 67f6ab75cc :: Add shortcut to check whether the loading bar is currently visible or not 2022-03-11 15:18:04 +01:00
Felix Mau 1f00f1d61f 📝 :: Update documentation 2022-03-11 15:05:51 +01:00
Felix Mau 41c084b27d 📝 :: Update documentation 2022-03-11 14:45:35 +01:00
Felix Mau e8d03a9ccc ♻️ :: Adapt configuration for iPhone XR 2022-03-11 14:33:45 +01:00
Felix Mau ecad3b98b9 ♻️ :: Allow offsetting the large circle in x and y direction 2022-03-11 14:08:56 +01:00
Felix Mau d97b99ab83 :: Add notch configuration for iPhone XR (WIP) 2022-03-11 14:04:12 +01:00
Felix Mau 0e20b0fb0e ♻️ :: Extract config for notch into separate struct
This struct is available per device as an extension on `NotchGradientLoadingBarViewModel.SafeAreaDevice`
2022-03-11 13:56:28 +01:00
Felix Mau 3e1c18818a ♻️ :: Combine scenes in example application 2022-03-11 13:42:30 +01:00
Felix Mau 76cd8c3ddf ♻️ :: Increase button height in example application 2022-03-11 10:00:10 +01:00
Felix Mau 66eace181a ♻️ :: Unify // MARK: - statements in tests 2022-03-10 14:09:33 +01:00
Felix Mau bbe2ddfe2f :: Fix flaky snapshot test 2022-03-10 14:08:39 +01:00
Felix Mau 0783d958a2 🚨 :: Fix warning 2022-03-10 14:08:18 +01:00
Felix Mau 07f2733ef8 ♻️ :: Use property drawHierarchyInKeyWindow instead of own custom helper 2022-03-10 14:08:02 +01:00
Felix Mau 03b9fac539 🚨 :: Fix keyWindow deprecation warning 2022-03-10 13:58:36 +01:00
Felix Mau be40ac8c35 :: Add snapshot tests 2022-03-10 12:01:35 +01:00
Felix Mau dec430d951 :: Add unit tests 2022-03-10 10:59:37 +01:00
Felix Mau 25de79f73d ♻️ :: Move custom colors to config value 2022-03-09 21:48:21 +01:00
Felix Mau 9ca33c4432 :: Adapt example application to show SwiftUI variant 2022-03-09 21:48:03 +01:00
Felix Mau f4b85195f5 :: Add SwiftUI view showing a gradient loading bar 2022-03-09 21:37:52 +01:00
Felix Mau 7309d0bd21 🚚 :: Rename file 2022-03-09 20:29:37 +01:00
Felix Mau d9c7840323 ♻️ :: Update example application 2022-03-07 21:53:13 +01:00
Felix Mau d484da4f83 ⬆️ :: Update dependencies 2022-03-07 19:41:14 +01:00
165 changed files with 5504 additions and 4964 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
# This workflow starts with a job called "build-and-test".
build-and-test:
name: Build & Test
runs-on: macos-latest
runs-on: macos-12
# Steps represent a sequence of tasks that will be executed as part of the job.
steps:
+1 -1
View File
@@ -1 +1 @@
5.1
5.5
+125
View File
@@ -0,0 +1,125 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1040" height="600" xml:space="preserve" id="cutout">
<!-- Generated by PaintCode - http://www.paintcodeapp.com -->
<defs>
<linearGradient id="cutout-gradient-bezier18" x1="207.78" y1="187.14" x2="912.47" y2="590.37" gradientUnits="userSpaceOnUse">
<stop offset="0.14" stop-color="rgb(0, 0, 0)" stop-opacity="0"></stop>
<stop offset="0.44" stop-color="rgb(64, 82, 91)" stop-opacity="0.05"></stop>
<stop offset="1" stop-color="rgb(129, 163, 182)" stop-opacity="0.09"></stop>
</linearGradient>
<linearGradient id="cutout-gradient2-rectangle" x1="559" y1="564" x2="559" y2="382" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="rgb(255, 255, 255)" stop-opacity="1"></stop>
<stop offset="1" stop-color="rgb(255, 255, 255)" stop-opacity="0"></stop>
</linearGradient>
</defs>
<path id="cutout-bezier26" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 928.5,563.5 L 928.5,259"></path>
<path id="cutout-bezier25" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 178.5,562.5 L 178.5,259"></path>
<path id="cutout-bezier18" stroke="none" fill="url(#cutout-gradient-bezier18)" d="M 929,561.48 L 929,306.52 C 929,267.79 929,248.42 922.41,227.57 914.12,204.81 896.19,186.88 873.42,178.6 855.96,172.83 833.21,172 794.48,172 L 781.34,172 C 776.06,172 773.42,172 770.58,172.9 767.47,174.03 765.03,176.47 763.9,179.58 763.11,181.96 763,185.06 763,190.34 L 763,192 C 763,214.09 745.09,232 723,232 L 385,232 C 362.91,232 345,214.09 345,192 L 345,190.34 C 345,185.06 345,182.42 344.1,179.58 342.97,176.47 340.53,174.03 337.42,172.9 335.04,172.11 331.94,172 326.66,172 L 313.52,172 C 274.79,172 267.5,172 267.5,172 218.9,172 179.5,211.4 179.5,260 179.5,260 179,267.79 179,306.52 L 179,561.48"></path>
<rect id="cutout-rectangle" stroke="none" fill="url(#cutout-gradient2-rectangle)" x="38" y="382" width="1042" height="182"></rect>
<circle id="cutout-oval3" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="383.5" cy="192.5" r="40"></circle>
<path id="cutout-bezier2" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 266.5,467.5 L 266.5,267"></path>
<circle id="cutout-oval4" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="0" cy="-0" r="12" transform="translate(331.5, 184.5)"></circle>
<circle id="cutout-oval" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="266.5" cy="260.5" r="88"></circle>
<g id="cutout-group8">
<path id="cutout-bezier13" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-linecap="square" stroke-miterlimit="10" fill="none" d="M 178.5,58.5 L 928.5,58.5"></path>
<polygon id="cutout-polygon" stroke="none" fill="rgb(65, 153, 231)" points="0,-9 3.68,4.5 -3.68,4.5" transform="translate(920, 58.5) rotate(90)"></polygon>
<polygon id="cutout-polygon2" stroke="none" fill="rgb(65, 153, 231)" points="-0,-9 -3.68,4.5 3.68,4.5" transform="translate(187, 58.5) rotate(-90)"></polygon>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="526.52" y="16" text-anchor="middle"><tspan x="553.5" y="45">375 pt</tspan></text>
</g>
<g id="cutout-group9">
<path id="cutout-bezier14" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-linecap="square" stroke-miterlimit="10" fill="none" d="M 178.5,125.5 L 343.5,125.5"></path>
<polygon id="cutout-polygon3" stroke="none" fill="rgb(65, 153, 231)" points="0,-9 3.68,4.5 -3.68,4.5" transform="translate(335, 125.5) rotate(90)"></polygon>
<polygon id="cutout-polygon4" stroke="none" fill="rgb(65, 153, 231)" points="-0,-9 -3.68,4.5 3.68,4.5" transform="translate(187, 125.5) rotate(-90)"></polygon>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="239.37" y="83" text-anchor="middle"><tspan x="261" y="112">83 pt</tspan></text>
</g>
<g id="cutout-group10">
<path id="cutout-bezier32" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-linecap="square" stroke-miterlimit="10" fill="none" d="M 762.5,125.5 L 928.5,125.5"></path>
<polygon id="cutout-polygon5" stroke="none" fill="rgb(65, 153, 231)" points="0,-9 3.68,4.5 -3.68,4.5" transform="translate(920, 125.5) rotate(90)"></polygon>
<polygon id="cutout-polygon6" stroke="none" fill="rgb(65, 153, 231)" points="-0,-9 -3.68,4.5 3.68,4.5" transform="translate(771, 125.5) rotate(-90)"></polygon>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="823.87" y="83" text-anchor="middle"><tspan x="845.5" y="112">83 pt</tspan></text>
</g>
<g id="cutout-group11">
<path id="cutout-bezier33" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-linecap="square" stroke-miterlimit="10" fill="none" d="M 343.5,125.5 L 762.5,125.5"></path>
<polygon id="cutout-polygon7" stroke="none" fill="rgb(65, 153, 231)" points="0,-9 3.68,4.5 -3.68,4.5" transform="translate(754, 125.5) rotate(90)"></polygon>
<polygon id="cutout-polygon8" stroke="none" fill="rgb(65, 153, 231)" points="-0,-9 -3.68,4.5 3.68,4.5" transform="translate(352, 125.5) rotate(-90)"></polygon>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="526.02" y="83" text-anchor="middle"><tspan x="553" y="112">209 pt</tspan></text>
</g>
<g id="cutout-group12">
<path id="cutout-bezier34" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-linecap="square" stroke-miterlimit="10" fill="none" d="M 94.5,221.5 L 94.5,186.5"></path>
<polygon id="cutout-polygon9" stroke="none" fill="rgb(65, 153, 231)" points="0,-9 3.68,4.5 -3.68,4.5" transform="translate(94.5, 223.5) rotate(180)"></polygon>
<polygon id="cutout-polygon10" stroke="none" fill="rgb(65, 153, 231)" points="-0,-9 -3.68,4.5 3.68,4.5" transform="translate(94.5, 182.5)"></polygon>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="43.75" y="188" text-anchor="end"><tspan x="87" y="208">30 pt</tspan></text>
</g>
<path id="cutout-bezier5" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 82,232.5 L 717.5,232.5"></path>
<path id="cutout-bezier7" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 343.5,192 L 343.5,108"></path>
<path id="cutout-bezier4" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 82,172.5 L 840.5,172.5"></path>
<path id="cutout-bezier8" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 762.5,192 L 762.5,108"></path>
<path id="cutout-bezier9" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 928.5,373 L 928.5,38"></path>
<path id="cutout-bezier10" opacity="0.3" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 178.5,259.5 L 178.5,39"></path>
<circle id="cutout-oval2" opacity="0.2" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="840.5" cy="260.5" r="88"></circle>
<circle id="cutout-oval5" opacity="0.2" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="722.5" cy="192.5" r="40"></circle>
<circle id="cutout-oval6" opacity="0.2" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="none" cx="0" cy="-0" r="12" transform="translate(774.5, 184.5)"></circle>
<circle id="cutout-oval10" stroke="none" fill="rgb(65, 153, 231)" cx="266.5" cy="470.5" r="3.5"></circle>
<g id="cutout-group">
<path id="cutout-bezier11" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 331.5,389.5 L 331.5,191"></path>
<circle id="cutout-oval12" stroke="none" fill="rgb(65, 153, 231)" cx="331.5" cy="389.5" r="3.5"></circle>
</g>
<path id="cutout-bezier17" stroke="rgb(65, 153, 231)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 383.5,324.5 L 383.5,202"></path>
<circle id="cutout-oval13" stroke="none" fill="rgb(65, 153, 231)" cx="383.5" cy="325.5" r="3.5"></circle>
<g id="cutout-group2">
<path id="cutout-bezier15" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 383.5,202 L 383.5,189"></path>
<path id="cutout-bezier16" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 377,195.5 L 390,195.5"></path>
<circle id="cutout-oval8" stroke="none" fill="rgb(0, 0, 0)" cx="383.5" cy="195.5" r="3.5"></circle>
</g>
<g id="cutout-group3" opacity="0.3">
<circle id="cutout-oval9" stroke="none" fill="rgb(0, 0, 0)" cx="721.5" cy="193.5" r="3.5"></circle>
<path id="cutout-bezier19" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 721.5,200 L 721.5,187"></path>
<path id="cutout-bezier20" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 715,193.5 L 728,193.5"></path>
</g>
<g id="cutout-group4" opacity="0.2">
<circle id="cutout-oval14" stroke="none" fill="rgb(0, 0, 0)" cx="839.5" cy="260.5" r="3.5"></circle>
<path id="cutout-bezier21" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 839.5,267 L 839.5,254"></path>
<path id="cutout-bezier22" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 833,260.5 L 846,260.5"></path>
</g>
<g id="cutout-group5" opacity="0.2">
<circle id="cutout-oval15" stroke="none" fill="rgb(0, 0, 0)" cx="774.5" cy="184.5" r="3.5"></circle>
<path id="cutout-bezier23" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 774.5,191 L 774.5,178"></path>
<path id="cutout-bezier24" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 768,184.5 L 781,184.5"></path>
</g>
<path id="cutout-bezier27" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 723,232.5 L 383,232.5"></path>
<path id="cutout-bezier28" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 332,172.5 L 265,172.5"></path>
<path id="cutout-bezier29" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 841.5,172.5 L 774,172.5"></path>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="281" y="454"><tspan x="281" y="476">40 pt radius</tspan></text>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="346" y="373"><tspan x="346" y="395">6 pt radius</tspan></text>
<text fill="rgb(65, 153, 231)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="18" x="403" y="309"><tspan x="403" y="331">20 pt radius</tspan></text>
<path id="cutout-oval16" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 383.5,232.5 C 361.41,232.5 343.5,214.59 343.5,192.5"></path>
<path id="cutout-oval17" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 178.5,260.5 C 178.5,211.9 217.9,172.5 266.5,172.5"></path>
<path id="cutout-oval18" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 331.5,172.5 C 338.13,172.5 343.5,177.87 343.5,184.5"></path>
<path id="cutout-bezier30" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 343.5,184.5 L 343.5,194.5"></path>
<path id="cutout-oval19" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 774.5,172.5 C 767.87,172.5 762.5,177.87 762.5,184.5"></path>
<path id="cutout-oval20" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 722.5,232.5 C 744.59,232.5 762.5,214.59 762.5,192.5"></path>
<path id="cutout-bezier31" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 762.5,184 L 762.5,194.5"></path>
<path id="cutout-oval21" stroke="rgb(0, 0, 0)" stroke-width="3" stroke-miterlimit="10" fill="none" d="M 928.5,260.5 C 928.5,211.9 889.1,172.5 840.5,172.5"></path>
<g id="cutout-group6">
<path id="cutout-bezier" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 266.5,267 L 266.5,254"></path>
<path id="cutout-bezier12" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 260,260.5 L 273,260.5"></path>
<circle id="cutout-oval7" stroke="none" fill="rgb(0, 0, 0)" cx="266.5" cy="260.5" r="3.5"></circle>
</g>
<g id="cutout-group7">
<path id="cutout-bezier3" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 331.5,191 L 331.5,178"></path>
<path id="cutout-bezier6" stroke="rgb(0, 0, 0)" stroke-width="1" stroke-miterlimit="10" fill="rgb(255, 255, 255)" d="M 325,184.5 L 338,184.5"></path>
<circle id="cutout-oval11" stroke="none" fill="rgb(0, 0, 0)" cx="331.5" cy="184.5" r="3.5"></circle>
</g>
<!-- Manually added copyright -->
<text fill="rgb(0, 0, 0)" font-family="AvenirNext-Medium, 'Avenir Next', sans-serif" font-size="15" x="560" y="560" text-anchor="middle">
Source: https://www.paintcodeapp.com/news/iphone-x-screen-demystified
</text>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

+51 -6
View File
@@ -7,6 +7,43 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
## [Unreleased]
## [2.3.5] - 2022-12-09
### Fixed
- Fixed wrong minimum iOS deployment target when using Carthage.
## [2.3.4] - 2022-11-09
### Fixed
- Added missing `UIKit` import when using Swift Package Manager.
## [2.3.3] - 2022-08-09
### Changed
- Added specific Bézier Path for `NotchGradientLoadingBar` for "iPhone 14" and "iPhone 14 Plus"
## [2.3.2] - 2022-08-09
### Changed
- Improved Bézier Path of `NotchGradientLoadingBar`
- Adapt logic of `UIKit` variant for calculating and animating the gradient to `SwiftUI` variant. This should not make any difference visually, but will be easier to maintain.
### Fixed
- Fixed incorrect layout on `NotchGradientLoadingBar` when using "iPhone 12 Mini" or "iPhone 13 Mini"
## [2.3.1] - 2022-10-05
### Fixed
- Fixed incorrect layout on `NotchGradientLoadingBar` when using "iPhone 11 Pro" or "iPhone 11 Pro Max" ([#029])
[#029]: https://github.com/fxm90/GradientLoadingBar/issues/29
## [2.3.0] - 2022-06-05
### Added
- Add `GradientLoadingBarView` to support SwiftUI
## [2.2.5] - 2022-27-03
### Fixed
- Fixed incorrect layout on `NotchGradientLoadingBar` when using "iPhone 11"
## [2.2.4] - 2022-16-03
### Fixed
- Fixed incorrect layout on `NotchGradientLoadingBar` when using "iPhone XR"
## [2.2.3] - 2021-29-12
### Fixed
- Fixed incorrect layout on `NotchGradientLoadingBar` when using an increased height ([#026], thanks to [alinfarcas12](https://github.com/alinfarcas12))
@@ -77,7 +114,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
## [1.1.14] - 2018-20-12
### Changed
- Fix fade-out animation not working in iOS 12 (https://openradar.appspot.com/46753872)
- Fixed fade-out animation not working in iOS 12 (https://openradar.appspot.com/46753872)
## [1.1.13] - 2018-14-11
### Changed
@@ -135,7 +172,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
## [1.1.3] - 2017-09-25
### Fixed
- Fix never adding gradient view to "keyWindow" if it is not available on first call to "show()"
- Fixed never adding gradient view to "keyWindow" if it is not available on first call to "show()"
## [1.1.2] - 2017-08-27
### Added
@@ -145,8 +182,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
## [1.1.1] - 2017-08-18
### Fixed
- Fix optical animation issue
- Fix orientation change bug
- Fixed optical animation issue
- Fixed orientation change bug
### Changed
- Refactor entire code
- Lint code
@@ -159,8 +196,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
- Initial release
[Unreleased]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.3...master
[2.2.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.2...2.2.3
[Unreleased]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.5...main
[2.3.5]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.4...2.3.5
[2.3.4]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.3...2.3.4
[2.3.3]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.2...2.3.3
[2.3.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.1...2.3.2
[2.3.1]: https://github.com/fxm90/GradientLoadingBar/compare/2.3.0...2.3.1
[2.3.0]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.5...2.3.0
[2.2.5]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.4...2.2.5
[2.2.4]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.3...2.2.4
[2.2.3]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.2...2.2.3
[2.2.2]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.1...2.2.2
[2.2.1]: https://github.com/fxm90/GradientLoadingBar/compare/2.2.0...2.2.1
[2.2.0]: https://github.com/fxm90/GradientLoadingBar/compare/2.1.1...2.2.0
+1 -1
View File
@@ -1 +1 @@
github "fxm90/LightweightObservable" ~> 1.0
github "fxm90/LightweightObservable" ~> 2.0
+3 -4
View File
@@ -1,4 +1,4 @@
#
#
# .swiftlint.yml
# Created by Felix Mau (https://felix.hamburg)
#
@@ -10,7 +10,7 @@ file_header:
required_pattern: |
\/\/
\/\/ SWIFTLINT_CURRENT_FILENAME
\/\/ (GradientLoadingBar|GradientLoadingBar_Example|GradientLoadingBar_Tests|GradientLoadingBar_SnapshotTests)
\/\/ (GradientLoadingBar|Example|ExampleTests|ExampleSnapshotTests)
\/\/
\/\/ Created by .*? on \d{2}\.\d{2}\.\d{2}\.
\/\/ Copyright © \d{4} .*?\. All rights reserved\.
@@ -23,5 +23,4 @@ included:
excluded:
- Pods
parent_config: Pods/SwiftConfigurationFiles/.swiftlint.yml
parent_config: Pods/SwiftConfigurationFiles/.swiftlint.yml
File diff suppressed because it is too large Load Diff
@@ -2,7 +2,7 @@
<Workspace
version = "1.0">
<FileRef
location = "group:GradientLoadingBar.xcodeproj">
location = "group:Example.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
+31
View File
@@ -0,0 +1,31 @@
//
// ExampleApp.swift
// Example
//
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import SwiftUI
@main
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
EntryPointView()
.onAppear {
// Use iOS 13 navigation bar appearance.
//
// While the entry point scene looks better with an opaque navigation background, the child scenes look
// better with the default navigation background. As we can't update the appearance per scene we fallback
// to an appearance with the default background here.
//
// Based on: https://sarunw.com/posts/uinavigationbar-changes-in-ios13/
let appearance = UINavigationBarAppearance()
appearance.configureWithDefaultBackground()
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
}
}
}
@@ -0,0 +1,29 @@
//
// StoryboardView.swift
// Example
//
// Created by Felix Mau on 02.02.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import SwiftUI
struct StoryboardView: UIViewControllerRepresentable {
// MARK: - Public properties
let name: String
// MARK: - Public methods
func makeUIViewController(context _: Context) -> UIViewController {
let storyboard = UIStoryboard(name: name, bundle: nil)
guard let viewController = storyboard.instantiateInitialViewController() else {
fatalError("⚠️ Could not instantiate initial view controller for storyboard with name `\(name)`.")
}
return viewController
}
func updateUIViewController(_: UIViewController, context _: Context) {}
}
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ZAD-6Y-gxa">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Advanced Example Table View Controller-->
<scene sceneID="iwG-zT-VrO">
<objects>
<tableViewController id="ZAD-6Y-gxa" customClass="AdvancedExampleTableViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="insetGrouped" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" estimatedSectionHeaderHeight="-1" sectionFooterHeight="18" estimatedSectionFooterHeight="-1" id="2vt-bX-4b7">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="CustomColorsTableViewCell" id="qq9-jr-nNk" customClass="CustomColorsTableViewCell" customModule="Example" customModuleProvider="target">
<rect key="frame" x="20" y="49.5" width="374" height="120.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qq9-jr-nNk" id="60G-w2-6BV">
<rect key="frame" x="0.0" y="0.0" width="374" height="120.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="zN2-pr-LT6">
<rect key="frame" x="16" y="16" width="342" height="88.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Example showing how to provide custom gradient colors." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lbJ-pG-fGJ">
<rect key="frame" x="0.0" y="0.0" width="342" height="36"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uL7-lu-aRP" userLabel="Toggle Custom Colors Button">
<rect key="frame" x="0.0" y="48" width="342" height="40.5"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="jZd-Vw-MAb"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Toggle Custom Colors ↑">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="customColorsButtonTouchUpInside:" destination="qq9-jr-nNk" eventType="touchUpInside" id="XyI-4Q-sja"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstItem="zN2-pr-LT6" firstAttribute="leading" secondItem="60G-w2-6BV" secondAttribute="leading" constant="16" id="18p-RW-IFT"/>
<constraint firstAttribute="bottom" secondItem="zN2-pr-LT6" secondAttribute="bottom" constant="16" id="6LP-eX-o55"/>
<constraint firstItem="zN2-pr-LT6" firstAttribute="top" secondItem="60G-w2-6BV" secondAttribute="top" constant="16" id="RzJ-mr-IHP"/>
<constraint firstAttribute="trailing" secondItem="zN2-pr-LT6" secondAttribute="trailing" constant="16" id="h7A-pm-6hb"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="InterfaceBuilderSetupTableViewCell" id="yBS-fc-uJy" customClass="InterfaceBuilderSetupTableViewCell" customModule="Example" customModuleProvider="target">
<rect key="frame" x="20" y="170" width="374" height="83.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="yBS-fc-uJy" id="Tid-am-qRM">
<rect key="frame" x="0.0" y="0.0" width="374" height="83.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="KTF-6b-NmT">
<rect key="frame" x="16" y="16" width="342" height="51.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bCd-m6-FJm" customClass="GradientActivityIndicatorView" customModule="GradientLoadingBar">
<rect key="frame" x="0.0" y="0.0" width="342" height="3"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="3" id="FQe-RY-KH7"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TpO-6A-9Bl" userLabel="Toggle IB Setup Button">
<rect key="frame" x="0.0" y="11" width="342" height="40.5"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="QLO-3y-Y29"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Toggle IB Setup 🎨">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="toggleIBSetupButtonTouchUpInside:" destination="yBS-fc-uJy" eventType="touchUpInside" id="WLP-Dw-VmD"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstItem="KTF-6b-NmT" firstAttribute="top" secondItem="Tid-am-qRM" secondAttribute="top" constant="16" id="2Bc-ex-Ggk"/>
<constraint firstItem="KTF-6b-NmT" firstAttribute="leading" secondItem="Tid-am-qRM" secondAttribute="leading" constant="16" id="Aka-HV-cVb"/>
<constraint firstAttribute="bottom" secondItem="KTF-6b-NmT" secondAttribute="bottom" constant="16" id="MH0-A6-FGH"/>
<constraint firstAttribute="trailing" secondItem="KTF-6b-NmT" secondAttribute="trailing" constant="16" id="pLD-Mq-O5j"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="gradientActivityIndicator" destination="bCd-m6-FJm" id="z4t-IP-gqw"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="CustomSuperviewViewCell" id="ah2-WM-rFd" customClass="CustomSuperviewTableViewCell" customModule="Example" customModuleProvider="target">
<rect key="frame" x="20" y="253.5" width="374" height="120.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ah2-WM-rFd" id="2Sj-GS-zEL">
<rect key="frame" x="0.0" y="0.0" width="374" height="120.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="ja4-s5-ZP7">
<rect key="frame" x="20" y="16" width="334" height="88.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Example showing how to add the loading bar as a subview." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c7X-oS-Zcv">
<rect key="frame" x="0.0" y="0.0" width="334" height="36"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZxZ-rY-wUa" userLabel="Toggle Custom Superview Button" customClass="BorderedButton" customModule="Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="48" width="334" height="40.5"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="YS7-tA-cMK"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" title="Toggle Custom Superview 🧪">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="toggleButtonTouchUpInside:" destination="ah2-WM-rFd" eventType="touchUpInside" id="W51-If-b5H"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstItem="ja4-s5-ZP7" firstAttribute="top" secondItem="2Sj-GS-zEL" secondAttribute="top" constant="16" id="ERr-8u-XhG"/>
<constraint firstAttribute="trailing" secondItem="ja4-s5-ZP7" secondAttribute="trailing" constant="20" id="SsK-Vx-1BL"/>
<constraint firstAttribute="bottom" secondItem="ja4-s5-ZP7" secondAttribute="bottom" constant="16" id="UBf-R5-ixV"/>
<constraint firstItem="ja4-s5-ZP7" firstAttribute="leading" secondItem="2Sj-GS-zEL" secondAttribute="leading" constant="20" id="xgE-OJ-VIu"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="toggleButton" destination="ZxZ-rY-wUa" id="TwF-62-tM1"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="ZAD-6Y-gxa" id="3QD-qs-jpF"/>
<outlet property="delegate" destination="ZAD-6Y-gxa" id="yIF-PG-bRO"/>
</connections>
</tableView>
<extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="R94-H9-mvS" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-165" y="27"/>
</scene>
</scenes>
<designables>
<designable name="ZxZ-rY-wUa">
<size key="intrinsicContentSize" width="216.5" height="31"/>
</designable>
</designables>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -0,0 +1,136 @@
//
// AdvancedExampleTableViewController.swift
// Example
//
// Created by Felix Mau on 12.04.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import GradientLoadingBar
import SwiftUI
import UIKit
final class AdvancedExampleTableViewController: UITableViewController {
// MARK: - Config
private enum Config {
/// The custom gradient colors we use.
/// Source: https://color.adobe.com/Pink-Flamingo-color-theme-10343714/
static let gradientColors = [
#colorLiteral(red: 0.9490196078, green: 0.3215686275, blue: 0.431372549, alpha: 1), #colorLiteral(red: 0.9450980392, green: 0.4784313725, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.9529411765, green: 0.737254902, blue: 0.7843137255, alpha: 1), #colorLiteral(red: 0.4274509804, green: 0.8666666667, blue: 0.9490196078, alpha: 1), #colorLiteral(red: 0.7568627451, green: 0.9411764706, blue: 0.9568627451, alpha: 1),
]
static let firstSectionHeaderHeight: CGFloat = 48
static let defaultSectionHeaderHeight: CGFloat = 32
}
// MARK: - Types
private enum Section: CaseIterable {
case customColors
case interfaceBuilderSetup
case customSuperview
var cellIdentifier: String {
switch self {
case .customColors:
return CustomColorsTableViewCell.reuseIdentifier
case .interfaceBuilderSetup:
return InterfaceBuilderSetupTableViewCell.reuseIdentifier
case .customSuperview:
return CustomSuperviewTableViewCell.reuseIdentifier
}
}
var sectionTitle: String {
switch self {
case .customColors:
return "Custom Colors"
case .interfaceBuilderSetup:
return "Interface Builder Setup"
case .customSuperview:
return "Custom Superview"
}
}
var sectionHeaderHeight: CGFloat {
switch self {
case .customColors:
return Config.firstSectionHeaderHeight
case .interfaceBuilderSetup, .customSuperview:
return Config.defaultSectionHeaderHeight
}
}
}
// MARK: - Private properties
private let gradientLoadingBar = GradientLoadingBar()
// MARK: - Public methods
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGroupedBackground
gradientLoadingBar.gradientColors = Config.gradientColors
}
// MARK: - Table view data source
override func numberOfSections(in _: UITableView) -> Int {
Section.allCases.count
}
override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = Section.allCases[indexPath.section]
switch section {
case .customColors:
guard let cell = tableView.dequeueReusableCell(withIdentifier: section.cellIdentifier, for: indexPath) as? CustomColorsTableViewCell else {
fatalError("⚠️ Invalid table view setup. Expected to have `CustomColorsTableViewCell` at this point!")
}
cell.tapHandler = { [weak self] in
if self?.gradientLoadingBar.isHidden == true {
self?.gradientLoadingBar.fadeIn()
} else {
self?.gradientLoadingBar.fadeOut()
}
}
return cell
case .interfaceBuilderSetup, .customSuperview:
return tableView.dequeueReusableCell(withIdentifier: section.cellIdentifier, for: indexPath)
}
}
override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
Section.allCases[section].sectionTitle
}
override func tableView(_: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
Section.allCases[section].sectionHeaderHeight
}
}
// MARK: - Helper
struct AdvancedExampleView: View {
var body: some View {
StoryboardView(name: "AdvancedExample")
.navigationTitle("🚀 Advanced Example")
.edgesIgnoringSafeArea(.bottom)
}
}
@@ -0,0 +1,24 @@
//
// CustomColorsTableViewCell.swift
// Example
//
// Created by Felix Mau on 15.04.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import UIKit
final class CustomColorsTableViewCell: UITableViewCell {
// MARK: - Public properties
static let reuseIdentifier = "CustomColorsTableViewCell"
var tapHandler: (() -> Void)?
// MARK: - Private methods
@IBAction private func customColorsButtonTouchUpInside(_: Any) {
tapHandler?()
}
}
@@ -0,0 +1,62 @@
//
// CustomSuperviewTableViewCell.swift
// Example
//
// Created by Felix Mau on 15.04.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import GradientLoadingBar
import UIKit
final class CustomSuperviewTableViewCell: UITableViewCell {
// MARK: - Config
private enum Config {
static let height: CGFloat = 3
}
// MARK: - Outlets
@IBOutlet private var toggleButton: UIButton!
// MARK: - Public properties
static let reuseIdentifier = "CustomSuperviewViewCell"
// MARK: - Private properties
private let gradientActivityIndicatorView = GradientActivityIndicatorView()
// MARK: - Public methods
override func awakeFromNib() {
super.awakeFromNib()
setupGradientActivityIndicatorView()
}
// MARK: - Private methods
private func setupGradientActivityIndicatorView() {
gradientActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
toggleButton.addSubview(gradientActivityIndicatorView)
NSLayoutConstraint.activate([
gradientActivityIndicatorView.leadingAnchor.constraint(equalTo: toggleButton.leadingAnchor),
gradientActivityIndicatorView.trailingAnchor.constraint(equalTo: toggleButton.trailingAnchor),
gradientActivityIndicatorView.bottomAnchor.constraint(equalTo: toggleButton.bottomAnchor),
gradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: Config.height),
])
}
@IBAction private func toggleButtonTouchUpInside(_: Any) {
if gradientActivityIndicatorView.isHidden {
gradientActivityIndicatorView.fadeIn()
} else {
gradientActivityIndicatorView.fadeOut()
}
}
}
@@ -0,0 +1,41 @@
//
// InterfaceBuilderSetupTableViewCell.swift
// Example
//
// Created by Felix Mau on 15.04.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import GradientLoadingBar
import UIKit
final class InterfaceBuilderSetupTableViewCell: UITableViewCell {
// MARK: - Config
private enum Config {
static let animationDuration: TimeInterval = 0.5
}
// MARK: - Outlets
@IBOutlet private var gradientActivityIndicator: GradientActivityIndicatorView!
// MARK: - Public properties
static let reuseIdentifier = "InterfaceBuilderSetupTableViewCell"
// MARK: - Private methods
@IBAction private func toggleIBSetupButtonTouchUpInside(_: Any) {
// We explicitly "only" reduce the alpha here, as calling `fadeIn()` / `fadeOut()` would update the `isHidden`
// flag accordingly. This would then lead to a height-update of the parent stack view.
UIView.animate(withDuration: Config.animationDuration) {
if self.gradientActivityIndicator.alpha > 0 {
self.gradientActivityIndicator.alpha = 0
} else {
self.gradientActivityIndicator.alpha = 1
}
}
}
}
@@ -0,0 +1,47 @@
//
// BorderedButton.swift
// Example
//
// Created by Felix Mau on 15.04.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import UIKit
@IBDesignable
final class BorderedButton: UIButton {
// MARK: - Config
private enum Config {
static let borderColor = #colorLiteral(red: 0.2862745098, green: 0.5647058824, blue: 0.8862745098, alpha: 1)
static let borderWidth: CGFloat = 1
static let cornerRadius: CGFloat = 4
}
// MARK: - Instance Lifecycle
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
// MARK: - Private methods
private func commonInit() {
backgroundColor = .clear
tintColor = Config.borderColor
layer.borderColor = Config.borderColor.cgColor
layer.borderWidth = Config.borderWidth
layer.cornerRadius = Config.cornerRadius
layer.masksToBounds = true
}
}
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Basic Example View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" customClass="BasicExampleViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="i3m-u5-CBZ" userLabel="Content Stack View">
<rect key="frame" x="16" y="428" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iqR-B3-IAJ" userLabel="ShowButton">
<rect key="frame" x="0.0" y="0.0" width="183" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="ygd-aW-5tx"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Show ↑">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="showButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="syE-bX-c9J"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0mi-83-2Nx" userLabel="HideButton">
<rect key="frame" x="199" y="0.0" width="183" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="bWt-eh-ohc"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Hide ">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="hideButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="xWJ-X0-hCH"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="i3m-u5-CBZ" firstAttribute="centerY" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" id="J8f-pR-dOH"/>
<constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="i3m-u5-CBZ" secondAttribute="trailing" constant="16" id="RpI-X5-afT"/>
<constraint firstItem="i3m-u5-CBZ" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="16" id="qcn-hk-qmQ"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="132" y="115"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -1,23 +1,28 @@
//
// BasicExampleViewController.swift
// GradientLoadingBar_Example
// Example
//
// Created by Felix Mau on 30.09.17.
// Copyright © 2017 Felix Mau. All rights reserved.
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import UIKit
import GradientLoadingBar
import SwiftUI
import UIKit
final class BasicExampleViewController: UIViewController {
class BasicExampleViewController: UIViewController {
// MARK: - Public methods
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Reset any possible visible loading bar.
GradientLoadingBar.shared.fadeOut()
}
// MARK: - Private methods
@IBAction private func showButtonTouchUpInside(_: Any) {
GradientLoadingBar.shared.fadeIn()
}
@@ -26,3 +31,12 @@ class BasicExampleViewController: UIViewController {
GradientLoadingBar.shared.fadeOut()
}
}
// MARK: - Helper
struct BasicExampleView: View {
var body: some View {
StoryboardView(name: "BasicExample")
.navigationTitle("🏡 Basic Example")
}
}
@@ -0,0 +1,95 @@
//
// EntryPointView.swift
// Example
//
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import SwiftUI
struct EntryPointView: View {
// MARK: - Private properties
@State
private var isNavigationBarExampleVisible = false
// MARK: - Render
var body: some View {
NavigationView {
List {
Section(header: Text("UIKit Examples")) {
NavigationLink(destination: BasicExampleView()) {
TitleSubtitleView(title: "🏡 Basic Example",
subtitle: "Basic usage and setup.")
}
NavigationLink(destination: SafeAreaExampleView()) {
TitleSubtitleView(title: "📲 Safe Area Example",
subtitle: "Loading bar ignoring the safe area.")
}
NavigationLink(destination: AdvancedExampleView()) {
TitleSubtitleView(title: "🚀 Advanced Example",
subtitle: "How to apply e.g. custom colors.")
}
Button {
isNavigationBarExampleVisible = true
} label: {
TitleSubtitleView(title: "🧭 Navigation Bar Example",
subtitle: "Attach the loading bar to a navigation bar.")
// Make entire row tappable and not just the text.
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
.buttonStyle(PlainButtonStyle())
}
Section(header: Text("SwiftUI Examples")) {
NavigationLink(destination: SwiftUIExampleView()) {
TitleSubtitleView(title: "🎨 GradientLoadingBarView Example",
subtitle: "How to use the SwiftUI view.")
}
}
}
// We present the `NavigationBarExampleView` as a sheet using it's own navigation controller.
// The `NavigationView` passed from SwiftUI isn't accessible from a `UIViewController` in a way, that we can add subviews to it.
.sheet(isPresented: $isNavigationBarExampleVisible) {
NavigationBarExampleView()
}
// Unfortunately setting the title here results in constraint warnings.
// I couldn't find a possible fix yet, even `.navigationViewStyle(.stack)` doesn't seem to work.
// https://stackoverflow.com/q/65316497
.navigationTitle("GradientLoadingBar")
.navigationBarTitleDisplayMode(.large)
}
}
}
// MARK: - Subviews
private struct TitleSubtitleView: View {
let title: String
let subtitle: String
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(title)
.font(.headline)
Text(subtitle)
.font(.subheadline)
}
.padding(.vertical, 8)
}
}
// MARK: - Preview
struct EntryPointView_Previews: PreviewProvider {
static var previews: some View {
EntryPointView()
}
}
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="QqU-dK-9N3">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--🧭 Navigation Bar Example-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" customClass="NavigationBarExampleViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="NLc-ox-i4v">
<rect key="frame" x="16" y="428" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m50-Bi-edx" userLabel="ShowButton">
<rect key="frame" x="0.0" y="0.0" width="183" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="3OT-yv-cyC"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Show">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="showButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="Wp7-QY-9dg"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aXh-Qp-yVs" userLabel="HideButton">
<rect key="frame" x="199" y="0.0" width="183" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="0sc-bb-ZEH"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Hide">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="hideButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="vxz-29-LMX"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="NLc-ox-i4v" secondAttribute="trailing" constant="16" id="2Ig-gz-o5i"/>
<constraint firstItem="NLc-ox-i4v" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="16" id="5DU-9Z-LFC"/>
<constraint firstItem="NLc-ox-i4v" firstAttribute="centerY" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" id="uG6-3e-Y6q"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="🧭 Navigation Bar Example" id="cJ0-SC-qx4"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1042.0289855072465" y="61.607142857142854"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="Fzj-P1-1gQ">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="QqU-dK-9N3" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" largeTitles="YES" id="Gew-of-pOh">
<rect key="frame" x="0.0" y="44" width="414" height="96"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="Y6W-OH-hqX" kind="relationship" relationship="rootViewController" id="YmV-f4-HGX"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="brr-zi-WNx" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="131.8840579710145" y="61.607142857142854"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -1,15 +1,17 @@
//
// NavigationBarExampleViewController.swift
// GradientLoadingBar_Example
// Example
//
// Created by Felix Mau on 29.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import UIKit
import GradientLoadingBar
import SwiftUI
import UIKit
final class NavigationBarExampleViewController: UIViewController {
class NavigationBarExampleViewController: UIViewController {
// MARK: - Config
private enum Config {
@@ -26,20 +28,16 @@ class NavigationBarExampleViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let barButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
navigationItem.rightBarButtonItem = barButtonItem
setupGradientProgressIndicatorView()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
gradientProgressIndicatorView.fadeOut()
}
@IBAction private func showButtonTouchUpInside(_: Any) {
gradientProgressIndicatorView.fadeIn()
}
@IBAction private func hideButtonTouchUpInside(_: Any) {
// Reset any possible visible loading bar.
gradientProgressIndicatorView.fadeOut()
}
@@ -48,8 +46,6 @@ class NavigationBarExampleViewController: UIViewController {
private func setupGradientProgressIndicatorView() {
guard let navigationBar = navigationController?.navigationBar else { return }
gradientProgressIndicatorView.fadeOut(duration: 0)
gradientProgressIndicatorView.translatesAutoresizingMaskIntoConstraints = false
navigationBar.addSubview(gradientProgressIndicatorView)
@@ -61,4 +57,24 @@ class NavigationBarExampleViewController: UIViewController {
gradientProgressIndicatorView.heightAnchor.constraint(equalToConstant: Config.height),
])
}
@IBAction private func doneButtonTapped(_: Any) {
dismiss(animated: true)
}
@IBAction private func showButtonTouchUpInside(_: Any) {
gradientProgressIndicatorView.fadeIn()
}
@IBAction private func hideButtonTouchUpInside(_: Any) {
gradientProgressIndicatorView.fadeOut()
}
}
// MARK: - Helper
struct NavigationBarExampleView: View {
var body: some View {
StoryboardView(name: "NavigationBarExample")
}
}
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Safe Area Example View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" customClass="SafeAreaExampleViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="vQo-n2-n4V" userLabel="Top Content Stack View">
<rect key="frame" x="16" y="400" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xx7-io-IHi" userLabel="ShowBasicBarButton">
<rect key="frame" x="0.0" y="0.0" width="244" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="wri-XG-tfO"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Show Basic Bar">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="showBasicBarButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="o8j-Z6-6kZ"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xxs-Xn-l65" userLabel="HideBasicBarButton">
<rect key="frame" x="260" y="0.0" width="122" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="zfx-4A-wZB"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Hide">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="hideBasicBarButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="XXK-yZ-LR4"/>
</connections>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="J6X-XZ-YZb" userLabel="Bottom Content Stack View">
<rect key="frame" x="16" y="456" width="382" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DS9-JT-RIl" userLabel="HideNotchBarButton">
<rect key="frame" x="0.0" y="0.0" width="104" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="64O-UM-b99"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Hide">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="hideNotchBarButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="INf-lf-Egt"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8wt-vv-Sj1" userLabel="ShowNotchBarButton">
<rect key="frame" x="120" y="0.0" width="262" height="40"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="40" id="nUb-HA-Cts"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Show Notch Bar">
<fontDescription key="titleFontDescription" style="UICTFontTextStyleBody"/>
</buttonConfiguration>
<connections>
<action selector="showNotchBarButtonTouchUpInside:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="aHn-BO-ovO"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="J6X-XZ-YZb" secondAttribute="trailing" constant="16" id="FLY-Rz-mWy"/>
<constraint firstItem="vQo-n2-n4V" firstAttribute="leading" secondItem="5EZ-qb-Rvc" secondAttribute="leading" constant="16" id="Vh8-QH-gYf"/>
<constraint firstItem="J6X-XZ-YZb" firstAttribute="top" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" constant="8" id="XPa-0S-CCv"/>
<constraint firstItem="J6X-XZ-YZb" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="16" id="XpT-4k-VAf"/>
<constraint firstItem="vQo-n2-n4V" firstAttribute="bottom" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" constant="-8" id="czm-UN-XEM"/>
<constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="vQo-n2-n4V" secondAttribute="trailing" constant="16" id="umO-We-0lr"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="133" y="115"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
@@ -1,19 +1,20 @@
//
// SafeAreaExampleViewController.swift
// GradientLoadingBar_Example
// Example
//
// Created by Felix Mau on 30.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import UIKit
import GradientLoadingBar
import SwiftUI
import UIKit
final class SafeAreaExampleViewController: UIViewController {
class SafeAreaExampleViewController: UIViewController {
// MARK: - Private properties
private let gradientLoadingBar = GradientLoadingBar(isRelativeToSafeArea: false)
private let notchGradientLoadingBar = NotchGradientLoadingBar(isRelativeToSafeArea: false)
// MARK: - Public methods
@@ -21,10 +22,13 @@ class SafeAreaExampleViewController: UIViewController {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Reset any possible visible loading bar.
gradientLoadingBar.fadeOut()
notchGradientLoadingBar.fadeOut()
}
// MARK: - Private methods
@IBAction private func showBasicBarButtonTouchUpInside(_: Any) {
gradientLoadingBar.fadeIn()
}
@@ -41,3 +45,12 @@ class SafeAreaExampleViewController: UIViewController {
notchGradientLoadingBar.fadeOut()
}
}
// MARK: - Helper
struct SafeAreaExampleView: View {
var body: some View {
StoryboardView(name: "SafeAreaExample")
.navigationTitle("📲 Safe Area Example")
}
}
@@ -0,0 +1,177 @@
//
// SwiftUIExampleView.swift
// Example
//
// Created by Felix Mau on 07.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import GradientLoadingBar
import SwiftUI
struct SwiftUIExampleView: View {
// MARK: - Render
var body: some View {
List {
Section(header: Text("Default example")) {
DefaultExampleView()
}
Section(header: Text("Custom colors")) {
CustomColorsExampleView()
}
Section(header: Text("Custom animation duration")) {
CustomProgressDurationExampleView()
}
}
.navigationTitle("🎨 SwiftUI Example")
}
}
// MARK: - Subviews
private struct DefaultExampleView: View {
@State
private var isVisible = true
var body: some View {
VStack(spacing: 16) {
Text("Example using the default configuration.")
.frame(maxWidth: .infinity, alignment: .leading)
GradientLoadingBarView()
.frame(maxWidth: .infinity, maxHeight: 3)
.cornerRadius(1.5)
.opacity(isVisible ? 1 : 0)
HStack(spacing: 16) {
Button("Show") {
withAnimation(.easeInOut) {
isVisible = true
}
}
.buttonStyle(RoundedRectangleButtonStyle())
Button("Hide") {
withAnimation(.easeInOut) {
isVisible = false
}
}
.buttonStyle(RoundedRectangleButtonStyle())
}
}
.padding(.horizontal, 8)
.padding(.vertical, 16)
}
}
private struct CustomColorsExampleView: View {
private enum Config {
/// The custom gradient colors we use.
/// Source: https://color.adobe.com/Pink-Flamingo-color-theme-10343714/
static let gradientColors = [
#colorLiteral(red: 0.9490196078, green: 0.3215686275, blue: 0.431372549, alpha: 1), #colorLiteral(red: 0.9450980392, green: 0.4784313725, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.9529411765, green: 0.737254902, blue: 0.7843137255, alpha: 1), #colorLiteral(red: 0.4274509804, green: 0.8666666667, blue: 0.9490196078, alpha: 1), #colorLiteral(red: 0.7568627451, green: 0.9411764706, blue: 0.9568627451, alpha: 1),
].map(Color.init)
}
@State
private var isVisible = true
var body: some View {
VStack(spacing: 16) {
Text("Example showing how to provide custom gradient colors.")
.frame(maxWidth: .infinity, alignment: .leading)
GradientLoadingBarView(gradientColors: Config.gradientColors)
.frame(maxWidth: .infinity, maxHeight: 3)
.cornerRadius(1.5)
.opacity(isVisible ? 1 : 0)
HStack(spacing: 16) {
Button("Show") {
withAnimation(.easeInOut) {
isVisible = true
}
}
.buttonStyle(RoundedRectangleButtonStyle())
Button("Hide") {
withAnimation(.easeInOut) {
isVisible = false
}
}
.buttonStyle(RoundedRectangleButtonStyle())
}
}
.padding(.horizontal, 8)
.padding(.vertical, 16)
}
}
private struct CustomProgressDurationExampleView: View {
private enum Config {
/// The custom progress duration to use.
static let progressDuration: TimeInterval = 10
}
@State
private var isVisible = true
var body: some View {
VStack(spacing: 16) {
Text("Example showing how to provide a custom progress animation duration.")
.frame(maxWidth: .infinity, alignment: .leading)
GradientLoadingBarView(progressDuration: Config.progressDuration)
.frame(maxWidth: .infinity, maxHeight: 3)
.cornerRadius(1.5)
.opacity(isVisible ? 1 : 0)
HStack(spacing: 16) {
Button("Show") {
withAnimation(.easeInOut) {
isVisible = true
}
}
.buttonStyle(RoundedRectangleButtonStyle())
Button("Hide") {
withAnimation(.easeInOut) {
isVisible = false
}
}
.buttonStyle(RoundedRectangleButtonStyle())
}
}
.padding(.horizontal, 8)
.padding(.vertical, 16)
}
}
// MARK: - Helper
private struct RoundedRectangleButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(12)
.frame(maxWidth: .infinity)
.foregroundColor(.white)
.background(Color.blue.cornerRadius(8))
.scaleEffect(configuration.isPressed ? 0.95 : 1)
}
}
// MARK: - Preview
struct SwiftUIExampleView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIExampleView()
}
}
@@ -0,0 +1,56 @@
//
// GradientActivityIndicatorViewTestCase.swift
// ExampleSnapshotTests
//
// Created by Felix Mau on 09.11.19.
// Copyright © 2019 Felix Mau. All rights reserved.
//
import SnapshotTesting
import XCTest
@testable import GradientLoadingBar
final class GradientActivityIndicatorViewTestCase: XCTestCase {
// MARK: - Config
private enum Config {
/// The frame we use for rendering the `GradientActivityIndicatorView`.
/// This will also be the image size for our snapshot.
static let frame = CGRect(origin: .zero, size: CGSize(width: 375, height: 4))
/// The custom colors we use on this test-case.
/// Source: https://color.adobe.com/Pink-Flamingo-color-theme-10343714/
static let gradientColors = [
#colorLiteral(red: 0.9490196078, green: 0.3215686275, blue: 0.431372549, alpha: 1), #colorLiteral(red: 0.9450980392, green: 0.4784313725, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.9529411765, green: 0.737254902, blue: 0.7843137255, alpha: 1), #colorLiteral(red: 0.4274509804, green: 0.8666666667, blue: 0.9490196078, alpha: 1), #colorLiteral(red: 0.7568627451, green: 0.9411764706, blue: 0.9568627451, alpha: 1),
]
}
// MARK: - Test cases
func test_gradientActivityIndicatorView_shouldContainCorrectDefaultColors() {
// Given
let gradientActivityIndicatorView = GradientActivityIndicatorView(frame: Config.frame)
// We're only interested in the initial state containing the correct gradient-colors.
// Therefore we're gonna remove the progress animation.
gradientActivityIndicatorView.layer.removeAllAnimations()
// Then
assertSnapshot(matching: gradientActivityIndicatorView, as: .image)
}
func test_gradientActivityIndicatorView_shouldContainCorrectCustomColors() {
// Given
let gradientActivityIndicatorView = GradientActivityIndicatorView(frame: Config.frame)
gradientActivityIndicatorView.gradientColors = Config.gradientColors
// We're only interested in the initial state containing the correct gradient-colors.
// Therefore we're gonna remove the progress animation.
gradientActivityIndicatorView.layer.removeAllAnimations()
// Then
assertSnapshot(matching: gradientActivityIndicatorView, as: .image)
}
}
@@ -0,0 +1,56 @@
//
// GradientLoadingBarControllerTestCase.swift
// ExampleSnapshotTests
//
// Created by Felix Mau on 14.06.20.
// Copyright © 2020 Felix Mau. All rights reserved.
//
import SnapshotTesting
import XCTest
@testable import GradientLoadingBar
final class GradientLoadingBarControllerTestCase: XCTestCase {
// MARK: - Private properties
private var window: UIWindow!
// MARK: - Public methods
override func setUp() {
super.setUp()
window = UIApplication.shared.keyWindowInConnectedScenes
}
override func tearDown() {
window = nil
super.tearDown()
}
// MARK: - Test cases
func test_gradientLoadingBarController() {
// Given
// Show an empty view controller behind loading bar in our test.
let rootViewController = UIViewController()
window.rootViewController = rootViewController
let expectation = expectation(description: "Expect view to be completely visible.")
// When
let gradientLoadingBarController = GradientLoadingBarController()
gradientLoadingBarController.fadeIn(duration: 0) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.1)
// Workaround, as snapshotting a `UIWindow` is currently not supported and crashes when running all tests.
assertSnapshot(matching: window.layer, as: .image)
}
}
@@ -0,0 +1,53 @@
//
// GradientLoadingBarViewTestCase.swift
// ExampleSnapshotTests
//
// Created by Felix Mau on 10.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import SnapshotTesting
import SwiftUI
import XCTest
@testable import GradientLoadingBar
final class GradientLoadingBarViewTestCase: XCTestCase {
// MARK: - Config
private enum Config {
/// The frame we use for rendering the `GradientLoadingBarView`.
/// This will also be the image size for our snapshot.
static let frame = CGRect(origin: .zero, size: CGSize(width: 375, height: 4))
/// The custom colors we use on this test-case.
/// Source: https://color.adobe.com/Pink-Flamingo-color-theme-10343714/
static let gradientColors = [
#colorLiteral(red: 0.9490196078, green: 0.3215686275, blue: 0.431372549, alpha: 1), #colorLiteral(red: 0.9450980392, green: 0.4784313725, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.9529411765, green: 0.737254902, blue: 0.7843137255, alpha: 1), #colorLiteral(red: 0.4274509804, green: 0.8666666667, blue: 0.9490196078, alpha: 1), #colorLiteral(red: 0.7568627451, green: 0.9411764706, blue: 0.9568627451, alpha: 1),
].map(Color.init)
/// The percentage of pixels that must match.
static let precision: Float = 0.98
}
// MARK: - Test cases
func test_gradientLoadingBarView_shouldContainCorrectDefaultColors() {
// Given
let gradientLoadingBarView = GradientLoadingBarView()
.frame(width: Config.frame.width, height: Config.frame.height)
// Then
assertSnapshot(matching: gradientLoadingBarView, as: .image(precision: Config.precision))
}
func test_gradientLoadingBarView_shouldContainCorrectCustomColors() {
// Given
let gradientLoadingBarView = GradientLoadingBarView(gradientColors: Config.gradientColors)
.frame(width: Config.frame.width, height: Config.frame.height)
// Then
assertSnapshot(matching: gradientLoadingBarView, as: .image(precision: Config.precision))
}
}
@@ -0,0 +1,57 @@
//
// NotchGradientLoadingBarControllerTestCase.swift
// ExampleSnapshotTests
//
// Created by Felix Mau on 14.06.20.
// Copyright © 2020 Felix Mau. All rights reserved.
//
import SnapshotTesting
import XCTest
@testable import GradientLoadingBar
final class NotchGradientLoadingBarControllerTestCase: XCTestCase {
// swiftlint:disable:previous type_name
// MARK: - Private properties
private var window: UIWindow!
// MARK: - Public methods
override func setUp() {
super.setUp()
window = UIApplication.shared.keyWindowInConnectedScenes
}
override func tearDown() {
window = nil
super.tearDown()
}
// MARK: - Test cases
func test_notchGradientLoadingBarController() {
// Given
// Show an empty view controller behind loading bar in our test.
let rootViewController = UIViewController()
window.rootViewController = rootViewController
let expectation = expectation(description: "Expect view to be completely visible.")
// When
let gradientLoadingBarController = NotchGradientLoadingBarController()
gradientLoadingBarController.fadeIn(duration: 0) { _ in
expectation.fulfill()
}
// Then
wait(for: [expectation], timeout: 0.1)
// Workaround, as snapshotting a `UIWindow` is currently not supported and crashes when running all tests.
assertSnapshot(matching: window.layer, as: .image)
}
}
+4
View File
@@ -0,0 +1,4 @@
# Snapshot-Tests
## Device
Run test-cases with the `iPhone 13` using `iOS 15.5`.
@@ -1,6 +1,6 @@
//
// GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift
// GradientLoadingBar_Tests
// ExampleTests
//
// Created by Felix Mau on 19.05.19.
// Copyright © 2017 Felix Mau. All rights reserved.
@@ -11,7 +11,8 @@ import XCTest
@testable import GradientLoadingBar
// swiftlint:disable:next type_name
class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
final class GradientActivityIndicatorView_AnimateIsHiddenTestCase: XCTestCase {
// MARK: - Private properties
private var window: UIWindow!
@@ -24,7 +25,7 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
// In order for UIView animations to be executed correctly, the corresponding view has to be attached to a visible window.
// Therefore we're gonna use the current key-window, add our testing view here in `setUp()` and remove it later in `tearDown()`.
window = UIApplication.shared.windows.first { $0.isKeyWindow }
window = UIApplication.shared.keyWindowInConnectedScenes
gradientActivityIndicatorView = GradientActivityIndicatorView()
window.addSubview(gradientActivityIndicatorView)
@@ -41,9 +42,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
// MARK: - Test method `animate(isHidden:)`
func testAnimateIsHiddenShouldShowViewAndCallCompletionHandler() {
func test_animateIsHidden_shouldShowView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// Hide view to validate fade-in.
gradientActivityIndicatorView.alpha = 0
@@ -59,12 +60,12 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
wait(for: [expectation], timeout: 1)
XCTAssertFalse(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1, accuracy: CGFloat.ulpOfOne)
}
func testAnimateIsHiddenWithInterruptionShouldShowViewAndCallCompletionHandler() {
func test_animateIsHidden_withInterruption_shouldShowView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// Hide view to validate fade-in.
gradientActivityIndicatorView.alpha = 0
@@ -85,9 +86,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
XCTAssertFalse(gradientActivityIndicatorView.isHidden)
}
func testAnimateIsHiddenShouldHideViewAndCallCompletionHandler() {
func test_animateIsHidden_shouldHideView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// When
gradientActivityIndicatorView.animate(isHidden: true, duration: 0.1) { isFinished in
@@ -102,9 +103,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
XCTAssertEqual(gradientActivityIndicatorView.alpha, 0, accuracy: CGFloat.ulpOfOne)
}
func testAnimateIsHiddenWithInterruptionShouldNotHideViewAndCallCompletionHandler() {
func test_animateIsHidden_withInterruption_shouldNotHideView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// When
gradientActivityIndicatorView.animate(isHidden: true, duration: 0.1) { isFinished in
@@ -123,9 +124,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
// MARK: - Test method `fadeIn()`
func testFadeInShouldShowViewAndCallCompletionHandler() {
func test_fadeIn_shouldShowView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// Hide view to validate fade-in.
gradientActivityIndicatorView.alpha = 0
@@ -141,12 +142,12 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
wait(for: [expectation], timeout: 1)
XCTAssertFalse(gradientActivityIndicatorView.isHidden)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1.0, accuracy: CGFloat.ulpOfOne)
XCTAssertEqual(gradientActivityIndicatorView.alpha, 1, accuracy: CGFloat.ulpOfOne)
}
func testFadeInWithInterruptionShouldShowViewAndCallCompletionHandler() {
func test_fadeIn_withInterruption_shouldShowView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// Hide view to validate fade-in.
gradientActivityIndicatorView.alpha = 0
@@ -169,9 +170,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
// MARK: - Test method `fadeOut()`
func testFadeOutShouldHideViewAndCallCompletionHandler() {
func test_fadeOut_shouldHideView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// When
gradientActivityIndicatorView.fadeOut(duration: 0.1) { isFinished in
@@ -186,9 +187,9 @@ class GradientActivityIndicatorViewAnimateIsHiddenTestCase: XCTestCase {
XCTAssertEqual(gradientActivityIndicatorView.alpha, 0, accuracy: CGFloat.ulpOfOne)
}
func testFadeOutWithInterruptionShouldNotHideViewAndCallCompletionHandler() {
func test_fadeOut_withInterruption_shouldNotHideView_andCallCompletionHandler() {
// Given
let expectation = self.expectation(description: "Expect completion handler to be called.")
let expectation = expectation(description: "Expect completion handler to be invoked.")
// When
gradientActivityIndicatorView.fadeOut(duration: 0.1) { isFinished in
@@ -0,0 +1,53 @@
//
// GradientActivityIndicatorViewModel+SizeUpdateTestCase.swift
// ExampleTests
//
// Created by Felix Mau on 18.08.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import XCTest
@testable import GradientLoadingBar
// swiftlint:disable:next type_name
final class GradientActivityIndicatorViewModel_SizeUpdateTestCase: XCTestCase {
// MARK: - Test property `frame`
func test_frame() {
// Given
let bounds = CGRect(x: 0,
y: 0,
width: .random(in: 0 ... .max),
height: .random(in: 0 ... .max))
// When
let sizeUpdate = GradientActivityIndicatorViewModel.SizeUpdate(bounds: bounds)
// Then
let expectedFrame = CGRect(x: 0,
y: 0,
width: bounds.width * 3,
height: bounds.height)
XCTAssertEqual(sizeUpdate.frame, expectedFrame)
}
// MARK: - Test property `fromValue`
func test_fromValue() {
// Given
let bounds = CGRect(x: 0,
y: 0,
width: .random(in: 0 ... .max),
height: .random(in: 0 ... .max))
// When
let sizeUpdate = GradientActivityIndicatorViewModel.SizeUpdate(bounds: bounds)
// Then
let expectedFromValue = bounds.width * -2
XCTAssertEqual(sizeUpdate.fromValue, expectedFromValue)
}
}
@@ -0,0 +1,215 @@
//
// GradientActivityIndicatorViewModelTestCase.swift
// ExampleTests
//
// Created by Felix Mau on 26.08.19.
// Copyright © 2019 Felix Mau. All rights reserved.
//
import LightweightObservable
import XCTest
@testable import GradientLoadingBar
// swiftlint:disable:next type_name
final class GradientActivityIndicatorViewModelTestCase: XCTestCase {
// MARK: - Private properties
private var viewModel: GradientActivityIndicatorViewModel!
// MARK: - Public methods
override func setUp() {
super.setUp()
viewModel = GradientActivityIndicatorViewModel()
}
override func tearDown() {
viewModel = nil
super.tearDown()
}
// MARK: - Test property `isHidden`
func test_settingIsHidden_toTrue_shouldUpdateIsAnimatingSubject_withFalse() throws {
// Given
var receivedIsAnimating: Bool?
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating = isAnimating
}
// When
withExtendedLifetime(disposable) {
viewModel.isHidden = true
}
// Then
XCTAssertFalse(
try XCTUnwrap(receivedIsAnimating, "Expected to have received a value from the subscription closure at this point.")
)
}
func test_settingIsHidden_toFalse_shouldUpdateIsAnimatingSubject_withTrue() throws {
// Given
var receivedIsAnimating: Bool?
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating = isAnimating
}
// When
withExtendedLifetime(disposable) {
viewModel.isHidden = false
}
// Then
XCTAssertTrue(
try XCTUnwrap(receivedIsAnimating, "Expected to have received a value from the subscription closure at this point.")
)
}
// MARK: - Test property `bounds`
func test_settingBounds_shouldUpdateGradientLayerSizeUpdate() {
// Given
var receivedSizeUpdate: GradientActivityIndicatorViewModel.SizeUpdate?
let disposable = viewModel.gradientLayerSizeUpdate.subscribe { sizeUpdate, _ in
receivedSizeUpdate = sizeUpdate
}
let size = CGSize(width: .random(in: 1 ... 100), height: .random(in: 1 ... 100))
let bounds = CGRect(origin: .zero, size: size)
// When
withExtendedLifetime(disposable) {
viewModel.bounds = bounds
}
// Then
let expectedSizeUpdate = GradientActivityIndicatorViewModel.SizeUpdate(bounds: bounds)
XCTAssertEqual(receivedSizeUpdate, expectedSizeUpdate)
}
func test_settingBounds_shouldRestartAnimation() {
// Given
var receivedIsAnimating = [Bool]()
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating.append(isAnimating)
}
receivedIsAnimating.removeAll()
let size = CGSize(width: .random(in: 1 ... 100), height: .random(in: 1 ... 100))
let bounds = CGRect(origin: .zero, size: size)
// When
withExtendedLifetime(disposable) {
viewModel.bounds = bounds
}
// Then
let expectedIsAnimating = [false, true]
XCTAssertEqual(receivedIsAnimating, expectedIsAnimating)
}
func test_settingBounds_shouldNotRestartAnimation_dueToViewIsHidden() {
// Given
var receivedIsAnimating = [Bool]()
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating.append(isAnimating)
}
let size = CGSize(width: .random(in: 1 ... 100), height: .random(in: 1 ... 100))
let bounds = CGRect(origin: .zero, size: size)
viewModel.isHidden = true
receivedIsAnimating.removeAll()
// When
withExtendedLifetime(disposable) {
viewModel.bounds = bounds
}
// Then
XCTAssertTrue(receivedIsAnimating.isEmpty)
}
// MARK: - Test property `gradientColors`
func test_settingGradientColors_shouldUpdateGradientLayerColors() {
// Given
var receivedGradientLayerColors: [CGColor]?
let disposable = viewModel.gradientLayerColors.subscribe { gradientLayerColors, _ in
receivedGradientLayerColors = gradientLayerColors
}
let gradientColors: [UIColor] = [.red, .yellow, .green]
// When
withExtendedLifetime(disposable) {
viewModel.gradientColors = gradientColors
}
// Then
let expectedGradientLayerColors = [UIColor.red, .yellow, .green, .yellow, .red, .yellow, .green].map(\.cgColor)
XCTAssertEqual(receivedGradientLayerColors, expectedGradientLayerColors)
}
// MARK: - Test property `progressAnimationDuration`
func test_settingProgressAnimationDuration_shouldUpdateGradientLayerAnimationDuration() {
// Given
var receivedGradientLayerAnimationDuration: TimeInterval?
let disposable = viewModel.gradientLayerAnimationDuration.subscribe { gradientLayerAnimationDuration, _ in
receivedGradientLayerAnimationDuration = gradientLayerAnimationDuration
}
let progressAnimationDuration: TimeInterval = .random(in: 0 ... 100)
// When
withExtendedLifetime(disposable) {
viewModel.progressAnimationDuration = progressAnimationDuration
}
// Then
XCTAssertEqual(receivedGradientLayerAnimationDuration, progressAnimationDuration)
}
func test_settingProgressAnimationDuration_shouldRestartAnimation() {
// Given
var receivedIsAnimating = [Bool]()
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating.append(isAnimating)
}
receivedIsAnimating.removeAll()
// When
withExtendedLifetime(disposable) {
viewModel.progressAnimationDuration = .random(in: 0 ... 100)
}
// Then
let expectedIsAnimating = [false, true]
XCTAssertEqual(receivedIsAnimating, expectedIsAnimating)
}
func test_settingProgressAnimationDuration_shouldNotRestartAnimation_dueToViewIsHidden() {
// Given
var receivedIsAnimating = [Bool]()
let disposable = viewModel.isAnimating.subscribe { isAnimating, _ in
receivedIsAnimating.append(isAnimating)
}
viewModel.isHidden = true
receivedIsAnimating.removeAll()
// When
withExtendedLifetime(disposable) {
viewModel.progressAnimationDuration = .random(in: 0 ... 100)
}
// Then
XCTAssertTrue(receivedIsAnimating.isEmpty)
}
}
@@ -1,17 +1,18 @@
//
// GradientLoadingBarViewModelTestCase.swift
// GradientLoadingBar_Tests
// ExampleTests
//
// Created by Felix Mau on 26.12.17.
// Copyright © 2017 Felix Mau. All rights reserved.
//
import XCTest
import LightweightObservable
import XCTest
@testable import GradientLoadingBar
class GradientLoadingBarViewModelTestCase: XCTestCase {
final class GradientLoadingBarViewModelTestCase: XCTestCase {
// MARK: - Private properties
private var sharedApplicationMock: SharedApplicationMock!
@@ -35,23 +36,21 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
// MARK: - Test observable `superview`
func testInitializerShouldSetupSuperviewObservableNil() throws {
func test_init_shouldSetupSuperviewObservable_withNil() throws {
// When
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
// Then
let variable = try XCTUnwrap(viewModel.superview as? Variable, "Cast `Observable` instance to `Variable` in order to validate the initial value.")
XCTAssertNil(variable.value)
// The property `superview` is an optional, as well as the property `value`.
// Therefore we can't use `XCTAssertNil` here, as this doesn't work with double optionals.
XCTAssertEqual(viewModel.superview.value, .some(nil))
}
func testInitializerShouldSetupSuperviewObservableWithKeyWindow() {
func test_init_shouldSetupSuperviewObservable_withKeyWindow() {
// Given
let keyWindow = UIWindow()
keyWindow.makeKey()
let otherWindow = UIWindow()
sharedApplicationMock.windows = [keyWindow, otherWindow]
sharedApplicationMock.keyWindowInConnectedScenes = keyWindow
// When
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
@@ -61,61 +60,55 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
XCTAssertEqual(viewModel.superview.value, keyWindow)
}
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotification() {
func test_init_shouldSetupSuperviewObservable_afterUIWindowDidBecomeKeyNotification() {
// Given
let keyWindow = UIWindow()
keyWindow.makeKey()
let otherWindow = UIWindow()
sharedApplicationMock.windows = [otherWindow]
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
var receivedKeyWindows = [UIView?]()
let disposable = viewModel.superview.subscribe { keyWindow, _ in
receivedKeyWindows.append(keyWindow)
}
let keyWindow = UIWindow()
sharedApplicationMock.keyWindowInConnectedScenes = keyWindow
// When
sharedApplicationMock.windows.append(keyWindow)
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
object: nil)
withExtendedLifetime(disposable) {
notificationCenter.post(name: UIWindow.didBecomeKeyNotification, object: nil)
}
// Then
XCTAssertEqual(viewModel.superview.value, keyWindow)
let expectedKeyWindows = [nil, keyWindow]
XCTAssertEqual(receivedKeyWindows, expectedKeyWindows)
}
func testDeinitShouldResetSuperviewObservableToNil() {
func test_deinit_shouldResetSuperviewObservable_withNil() {
// Given
let keyWindow = UIWindow()
keyWindow.makeKey()
let otherWindow = UIWindow()
sharedApplicationMock.windows = [keyWindow, otherWindow]
sharedApplicationMock.keyWindowInConnectedScenes = keyWindow
var viewModel: GradientLoadingBarViewModel? = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
notificationCenter: notificationCenter)
let expectation = self.expectation(description: "Expected observer to be informed to reset superview to nil.")
var disposeBag = DisposeBag()
// As we've just initialized the view model it has to exist at this point, and therefore we can "safely" use force-unwrapping here.
// swiftlint:disable:next force_unwrapping
viewModel!.superview.subscribe { newSuperview, _ in
guard newSuperview == nil else {
// Skip initial call to observer.
return
}
expectation.fulfill()
}.disposed(by: &disposeBag)
var receivedKeyWindows = [UIView?]()
let disposable = viewModel?.superview.subscribe { keyWindow, _ in
receivedKeyWindows.append(keyWindow)
}
// When
viewModel = nil
withExtendedLifetime(disposable) {
viewModel = nil
}
// Then
wait(for: [expectation], timeout: 0.1)
let expectedKeyWindows = [keyWindow, nil]
XCTAssertEqual(receivedKeyWindows, expectedKeyWindows)
}
}
// MARK: - Mocks
private class SharedApplicationMock: UIApplicationProtocol {
var windows = [UIWindow]()
private final class SharedApplicationMock: UIApplicationProtocol {
var keyWindowInConnectedScenes: UIWindow?
}
@@ -0,0 +1,82 @@
//
// GradientLoadingBarView+ViewModelTestCase.swift
// ExampleTests
//
// Created by Felix Mau on 22.03.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import SwiftUI
import XCTest
@testable import GradientLoadingBar
// swiftlint:disable:next type_name
final class GradientLoadingBarView_ViewModelTestCase: XCTestCase {
// MARK: - Test property `gradientColors`
func test_initialGradientColors_shouldIncludeReversedGradientColors() {
// Given
let gradientColors: [Color] = [.red, .yellow, .green]
// When
let viewModel = GradientLoadingBarView.ViewModel(gradientColors: gradientColors, progressDuration: 1)
// Then
let expectedGradientColors: [Color] = [.red, .yellow, .green, .yellow, .red, .yellow, .green]
XCTAssertEqual(viewModel.gradientColors, expectedGradientColors)
}
// MARK: - Test property `horizontalOffset`
func test_initialHorizontalOffset_shouldBeZero() {
// When
let viewModel = GradientLoadingBarView.ViewModel(gradientColors: [], progressDuration: 1)
// Then
XCTAssertEqual(viewModel.horizontalOffset, 0)
}
func test_settingSize_shouldUpdateHorizontalOffset() {
// Given
let viewModel = GradientLoadingBarView.ViewModel(gradientColors: [], progressDuration: 1)
let size = CGSize(width: .random(in: 1 ... 100_000), height: .random(in: 1 ... 100_000))
var receivedValues = [CGFloat]()
let subscription = viewModel.$horizontalOffset.sink {
receivedValues.append($0)
}
withExtendedLifetime(subscription) {
// When
viewModel.size = size
}
// Then
let expectedValues = [0, -size.width, size.width]
XCTAssertEqual(receivedValues, expectedValues)
}
// MARK: - Test property `gradientWidth`
func test_initialGradientWidth_shouldBeZero() {
// When
let viewModel = GradientLoadingBarView.ViewModel(gradientColors: [], progressDuration: 1)
// Then
XCTAssertEqual(viewModel.gradientWidth, 0)
}
func test_settingSize_shouldUpdateGradientWidth() {
// Given
let viewModel = GradientLoadingBarView.ViewModel(gradientColors: [], progressDuration: 1)
let size = CGSize(width: .random(in: 1 ... 100_000), height: .random(in: 1 ... 100_000))
// When
viewModel.size = size
// Then
XCTAssertEqual(viewModel.gradientWidth, size.width * 3)
}
}
@@ -0,0 +1,58 @@
//
// NotchGradientLoadingBarViewModelTestCase.swift
// ExampleTests
//
// Created by Felix Mau on 26.12.17.
// Copyright © 2017 Felix Mau. All rights reserved.
//
import XCTest
@testable import GradientLoadingBar
final class NotchGradientLoadingBarViewModelTestCase: XCTestCase {
func test_initializer_shouldSetCorrectNotchDevice() {
// Given
let identifiersToNotchDeviceMap: [String: NotchGradientLoadingBarViewModel.NotchDevice] = [
"iPhone10,3": .iPhoneX,
"iPhone10,6": .iPhoneX,
"iPhone11,2": .iPhoneXS,
"iPhone11,4": .iPhoneXSMax,
"iPhone11,6": .iPhoneXSMax,
"iPhone11,8": .iPhoneXR,
"iPhone12,1": .iPhone11,
"iPhone12,3": .iPhone11Pro,
"iPhone12,5": .iPhone11ProMax,
"iPhone13,1": .iPhone12Mini,
"iPhone13,2": .iPhone12,
"iPhone13,3": .iPhone12Pro,
"iPhone13,4": .iPhone12ProMax,
"iPhone14,4": .iPhone13Mini,
"iPhone14,5": .iPhone13,
"iPhone14,2": .iPhone13Pro,
"iPhone14,3": .iPhone13ProMax,
"iPhone14,7": .iPhone14,
"iPhone14,8": .iPhone14Plus,
]
identifiersToNotchDeviceMap.forEach { deviceIdentifier, notchDevice in
// When
let viewModel = NotchGradientLoadingBarViewModel(deviceIdentifier: deviceIdentifier)
// Then
XCTAssertEqual(viewModel.notchDevice, notchDevice)
}
}
func test_initializer_shouldSetNotchDevice_toNil() {
// Given
let deviceIdentifier = "Foo-Bar-🤡"
// When
let viewModel = NotchGradientLoadingBarViewModel(deviceIdentifier: deviceIdentifier)
// Then
XCTAssertNil(viewModel.notchDevice)
}
}
+62 -58
View File
@@ -3,41 +3,41 @@ GEM
specs:
CFPropertyList (3.0.5)
rexml
activesupport (6.1.4.1)
activesupport (6.1.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.539.0)
aws-sdk-core (3.124.0)
aws-partitions (1.626.0)
aws-sdk-core (3.141.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.52.0)
aws-sdk-core (~> 3, >= 3.122.0)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.58.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.109.0)
aws-sdk-core (~> 3, >= 3.122.0)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.4.0)
aws-sigv4 (1.5.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
cocoapods (1.11.2)
claide (1.1.0)
cocoapods (1.11.3)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.2)
cocoapods-core (= 1.11.3)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
@@ -52,7 +52,7 @@ GEM
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.2)
cocoapods-core (1.11.3)
activesupport (>= 5.0, < 7)
addressable (~> 2.8)
algoliasearch (~> 1.0)
@@ -63,7 +63,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.5.1)
cocoapods-downloader (1.6.3)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@@ -75,28 +75,29 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.1.9)
concurrent-ruby (1.1.10)
declarative (0.0.20)
digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
dotenv (2.8.1)
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.15.0)
ffi (>= 1.15.0)
excon (0.88.0)
faraday (1.8.0)
excon (0.92.4)
faraday (1.10.2)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
@@ -105,14 +106,17 @@ GEM
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.5)
fastlane (2.198.1)
fastimage (2.2.6)
fastlane (2.209.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -151,14 +155,14 @@ GEM
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-swiftformat (0.1.0)
ffi (1.15.4)
fastlane-plugin-swiftformat (0.3.0)
ffi (1.15.5)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.13.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.4.1)
google-apis-androidpublisher_v3 (0.25.0)
google-apis-core (>= 0.7, < 2.a)
google-apis-core (0.7.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@@ -167,46 +171,46 @@ GEM
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.8.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.6.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.9.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-iamcredentials_v1 (0.13.0)
google-apis-core (>= 0.7, < 2.a)
google-apis-playcustomapp_v1 (0.10.0)
google-apis-core (>= 0.7, < 2.a)
google-apis-storage_v1 (0.17.0)
google-apis-core (>= 0.7, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.34.1)
addressable (~> 2.5)
google-cloud-storage (1.39.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.17.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.1.0)
faraday (>= 0.17.3, < 2.0)
googleauth (1.2.0)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.4)
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.8.11)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jmespath (1.4.0)
json (2.6.1)
jwt (2.3.0)
jmespath (1.6.1)
json (2.6.2)
jwt (2.5.0)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.2)
minitest (5.14.4)
minitest (5.16.3)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.0.0)
@@ -217,9 +221,9 @@ GEM
optparse (0.1.1)
os (1.1.4)
plist (3.6.0)
public_suffix (4.0.6)
public_suffix (4.0.7)
rake (13.0.6)
representable (3.1.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
@@ -230,9 +234,9 @@ GEM
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.16.0)
signet (0.17.0)
addressable (~> 2.8)
faraday (>= 0.17.3, < 2.0)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
@@ -248,16 +252,16 @@ GEM
tty-cursor (~> 0.7)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8)
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.21.0)
xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
@@ -268,7 +272,7 @@ GEM
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
zeitwerk (2.5.1)
zeitwerk (2.6.0)
PLATFORMS
ruby
@@ -279,4 +283,4 @@ DEPENDENCIES
fastlane-plugin-swiftformat
BUNDLED WITH
2.1.4
2.3.18
@@ -1,903 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
397E9F2412E802485B755A87 /* Pods_GradientLoadingBar_SnapshotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABA9B1EF5F3928BA6E31D3EA /* Pods_GradientLoadingBar_SnapshotTests.framework */; };
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
607FACD81AFB9204008FA782 /* BasicExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* BasicExampleViewController.swift */; };
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
640E8AC0231457620008C5A6 /* GradientActivityIndicatorViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640E8ABF231457620008C5A6 /* GradientActivityIndicatorViewModelTestCase.swift */; };
6430C3A32338F1CA001F4A33 /* LargeNavigationBarHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6430C3A22338F1CA001F4A33 /* LargeNavigationBarHeaderView.swift */; };
649A163C23770B4400404F3C /* DefaultColorSnapshotTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649A163B23770B4400404F3C /* DefaultColorSnapshotTestCase.swift */; };
649A164423770E9300404F3C /* CustomColorSnapshotTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649A164323770E9300404F3C /* CustomColorSnapshotTestCase.swift */; };
64C596EC2351D80000A6CC97 /* InterfaceBuilderExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C596EB2351D7FF00A6CC97 /* InterfaceBuilderExampleViewController.swift */; };
64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */; };
64E7F4252293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */; };
77357BD34CFF2778341F80E8 /* Pods_GradientLoadingBar_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03CD5D69D7C3FBBDBF5FABBB /* Pods_GradientLoadingBar_Example.framework */; };
8020C040972E902A8CCAA9E7 /* Pods_GradientLoadingBar_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 434E3C8A6E245A38C2831E73 /* Pods_GradientLoadingBar_Tests.framework */; };
972CFBCC2138849A006F14C9 /* SafeAreaExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */; };
97464E6721372BCD0097183A /* AdvancedExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */; };
97464E6921372C010097183A /* NavigationBarExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97464E6821372C010097183A /* NavigationBarExampleViewController.swift */; };
97B6F5FE2143F31F008CFEA5 /* UIColor+CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FA2143F31F008CFEA5 /* UIColor+CustomColors.swift */; };
97B6F5FF2143F31F008CFEA5 /* BlueFilledButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FC2143F31F008CFEA5 /* BlueFilledButton.swift */; };
97B6F6002143F31F008CFEA5 /* BlueBorderedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97B6F5FD2143F31F008CFEA5 /* BlueBorderedButton.swift */; };
DC190F622496A25A0069E2B0 /* NotchGradientLoadingBarControllerTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC190F602496A24F0069E2B0 /* NotchGradientLoadingBarControllerTestCase.swift */; };
DC9FF938270A470D0065B5B9 /* NotchGradientLoadingBarViewModelTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9FF937270A470D0065B5B9 /* NotchGradientLoadingBarViewModelTestCase.swift */; };
DCE3AB13249761B300889FFA /* Snapshotting+WindowedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE3AB11249761AB00889FFA /* Snapshotting+WindowedImage.swift */; };
DCE3AB16249764BB00889FFA /* GradientLoadingBarControllerTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE3AB14249764A000889FFA /* GradientLoadingBarControllerTestCase.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 607FACCF1AFB9204008FA782;
remoteInfo = GradientLoadingBar;
};
649A163E23770B4400404F3C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 607FACCF1AFB9204008FA782;
remoteInfo = GradientLoadingBar_Example;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
03CD5D69D7C3FBBDBF5FABBB /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0E24EC094BE0798D462B5F96 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
14959BE5652C9E83FC09BBDD /* Pods-GradientLoadingBar_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.release.xcconfig"; sourceTree = "<group>"; };
172FD3755BEBFF66683F5D81 /* Pods-GradientLoadingBar_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.release.xcconfig"; sourceTree = "<group>"; };
3DC26E6D2B0C63183F508578 /* Pods-GradientLoadingBar_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example.debug.xcconfig"; sourceTree = "<group>"; };
434E3C8A6E245A38C2831E73 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD01AFB9204008FA782 /* GradientLoadingBar_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GradientLoadingBar_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
607FACD71AFB9204008FA782 /* BasicExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicExampleViewController.swift; sourceTree = "<group>"; };
607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
607FACE51AFB9204008FA782 /* GradientLoadingBar_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GradientLoadingBar_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
640E8ABF231457620008C5A6 /* GradientActivityIndicatorViewModelTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientActivityIndicatorViewModelTestCase.swift; sourceTree = "<group>"; };
6430C3A22338F1CA001F4A33 /* LargeNavigationBarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeNavigationBarHeaderView.swift; sourceTree = "<group>"; };
649A163923770B4400404F3C /* GradientLoadingBar_SnapshotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GradientLoadingBar_SnapshotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
649A163B23770B4400404F3C /* DefaultColorSnapshotTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultColorSnapshotTestCase.swift; sourceTree = "<group>"; };
649A163D23770B4400404F3C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
649A164323770E9300404F3C /* CustomColorSnapshotTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomColorSnapshotTestCase.swift; sourceTree = "<group>"; };
64C596EB2351D7FF00A6CC97 /* InterfaceBuilderExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceBuilderExampleViewController.swift; sourceTree = "<group>"; };
64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModelTestCase.swift; sourceTree = "<group>"; };
64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift"; sourceTree = "<group>"; };
972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeAreaExampleViewController.swift; sourceTree = "<group>"; };
97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedExampleViewController.swift; sourceTree = "<group>"; };
97464E6821372C010097183A /* NavigationBarExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarExampleViewController.swift; sourceTree = "<group>"; };
97B6F5FA2143F31F008CFEA5 /* UIColor+CustomColors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+CustomColors.swift"; sourceTree = "<group>"; };
97B6F5FC2143F31F008CFEA5 /* BlueFilledButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlueFilledButton.swift; sourceTree = "<group>"; };
97B6F5FD2143F31F008CFEA5 /* BlueBorderedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlueBorderedButton.swift; sourceTree = "<group>"; };
A98CA9F1B0C1BD6864C14E01 /* Pods-GradientLoadingBar_SnapshotTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_SnapshotTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_SnapshotTests/Pods-GradientLoadingBar_SnapshotTests.release.xcconfig"; sourceTree = "<group>"; };
ABA9B1EF5F3928BA6E31D3EA /* Pods_GradientLoadingBar_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C06CA4DFA1DCB931095ABD3D /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = GradientLoadingBar.podspec; path = ../GradientLoadingBar.podspec; sourceTree = "<group>"; };
DC190F602496A24F0069E2B0 /* NotchGradientLoadingBarControllerTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotchGradientLoadingBarControllerTestCase.swift; sourceTree = "<group>"; };
DC9FF937270A470D0065B5B9 /* NotchGradientLoadingBarViewModelTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotchGradientLoadingBarViewModelTestCase.swift; sourceTree = "<group>"; };
DCE3AB11249761AB00889FFA /* Snapshotting+WindowedImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Snapshotting+WindowedImage.swift"; sourceTree = "<group>"; };
DCE3AB14249764A000889FFA /* GradientLoadingBarControllerTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarControllerTestCase.swift; sourceTree = "<group>"; };
DCE3AB172497670400889FFA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
E7B292793F03D669ACAA92D2 /* Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_SnapshotTests/Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig"; sourceTree = "<group>"; };
F76834BE9E43CA11377EC030 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
FECB95A4857728345199461F /* Pods-GradientLoadingBar_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GradientLoadingBar_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GradientLoadingBar_Tests/Pods-GradientLoadingBar_Tests.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
607FACCD1AFB9204008FA782 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
77357BD34CFF2778341F80E8 /* Pods_GradientLoadingBar_Example.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE21AFB9204008FA782 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8020C040972E902A8CCAA9E7 /* Pods_GradientLoadingBar_Tests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
649A163623770B4400404F3C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
397E9F2412E802485B755A87 /* Pods_GradientLoadingBar_SnapshotTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
607FACC71AFB9204008FA782 = {
isa = PBXGroup;
children = (
607FACF51AFB993E008FA782 /* Podspec Metadata */,
607FACD21AFB9204008FA782 /* Example for GradientLoadingBar */,
607FACE81AFB9204008FA782 /* Tests */,
649A163A23770B4400404F3C /* SnapshotTests */,
607FACD11AFB9204008FA782 /* Products */,
BFC08F9E633527E553EDA250 /* Pods */,
DB185876CEF7C6517EB25B58 /* Frameworks */,
);
sourceTree = "<group>";
};
607FACD11AFB9204008FA782 /* Products */ = {
isa = PBXGroup;
children = (
607FACD01AFB9204008FA782 /* GradientLoadingBar_Example.app */,
607FACE51AFB9204008FA782 /* GradientLoadingBar_Tests.xctest */,
649A163923770B4400404F3C /* GradientLoadingBar_SnapshotTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
607FACD21AFB9204008FA782 /* Example for GradientLoadingBar */ = {
isa = PBXGroup;
children = (
97B6F5F92143F31F008CFEA5 /* Extensions */,
97B6F5FB2143F31F008CFEA5 /* Views */,
607FACD71AFB9204008FA782 /* BasicExampleViewController.swift */,
972CFBCB2138849A006F14C9 /* SafeAreaExampleViewController.swift */,
64C596EB2351D7FF00A6CC97 /* InterfaceBuilderExampleViewController.swift */,
97464E6621372BCD0097183A /* AdvancedExampleViewController.swift */,
97464E6821372C010097183A /* NavigationBarExampleViewController.swift */,
607FACD51AFB9204008FA782 /* AppDelegate.swift */,
607FACD91AFB9204008FA782 /* Main.storyboard */,
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
607FACD31AFB9204008FA782 /* Supporting Files */,
);
name = "Example for GradientLoadingBar";
path = GradientLoadingBar;
sourceTree = "<group>";
};
607FACD31AFB9204008FA782 /* Supporting Files */ = {
isa = PBXGroup;
children = (
607FACD41AFB9204008FA782 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
607FACE81AFB9204008FA782 /* Tests */ = {
isa = PBXGroup;
children = (
64C6B3E72313259500076A69 /* ViewModel */,
64E7F4222293E16B00BE5095 /* Views */,
607FACE91AFB9204008FA782 /* Supporting Files */,
);
path = Tests;
sourceTree = "<group>";
};
607FACE91AFB9204008FA782 /* Supporting Files */ = {
isa = PBXGroup;
children = (
607FACEA1AFB9204008FA782 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
isa = PBXGroup;
children = (
C06CA4DFA1DCB931095ABD3D /* GradientLoadingBar.podspec */,
0E24EC094BE0798D462B5F96 /* README.md */,
F76834BE9E43CA11377EC030 /* LICENSE */,
);
name = "Podspec Metadata";
sourceTree = "<group>";
};
649A163A23770B4400404F3C /* SnapshotTests */ = {
isa = PBXGroup;
children = (
DCE3AB102497619600889FFA /* _Helper */,
DC190F5E2496A2290069E2B0 /* GradientActivityIndicatorView */,
DC190F5F2496A2380069E2B0 /* GradientLoadingBarController */,
649A163D23770B4400404F3C /* Info.plist */,
DCE3AB172497670400889FFA /* README.md */,
);
path = SnapshotTests;
sourceTree = "<group>";
};
64C6B3E72313259500076A69 /* ViewModel */ = {
isa = PBXGroup;
children = (
64E0F5BB2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift */,
640E8ABF231457620008C5A6 /* GradientActivityIndicatorViewModelTestCase.swift */,
DC9FF937270A470D0065B5B9 /* NotchGradientLoadingBarViewModelTestCase.swift */,
);
path = ViewModel;
sourceTree = "<group>";
};
64E7F4222293E16B00BE5095 /* Views */ = {
isa = PBXGroup;
children = (
64E7F4242293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift */,
);
path = Views;
sourceTree = "<group>";
};
97B6F5F92143F31F008CFEA5 /* Extensions */ = {
isa = PBXGroup;
children = (
97B6F5FA2143F31F008CFEA5 /* UIColor+CustomColors.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
97B6F5FB2143F31F008CFEA5 /* Views */ = {
isa = PBXGroup;
children = (
97B6F5FC2143F31F008CFEA5 /* BlueFilledButton.swift */,
97B6F5FD2143F31F008CFEA5 /* BlueBorderedButton.swift */,
6430C3A22338F1CA001F4A33 /* LargeNavigationBarHeaderView.swift */,
);
path = Views;
sourceTree = "<group>";
};
BFC08F9E633527E553EDA250 /* Pods */ = {
isa = PBXGroup;
children = (
3DC26E6D2B0C63183F508578 /* Pods-GradientLoadingBar_Example.debug.xcconfig */,
172FD3755BEBFF66683F5D81 /* Pods-GradientLoadingBar_Example.release.xcconfig */,
FECB95A4857728345199461F /* Pods-GradientLoadingBar_Tests.debug.xcconfig */,
14959BE5652C9E83FC09BBDD /* Pods-GradientLoadingBar_Tests.release.xcconfig */,
E7B292793F03D669ACAA92D2 /* Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig */,
A98CA9F1B0C1BD6864C14E01 /* Pods-GradientLoadingBar_SnapshotTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
DB185876CEF7C6517EB25B58 /* Frameworks */ = {
isa = PBXGroup;
children = (
03CD5D69D7C3FBBDBF5FABBB /* Pods_GradientLoadingBar_Example.framework */,
434E3C8A6E245A38C2831E73 /* Pods_GradientLoadingBar_Tests.framework */,
ABA9B1EF5F3928BA6E31D3EA /* Pods_GradientLoadingBar_SnapshotTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
DC190F5E2496A2290069E2B0 /* GradientActivityIndicatorView */ = {
isa = PBXGroup;
children = (
649A163B23770B4400404F3C /* DefaultColorSnapshotTestCase.swift */,
649A164323770E9300404F3C /* CustomColorSnapshotTestCase.swift */,
);
path = GradientActivityIndicatorView;
sourceTree = "<group>";
};
DC190F5F2496A2380069E2B0 /* GradientLoadingBarController */ = {
isa = PBXGroup;
children = (
DCE3AB14249764A000889FFA /* GradientLoadingBarControllerTestCase.swift */,
DC190F602496A24F0069E2B0 /* NotchGradientLoadingBarControllerTestCase.swift */,
);
path = GradientLoadingBarController;
sourceTree = "<group>";
};
DCE3AB102497619600889FFA /* _Helper */ = {
isa = PBXGroup;
children = (
DCE3AB11249761AB00889FFA /* Snapshotting+WindowedImage.swift */,
);
path = _Helper;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
607FACCF1AFB9204008FA782 /* GradientLoadingBar_Example */ = {
isa = PBXNativeTarget;
buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "GradientLoadingBar_Example" */;
buildPhases = (
8A80B9B4778F0A3D30371790 /* [CP] Check Pods Manifest.lock */,
607FACCC1AFB9204008FA782 /* Sources */,
607FACCD1AFB9204008FA782 /* Frameworks */,
607FACCE1AFB9204008FA782 /* Resources */,
1A66A3C243446BE65EBE3AAE /* [CP] Embed Pods Frameworks */,
972EE1C9201CA5C4001F603C /* Swiftformat */,
9753E83D1F80F7D300EF2822 /* Swiftlint */,
);
buildRules = (
);
dependencies = (
);
name = GradientLoadingBar_Example;
productName = GradientLoadingBar;
productReference = 607FACD01AFB9204008FA782 /* GradientLoadingBar_Example.app */;
productType = "com.apple.product-type.application";
};
607FACE41AFB9204008FA782 /* GradientLoadingBar_Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "GradientLoadingBar_Tests" */;
buildPhases = (
04A6606B8779F59C5BA953A7 /* [CP] Check Pods Manifest.lock */,
607FACE11AFB9204008FA782 /* Sources */,
607FACE21AFB9204008FA782 /* Frameworks */,
607FACE31AFB9204008FA782 /* Resources */,
);
buildRules = (
);
dependencies = (
607FACE71AFB9204008FA782 /* PBXTargetDependency */,
);
name = GradientLoadingBar_Tests;
productName = Tests;
productReference = 607FACE51AFB9204008FA782 /* GradientLoadingBar_Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
649A163823770B4400404F3C /* GradientLoadingBar_SnapshotTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 649A164223770B4400404F3C /* Build configuration list for PBXNativeTarget "GradientLoadingBar_SnapshotTests" */;
buildPhases = (
C6F0F8135CCFB10901DB76DB /* [CP] Check Pods Manifest.lock */,
649A163523770B4400404F3C /* Sources */,
649A163623770B4400404F3C /* Frameworks */,
649A163723770B4400404F3C /* Resources */,
568034A03F733A9FAEAC587B /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
649A163F23770B4400404F3C /* PBXTargetDependency */,
);
name = GradientLoadingBar_SnapshotTests;
productName = SnapshotTests;
productReference = 649A163923770B4400404F3C /* GradientLoadingBar_SnapshotTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
607FACC81AFB9204008FA782 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1120;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = CocoaPods;
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
LastSwiftMigration = 1020;
};
607FACE41AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;
LastSwiftMigration = 1020;
TestTargetID = 607FACCF1AFB9204008FA782;
};
649A163823770B4400404F3C = {
CreatedOnToolsVersion = 11.2;
ProvisioningStyle = Automatic;
TestTargetID = 607FACCF1AFB9204008FA782;
};
};
};
buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "GradientLoadingBar" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 607FACC71AFB9204008FA782;
productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
607FACCF1AFB9204008FA782 /* GradientLoadingBar_Example */,
607FACE41AFB9204008FA782 /* GradientLoadingBar_Tests */,
649A163823770B4400404F3C /* GradientLoadingBar_SnapshotTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
607FACCE1AFB9204008FA782 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE31AFB9204008FA782 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
649A163723770B4400404F3C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
04A6606B8779F59C5BA953A7 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-GradientLoadingBar_Tests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
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;
};
1A66A3C243446BE65EBE3AAE /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework",
"${BUILT_PRODUCTS_DIR}/LightweightObservable/LightweightObservable.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GradientLoadingBar.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LightweightObservable.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GradientLoadingBar_Example/Pods-GradientLoadingBar_Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
568034A03F733A9FAEAC587B /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GradientLoadingBar_SnapshotTests/Pods-GradientLoadingBar_SnapshotTests-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/SnapshotTesting/SnapshotTesting.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapshotTesting.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GradientLoadingBar_SnapshotTests/Pods-GradientLoadingBar_SnapshotTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
8A80B9B4778F0A3D30371790 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-GradientLoadingBar_Example-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
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;
};
972EE1C9201CA5C4001F603C /* Swiftformat */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = Swiftformat;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "SWIFTFORMAT=\"${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat\"\nif [ ! -f \"$SWIFTFORMAT\" ]; then\n echo \"warning: SwiftFormat not installed!\"\n exit 1\nfi\n\n$SWIFTFORMAT ../ --config \"${PODS_ROOT}/SwiftConfigurationFiles/.swiftformat\"\n";
};
9753E83D1F80F7D300EF2822 /* Swiftlint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = Swiftlint;
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "SWIFTLINT=\"${PODS_ROOT}/SwiftLint/swiftlint\"\nif [ ! -f \"$SWIFTLINT\" ]; then\n echo \"warning: SwiftLint not installed!\"\n exit 1\nfi\n\n$SWIFTLINT\n";
};
C6F0F8135CCFB10901DB76DB /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-GradientLoadingBar_SnapshotTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
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 */
/* Begin PBXSourcesBuildPhase section */
607FACCC1AFB9204008FA782 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
607FACD81AFB9204008FA782 /* BasicExampleViewController.swift in Sources */,
64C596EC2351D80000A6CC97 /* InterfaceBuilderExampleViewController.swift in Sources */,
972CFBCC2138849A006F14C9 /* SafeAreaExampleViewController.swift in Sources */,
97464E6721372BCD0097183A /* AdvancedExampleViewController.swift in Sources */,
6430C3A32338F1CA001F4A33 /* LargeNavigationBarHeaderView.swift in Sources */,
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
97B6F5FF2143F31F008CFEA5 /* BlueFilledButton.swift in Sources */,
97B6F5FE2143F31F008CFEA5 /* UIColor+CustomColors.swift in Sources */,
97B6F6002143F31F008CFEA5 /* BlueBorderedButton.swift in Sources */,
97464E6921372C010097183A /* NavigationBarExampleViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
607FACE11AFB9204008FA782 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
640E8AC0231457620008C5A6 /* GradientActivityIndicatorViewModelTestCase.swift in Sources */,
64E0F5BF2211B7D20066D00D /* GradientLoadingBarViewModelTestCase.swift in Sources */,
DC9FF938270A470D0065B5B9 /* NotchGradientLoadingBarViewModelTestCase.swift in Sources */,
64E7F4252293E16B00BE5095 /* GradientActivityIndicatorView+AnimateIsHiddenTestCase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
649A163523770B4400404F3C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DCE3AB13249761B300889FFA /* Snapshotting+WindowedImage.swift in Sources */,
DC190F622496A25A0069E2B0 /* NotchGradientLoadingBarControllerTestCase.swift in Sources */,
DCE3AB16249764BB00889FFA /* GradientLoadingBarControllerTestCase.swift in Sources */,
649A164423770E9300404F3C /* CustomColorSnapshotTestCase.swift in Sources */,
649A163C23770B4400404F3C /* DefaultColorSnapshotTestCase.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
607FACE71AFB9204008FA782 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 607FACCF1AFB9204008FA782 /* GradientLoadingBar_Example */;
targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */;
};
649A163F23770B4400404F3C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 607FACCF1AFB9204008FA782 /* GradientLoadingBar_Example */;
targetProxy = 649A163E23770B4400404F3C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
607FACD91AFB9204008FA782 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
607FACDA1AFB9204008FA782 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
607FACDF1AFB9204008FA782 /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
607FACED1AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
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_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
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;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
607FACEE1AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
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_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
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;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
607FACF01AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3DC26E6D2B0C63183F508578 /* Pods-GradientLoadingBar_Example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = GradientLoadingBar/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
607FACF11AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 172FD3755BEBFF66683F5D81 /* Pods-GradientLoadingBar_Example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = GradientLoadingBar/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
607FACF31AFB9204008FA782 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FECB95A4857728345199461F /* Pods-GradientLoadingBar_Tests.debug.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GradientLoadingBar_Example.app/GradientLoadingBar_Example";
};
name = Debug;
};
607FACF41AFB9204008FA782 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 14959BE5652C9E83FC09BBDD /* Pods-GradientLoadingBar_Tests.release.xcconfig */;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GradientLoadingBar_Example.app/GradientLoadingBar_Example";
};
name = Release;
};
649A164023770B4400404F3C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E7B292793F03D669ACAA92D2 /* Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = SnapshotTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = hamburg.felix.SnapshotTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GradientLoadingBar_Example.app/GradientLoadingBar_Example";
};
name = Debug;
};
649A164123770B4400404F3C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A98CA9F1B0C1BD6864C14E01 /* Pods-GradientLoadingBar_SnapshotTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = SnapshotTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = hamburg.felix.SnapshotTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GradientLoadingBar_Example.app/GradientLoadingBar_Example";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "GradientLoadingBar" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACED1AFB9204008FA782 /* Debug */,
607FACEE1AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "GradientLoadingBar_Example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACF01AFB9204008FA782 /* Debug */,
607FACF11AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "GradientLoadingBar_Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
607FACF31AFB9204008FA782 /* Debug */,
607FACF41AFB9204008FA782 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
649A164223770B4400404F3C /* Build configuration list for PBXNativeTarget "GradientLoadingBar_SnapshotTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
649A164023770B4400404F3C /* Debug */,
649A164123770B4400404F3C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 607FACC81AFB9204008FA782 /* Project object */;
}
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:GradientLoadingBar.xcodeproj">
</FileRef>
</Workspace>
@@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "GradientLoadingBar_Example.app"
BlueprintName = "GradientLoadingBar_Example"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACE41AFB9204008FA782"
BuildableName = "GradientLoadingBar_Tests.xctest"
BlueprintName = "GradientLoadingBar_Tests"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "GradientLoadingBar_Example.app"
BlueprintName = "GradientLoadingBar_Example"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</MacroExpansion>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AD9297F9E6CC3E50EDCFECA0A77800B7"
BuildableName = "GradientLoadingBar.framework"
BlueprintName = "GradientLoadingBar"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACE41AFB9204008FA782"
BuildableName = "GradientLoadingBar_Tests.xctest"
BlueprintName = "GradientLoadingBar_Tests"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "649A163823770B4400404F3C"
BuildableName = "GradientLoadingBar_SnapshotTests.xctest"
BlueprintName = "GradientLoadingBar_SnapshotTests"
ReferencedContainer = "container:GradientLoadingBar.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 = "607FACCF1AFB9204008FA782"
BuildableName = "GradientLoadingBar_Example.app"
BlueprintName = "GradientLoadingBar_Example"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "607FACCF1AFB9204008FA782"
BuildableName = "GradientLoadingBar_Example.app"
BlueprintName = "GradientLoadingBar_Example"
ReferencedContainer = "container:GradientLoadingBar.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,105 +0,0 @@
//
// AdvancedExampleViewController.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 30.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
import GradientLoadingBar
class AdvancedExampleViewController: UIViewController {
// MARK: - Config
private enum Config {
/// The programatically applied height of the `GradientActivityIndicatorView`.
static let height: CGFloat = 3.5
}
// MARK: - Outlets
@IBOutlet private var programmaticallyButton: BlueBorderedButton!
@IBOutlet private var customColorsButton: BlueBorderedButton!
// MARK: - Private properties
// swiftlint:disable:next identifier_name
private let programmaticallyGradientActivityIndicatorView = GradientActivityIndicatorView()
// swiftlint:disable:next identifier_name
private let customColorsGradientActivityIndicatorView: GradientActivityIndicatorView = {
let gradientActivityIndicatorView = GradientActivityIndicatorView()
// Source: https://color.adobe.com/Pink-Flamingo-color-theme-10343714/
gradientActivityIndicatorView.gradientColors = [
#colorLiteral(red: 0.9490196078, green: 0.3215686275, blue: 0.431372549, alpha: 1), #colorLiteral(red: 0.9450980392, green: 0.4784313725, blue: 0.5921568627, alpha: 1), #colorLiteral(red: 0.9529411765, green: 0.737254902, blue: 0.7843137255, alpha: 1), #colorLiteral(red: 0.4274509804, green: 0.8666666667, blue: 0.9490196078, alpha: 1), #colorLiteral(red: 0.7568627451, green: 0.9411764706, blue: 0.9568627451, alpha: 1),
]
return gradientActivityIndicatorView
}()
// MARK: - Public methods
override func viewDidLoad() {
super.viewDidLoad()
setupProgrammaticallyGradientActivityIndicatorView()
setupCustomColorsGradientActivityIndicatorView()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
programmaticallyGradientActivityIndicatorView.fadeOut()
customColorsGradientActivityIndicatorView.fadeOut()
}
@IBAction private func toggleProgrammaticallyButtonTouchUpInside(_: Any) {
if programmaticallyGradientActivityIndicatorView.isHidden {
programmaticallyGradientActivityIndicatorView.fadeIn()
} else {
programmaticallyGradientActivityIndicatorView.fadeOut()
}
}
@IBAction private func toggleCustomColorsButtonTouchUpInside(_: Any) {
if customColorsGradientActivityIndicatorView.isHidden {
customColorsGradientActivityIndicatorView.fadeIn()
} else {
customColorsGradientActivityIndicatorView.fadeOut()
}
}
// MARK: - Private methods
private func setupProgrammaticallyGradientActivityIndicatorView() {
programmaticallyGradientActivityIndicatorView.fadeOut(duration: 0)
programmaticallyGradientActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
programmaticallyButton.addSubview(programmaticallyGradientActivityIndicatorView)
NSLayoutConstraint.activate([
programmaticallyGradientActivityIndicatorView.leadingAnchor.constraint(equalTo: programmaticallyButton.leadingAnchor),
programmaticallyGradientActivityIndicatorView.trailingAnchor.constraint(equalTo: programmaticallyButton.trailingAnchor),
programmaticallyGradientActivityIndicatorView.topAnchor.constraint(equalTo: programmaticallyButton.topAnchor),
programmaticallyGradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: Config.height),
])
}
private func setupCustomColorsGradientActivityIndicatorView() {
customColorsGradientActivityIndicatorView.fadeOut(duration: 0)
customColorsGradientActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
customColorsButton.addSubview(customColorsGradientActivityIndicatorView)
NSLayoutConstraint.activate([
customColorsGradientActivityIndicatorView.leadingAnchor.constraint(equalTo: customColorsButton.leadingAnchor),
customColorsGradientActivityIndicatorView.trailingAnchor.constraint(equalTo: customColorsButton.trailingAnchor),
customColorsGradientActivityIndicatorView.bottomAnchor.constraint(equalTo: customColorsButton.bottomAnchor),
customColorsGradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: Config.height),
])
}
}
@@ -1,52 +0,0 @@
//
// AppDelegate.swift
// GradientLoadingBar
//
// Created by Felix Mau on 30.09.17.
// Copyright © 2017 Felix Mau. All rights reserved.
//
import GradientLoadingBar
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Example on how to customize the shared instance of `GradientLoadingBar`.
// We're gonna use the same height though ¯\_()_/¯
let customGradientLoadingBar = GradientLoadingBar(height: 3.0)
GradientLoadingBar.shared = customGradientLoadingBar
return true
}
func applicationWillResignActive(_: UIApplication) {
// Sent when the application is about to move from active to inactive state.
// This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application
// and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your
// application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive.
// If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Gradient Loading Bar" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iUK-He-88D">
<rect key="frame" x="20" y="219.5" width="440" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Example Application" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kZE-Up-yio">
<rect key="frame" x="20" y="240" width="440" height="18"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="kZE-Up-yio" secondAttribute="trailing" id="1w6-hQ-DuS"/>
<constraint firstItem="kZE-Up-yio" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leadingMargin" id="JLl-ee-fNq"/>
<constraint firstItem="kZE-Up-yio" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="centerY" id="b41-JE-swY"/>
<constraint firstAttribute="trailingMargin" secondItem="iUK-He-88D" secondAttribute="trailing" id="eCr-27-PHd"/>
<constraint firstItem="iUK-He-88D" firstAttribute="bottom" secondItem="iN0-l3-epB" secondAttribute="centerY" id="g3R-8N-4ZM"/>
<constraint firstItem="iUK-He-88D" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leadingMargin" id="lzx-6Y-lwW"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
@@ -1,489 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="31S-8b-Niv">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Basic Example-->
<scene sceneID="ufC-wZ-h7g">
<objects>
<viewController id="vXZ-lx-hvc" customClass="BasicExampleViewController" customModule="GradientLoadingBar_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="V1J-1V-cbT" customClass="LargeNavigationBarHeaderView" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="138"/>
<constraints>
<constraint firstAttribute="height" constant="138" id="ydQ-Zv-f3W"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="title" value="🏡 Basic Example"/>
<userDefinedRuntimeAttribute type="string" keyPath="prompt" value="Gradient Loading Bar"/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vCz-UL-eay" userLabel="Wrapper View">
<rect key="frame" x="0.0" y="138" width="375" height="480"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="Hrq-tB-Sk3">
<rect key="frame" x="16" y="220" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="W6V-cT-b8Q" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="MdR-sO-dac"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Show"/>
<connections>
<action selector="showButtonTouchUpInside:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="cns-MK-XRQ"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mLp-ey-yd5" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="vge-I5-pFX"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Hide"/>
<connections>
<action selector="hideButtonTouchUpInside:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="Cyb-6a-nJk"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="Hrq-tB-Sk3" firstAttribute="leading" secondItem="vCz-UL-eay" secondAttribute="leading" constant="16" id="Er7-gx-Ray"/>
<constraint firstItem="Hrq-tB-Sk3" firstAttribute="centerY" secondItem="vCz-UL-eay" secondAttribute="centerY" id="MB9-lc-dAX"/>
<constraint firstAttribute="trailing" secondItem="Hrq-tB-Sk3" secondAttribute="trailing" constant="16" id="ao9-tR-lfs"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="V1J-1V-cbT" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailing" id="9TW-dR-0YF"/>
<constraint firstItem="2fi-mo-0CV" firstAttribute="top" secondItem="vCz-UL-eay" secondAttribute="bottom" id="BSE-5g-uVL"/>
<constraint firstItem="vCz-UL-eay" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="Lym-2g-94s"/>
<constraint firstItem="V1J-1V-cbT" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="PZZ-lR-n3R"/>
<constraint firstItem="V1J-1V-cbT" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" id="VPm-eG-4vI"/>
<constraint firstItem="vCz-UL-eay" firstAttribute="top" secondItem="V1J-1V-cbT" secondAttribute="bottom" id="Vhb-09-feC"/>
<constraint firstAttribute="trailing" secondItem="vCz-UL-eay" secondAttribute="trailing" id="d0u-3Y-rTF"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Basic Example" image="house" catalog="system" id="QbQ-0M-Q7f"/>
<navigationItem key="navigationItem" title="Basic Example" prompt="Gradient Loading Bar" largeTitleDisplayMode="always" id="Rdw-Bd-vul"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-969" y="940"/>
</scene>
<!--Navigation Bar Example-->
<scene sceneID="Blz-xb-a2R">
<objects>
<viewController id="sEh-Tc-lv1" userLabel="Navigation Bar Example" customClass="NavigationBarExampleViewController" customModule="GradientLoadingBar_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Iik-d0-ufh"/>
<viewControllerLayoutGuide type="bottom" id="J9t-Vs-nTW"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="iwi-Ev-GiP">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wLK-vz-uDn" userLabel="Wrapper View">
<rect key="frame" x="0.0" y="138.5" width="375" height="479.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="xhZ-U8-Vur">
<rect key="frame" x="16" y="220" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ogf-h2-Nhm" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Ae3-GF-JqK"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Show"/>
<connections>
<action selector="showButtonTouchUpInside:" destination="sEh-Tc-lv1" eventType="touchUpInside" id="8M0-h9-3np"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZBM-PV-ZnL" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="2cO-9h-Wp9"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Hide"/>
<connections>
<action selector="hideButtonTouchUpInside:" destination="sEh-Tc-lv1" eventType="touchUpInside" id="oAh-2i-goU"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="xhZ-U8-Vur" secondAttribute="trailing" constant="16" id="2sW-85-0wR"/>
<constraint firstItem="xhZ-U8-Vur" firstAttribute="leading" secondItem="wLK-vz-uDn" secondAttribute="leading" constant="16" id="Al7-Jv-AJK"/>
<constraint firstItem="xhZ-U8-Vur" firstAttribute="centerY" secondItem="wLK-vz-uDn" secondAttribute="centerY" id="zTM-SW-qLa"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="wLK-vz-uDn" firstAttribute="leading" secondItem="iwi-Ev-GiP" secondAttribute="leading" id="A9Q-8d-dYD"/>
<constraint firstItem="wLK-vz-uDn" firstAttribute="top" secondItem="Iik-d0-ufh" secondAttribute="bottom" id="Pna-g3-eRn"/>
<constraint firstAttribute="trailing" secondItem="wLK-vz-uDn" secondAttribute="trailing" id="Vn7-pj-36y"/>
<constraint firstItem="J9t-Vs-nTW" firstAttribute="top" secondItem="wLK-vz-uDn" secondAttribute="bottom" id="b3J-NQ-cWP"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="💡 Navigation Bar Example" prompt=" Gradient Loading Bar " largeTitleDisplayMode="always" id="q3W-Ea-vnS"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="3VI-no-5Tx" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2009" y="1661"/>
</scene>
<!--Safe Area Example-->
<scene sceneID="0Ok-vd-ZTP">
<objects>
<viewController id="G0W-Ta-C7r" userLabel="Safe Area Example" customClass="SafeAreaExampleViewController" customModule="GradientLoadingBar_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="4Ae-UH-dXd"/>
<viewControllerLayoutGuide type="bottom" id="9TC-19-AMF"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="5Bk-7E-1bh">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tyJ-Wx-jmZ" customClass="LargeNavigationBarHeaderView" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="138"/>
<constraints>
<constraint firstAttribute="height" constant="138" id="toR-QS-r8U"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="title" value="📲 Safe Area Example"/>
<userDefinedRuntimeAttribute type="string" keyPath="prompt" value=" Gradient Loading Bar "/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cQz-wE-hV5" userLabel="Wrapper View">
<rect key="frame" x="0.0" y="138" width="375" height="480"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="oWt-EZ-h2R" userLabel="Upper Stack View">
<rect key="frame" x="16" y="192" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6AO-o8-uCr" userLabel="Show Button" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="JJW-aV-Rqk"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Show Basic Bar"/>
<connections>
<action selector="showBasicBarButtonTouchUpInside:" destination="G0W-Ta-C7r" eventType="touchUpInside" id="Nbx-cD-Wmk"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="enr-bC-bdY" userLabel="Hide Button" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="tlC-vL-RSX"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Hide Basic Bar"/>
<connections>
<action selector="hideBasicBarButtonTouchUpInside:" destination="G0W-Ta-C7r" eventType="touchUpInside" id="Um3-56-3gL"/>
</connections>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="eno-YK-fo8" userLabel="Lower Stack View">
<rect key="frame" x="16" y="248" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oLd-Dp-Iks" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="DIo-cN-15i"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Show Notch Bar"/>
<connections>
<action selector="showNotchBarButtonTouchUpInside:" destination="G0W-Ta-C7r" eventType="touchUpInside" id="Q1l-9E-ova"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="S86-Vf-cv9" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="oOd-1X-Klv"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Hide Notch Bar"/>
<connections>
<action selector="hideNotchBarButtonTouchUpInside:" destination="G0W-Ta-C7r" eventType="touchUpInside" id="nJm-HD-YTg"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="oWt-EZ-h2R" firstAttribute="bottom" secondItem="cQz-wE-hV5" secondAttribute="centerY" constant="-8" id="77C-lL-1fS"/>
<constraint firstItem="oWt-EZ-h2R" firstAttribute="leading" secondItem="cQz-wE-hV5" secondAttribute="leading" constant="16" id="Hjd-XM-aek"/>
<constraint firstAttribute="trailing" secondItem="oWt-EZ-h2R" secondAttribute="trailing" constant="16" id="ifg-oy-eiV"/>
<constraint firstAttribute="trailing" secondItem="eno-YK-fo8" secondAttribute="trailing" constant="16" id="o3h-uA-jbM"/>
<constraint firstItem="eno-YK-fo8" firstAttribute="top" secondItem="cQz-wE-hV5" secondAttribute="centerY" constant="8" id="rVX-yO-z4X"/>
<constraint firstItem="eno-YK-fo8" firstAttribute="leading" secondItem="cQz-wE-hV5" secondAttribute="leading" constant="16" id="zaJ-tE-bCY"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="tyJ-Wx-jmZ" firstAttribute="leading" secondItem="5Bk-7E-1bh" secondAttribute="leading" id="BGY-Fa-Ib2"/>
<constraint firstAttribute="trailing" secondItem="cQz-wE-hV5" secondAttribute="trailing" id="KmM-2A-jAw"/>
<constraint firstItem="cQz-wE-hV5" firstAttribute="top" secondItem="tyJ-Wx-jmZ" secondAttribute="bottom" id="NJ3-mJ-mLD"/>
<constraint firstItem="cQz-wE-hV5" firstAttribute="leading" secondItem="5Bk-7E-1bh" secondAttribute="leading" id="dID-N8-kru"/>
<constraint firstItem="tyJ-Wx-jmZ" firstAttribute="top" secondItem="4Ae-UH-dXd" secondAttribute="bottom" id="obq-xF-4qg"/>
<constraint firstItem="9TC-19-AMF" firstAttribute="top" secondItem="cQz-wE-hV5" secondAttribute="bottom" id="qfC-iN-Dv4"/>
<constraint firstAttribute="trailing" secondItem="tyJ-Wx-jmZ" secondAttribute="trailing" id="u0E-oe-0ko"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Safe Area Example" image="rectangle.and.arrow.up.right.and.arrow.down.left" catalog="system" id="VBS-L1-AHW"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="oYv-dl-Yai" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-214" y="940"/>
</scene>
<!--Interface Builder Example-->
<scene sceneID="NSv-IO-1Fu">
<objects>
<viewController title="Interface Builder Example" id="kcg-0d-bdI" customClass="InterfaceBuilderExampleViewController" customModule="GradientLoadingBar_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="znh-se-r1k"/>
<viewControllerLayoutGuide type="bottom" id="Ruy-Se-i9x"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="G47-Se-1Pm">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ei7-8i-vp4" customClass="LargeNavigationBarHeaderView" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="138"/>
<constraints>
<constraint firstAttribute="height" constant="138" id="z0S-oU-OR8"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="title" value="🎨 Interface Builder Example"/>
<userDefinedRuntimeAttribute type="string" keyPath="prompt" value=" Gradient Loading Bar "/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mbb-4g-X9Q" userLabel="Wrapper View">
<rect key="frame" x="0.0" y="138" width="375" height="480"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yze-Dk-6Ol" customClass="GradientActivityIndicatorView" customModule="GradientLoadingBar">
<rect key="frame" x="16" y="16" width="343" height="3"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="3" id="jPq-M8-Jzb"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="layer.cornerRadius" value="3"/>
</userDefinedRuntimeAttributes>
</view>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="B2P-Ta-wQl">
<rect key="frame" x="16" y="220" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FVq-l4-0tb" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="hLM-JF-3uL"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Show"/>
<connections>
<action selector="showButtonTouchUpInside:" destination="kcg-0d-bdI" eventType="touchUpInside" id="bBo-X1-9o5"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FWL-hp-DMs" customClass="BlueFilledButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="179.5" y="0.0" width="163.5" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="6jt-g9-DcI"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Hide"/>
<connections>
<action selector="hideButtonTouchUpInside:" destination="kcg-0d-bdI" eventType="touchUpInside" id="Zvk-pf-LDf"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Yze-Dk-6Ol" secondAttribute="trailing" constant="16" id="7Ae-mT-LLE"/>
<constraint firstItem="B2P-Ta-wQl" firstAttribute="leading" secondItem="mbb-4g-X9Q" secondAttribute="leading" constant="16" id="8cK-1Z-B70"/>
<constraint firstItem="Yze-Dk-6Ol" firstAttribute="leading" secondItem="mbb-4g-X9Q" secondAttribute="leading" constant="16" id="S1n-Cp-vlD"/>
<constraint firstItem="Yze-Dk-6Ol" firstAttribute="top" secondItem="mbb-4g-X9Q" secondAttribute="top" constant="16" id="asL-T7-vTV"/>
<constraint firstItem="B2P-Ta-wQl" firstAttribute="centerY" secondItem="mbb-4g-X9Q" secondAttribute="centerY" id="p7F-Kt-bT7"/>
<constraint firstAttribute="trailing" secondItem="B2P-Ta-wQl" secondAttribute="trailing" constant="16" id="tr4-w5-D3I"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="mbb-4g-X9Q" secondAttribute="trailing" id="7JI-Cf-Lbi"/>
<constraint firstItem="mbb-4g-X9Q" firstAttribute="leading" secondItem="G47-Se-1Pm" secondAttribute="leading" id="ASY-d8-7lc"/>
<constraint firstItem="mbb-4g-X9Q" firstAttribute="top" secondItem="ei7-8i-vp4" secondAttribute="bottom" id="CIq-u8-sbE"/>
<constraint firstItem="ei7-8i-vp4" firstAttribute="top" secondItem="znh-se-r1k" secondAttribute="bottom" id="G4H-cR-m9r"/>
<constraint firstAttribute="trailing" secondItem="ei7-8i-vp4" secondAttribute="trailing" id="hCK-vS-hrZ"/>
<constraint firstItem="ei7-8i-vp4" firstAttribute="leading" secondItem="G47-Se-1Pm" secondAttribute="leading" id="hch-Ju-3QH"/>
<constraint firstItem="Ruy-Se-i9x" firstAttribute="top" secondItem="mbb-4g-X9Q" secondAttribute="bottom" id="zdn-6E-6mg"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Interface Builder" image="photo" catalog="system" id="q1l-pB-Q4T"/>
<connections>
<outlet property="gradientActivityIndicatorView" destination="Yze-Dk-6Ol" id="v8n-H3-yyR"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4Yh-MD-f7b" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="537" y="940"/>
</scene>
<!--Advanced Example-->
<scene sceneID="7wr-48-QKh">
<objects>
<viewController id="l28-cg-vu8" customClass="AdvancedExampleViewController" customModule="GradientLoadingBar_Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="vvP-wW-eUz"/>
<viewControllerLayoutGuide type="bottom" id="9Nv-iX-Uwf"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="EZo-KN-FDG">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qZq-9D-wpV" customClass="LargeNavigationBarHeaderView" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="138"/>
<constraints>
<constraint firstAttribute="height" constant="138" id="St1-Xs-Hvy"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="title" value="🚀 Advanced Example"/>
<userDefinedRuntimeAttribute type="string" keyPath="prompt" value=" Gradient Loading Bar "/>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sJk-2n-yVK" userLabel="Wrapper View">
<rect key="frame" x="0.0" y="138" width="375" height="480"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="wzq-Eo-AIU">
<rect key="frame" x="16" y="194" width="343" height="92"/>
<subviews>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JKA-wf-nyj" userLabel="Toggle Programatically Button" customClass="BlueBorderedButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="343" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="sKv-MC-7kH"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Custom Superview"/>
<connections>
<action selector="toggleProgrammaticallyButtonTouchUpInside:" destination="l28-cg-vu8" eventType="touchUpInside" id="tZg-ye-xbi"/>
</connections>
</button>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Cbn-y8-lGV" userLabel="Toggle Custom Colors Button" customClass="BlueBorderedButton" customModule="GradientLoadingBar_Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="52" width="343" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="emu-Jk-zMc"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
<state key="normal" title="Custom Colors"/>
<connections>
<action selector="toggleCustomColorsButtonTouchUpInside:" destination="l28-cg-vu8" eventType="touchUpInside" id="BZJ-7f-xNF"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="wzq-Eo-AIU" firstAttribute="leading" secondItem="sJk-2n-yVK" secondAttribute="leading" constant="16" id="139-Ak-t87"/>
<constraint firstItem="wzq-Eo-AIU" firstAttribute="centerY" secondItem="sJk-2n-yVK" secondAttribute="centerY" id="IqE-ns-FHJ"/>
<constraint firstAttribute="trailing" secondItem="wzq-Eo-AIU" secondAttribute="trailing" constant="16" id="fcI-El-SAu"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="secondarySystemBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="sJk-2n-yVK" firstAttribute="top" secondItem="qZq-9D-wpV" secondAttribute="bottom" id="12P-NY-VtG"/>
<constraint firstItem="9Nv-iX-Uwf" firstAttribute="top" secondItem="sJk-2n-yVK" secondAttribute="bottom" id="3ZY-rc-hVf"/>
<constraint firstAttribute="trailing" secondItem="sJk-2n-yVK" secondAttribute="trailing" id="Hqt-KP-eSH"/>
<constraint firstItem="qZq-9D-wpV" firstAttribute="top" secondItem="vvP-wW-eUz" secondAttribute="bottom" id="IEz-PS-kaF"/>
<constraint firstItem="sJk-2n-yVK" firstAttribute="leading" secondItem="EZo-KN-FDG" secondAttribute="leading" id="ZPm-e3-QdJ"/>
<constraint firstAttribute="trailing" secondItem="qZq-9D-wpV" secondAttribute="trailing" id="kc6-MY-EP0"/>
<constraint firstItem="qZq-9D-wpV" firstAttribute="leading" secondItem="EZo-KN-FDG" secondAttribute="leading" id="piA-rQ-qe8"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Advanced Example" image="paperplane.fill" catalog="system" id="SyM-zw-tlg"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
<connections>
<outlet property="customColorsButton" destination="Cbn-y8-lGV" id="1ag-73-Mlh"/>
<outlet property="programmaticallyButton" destination="JKA-wf-nyj" id="JRN-do-tSa"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="fkr-pn-u5J" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1273" y="940"/>
</scene>
<!--Tab Bar Controller-->
<scene sceneID="gvY-1y-2Wb">
<objects>
<tabBarController automaticallyAdjustsScrollViewInsets="NO" id="31S-8b-Niv" sceneMemberID="viewController">
<toolbarItems/>
<tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="BSb-DD-oqz">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tabBar>
<connections>
<segue destination="vXZ-lx-hvc" kind="relationship" relationship="viewControllers" id="tyB-Oz-z6h"/>
<segue destination="G0W-Ta-C7r" kind="relationship" relationship="viewControllers" id="hPt-bW-PMO"/>
<segue destination="kcg-0d-bdI" kind="relationship" relationship="viewControllers" id="aD4-eR-rCH"/>
<segue destination="l28-cg-vu8" kind="relationship" relationship="viewControllers" id="4rs-U7-89R"/>
<segue destination="uZS-9p-82D" kind="relationship" relationship="viewControllers" id="Dcr-pe-ish"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="AXu-pz-Fer" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="538" y="134"/>
</scene>
<!--Nav Bar Example-->
<scene sceneID="HFG-Xb-221">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="uZS-9p-82D" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Nav Bar Example" image="lightbulb.fill" catalog="system" id="r91-al-1Rr"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="zAv-AH-IlN">
<rect key="frame" x="0.0" y="0.0" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="sEh-Tc-lv1" kind="relationship" relationship="rootViewController" id="Jor-5M-Hj4"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="yG3-j8-Ejc" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2009" y="940"/>
</scene>
</scenes>
<resources>
<image name="house" catalog="system" width="128" height="110"/>
<image name="lightbulb.fill" catalog="system" width="113" height="128"/>
<image name="paperplane.fill" catalog="system" width="128" height="121"/>
<image name="photo" catalog="system" width="128" height="93"/>
<image name="rectangle.and.arrow.up.right.and.arrow.down.left" catalog="system" width="121" height="128"/>
</resources>
</document>
@@ -1,16 +0,0 @@
//
// UIColor+CustomColors.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 29.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
extension UIColor {
/// Config that contains all our custom defined colors.
enum CustomColors {
static let blue = #colorLiteral(red: 0.2862745098, green: 0.5647058824, blue: 0.8862745098, alpha: 1)
}
}
-41
View File
@@ -1,41 +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>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>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
</dict>
</plist>
@@ -1,32 +0,0 @@
//
// InterfaceBuilderExampleViewController.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 12.10.19.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
import GradientLoadingBar
class InterfaceBuilderExampleViewController: UIViewController {
// MARK: - Outlets
@IBOutlet private var gradientActivityIndicatorView: GradientActivityIndicatorView!
// MARK: - Public methods
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
gradientActivityIndicatorView.fadeOut()
}
@IBAction private func showButtonTouchUpInside(_: Any) {
gradientActivityIndicatorView.fadeIn()
}
@IBAction private func hideButtonTouchUpInside(_: Any) {
gradientActivityIndicatorView.fadeOut()
}
}
@@ -1,37 +0,0 @@
//
// BlueBorderedButton.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 29.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
@IBDesignable
final class BlueBorderedButton: UIButton {
// MARK: - Initializer
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
// MARK: - Private methods
private func commonInit() {
backgroundColor = .clear
tintColor = UIColor.CustomColors.blue
layer.cornerRadius = 4
layer.borderColor = UIColor.CustomColors.blue.cgColor
layer.borderWidth = 1
}
}
@@ -1,41 +0,0 @@
//
// BlueFilledButton.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 29.08.18.
// Copyright © 2018 Felix Mau. All rights reserved.
//
import UIKit
@IBDesignable
final class BlueFilledButton: UIButton {
// MARK: - Initializer
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
commonInit()
}
// MARK: - Private methods
private func commonInit() {
tintColor = .white
backgroundColor = UIColor.CustomColors.blue
layer.cornerRadius = 4.0
}
}
@@ -1,85 +0,0 @@
//
// LargeNavigationBarHeaderView.swift
// GradientLoadingBar_Example
//
// Created by Felix Mau on 23.09.19.
// Copyright © 2019 CocoaPods. All rights reserved.
//
import UIKit
@IBDesignable
final class LargeNavigationBarHeaderView: UIView {
// MARK: - Public properties
@IBInspectable var title: String = "" {
didSet {
titleLabel.text = title
}
}
@IBInspectable var prompt: String = "" {
didSet {
promptLabel.text = prompt
}
}
// MARK: - Private properties
private let titleLabel = UILabel(frame: .zero)
private let promptLabel = UILabel(frame: .zero)
// MARK: - Initializer
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
// MARK: - Private methods
private func commonInit() {
setupTitleLabel()
setupPromptLabel()
}
private func setupTitleLabel() {
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .largeTitle)
titleLabel.font = UIFont.systemFont(ofSize: fontDescriptor.pointSize, weight: .bold)
titleLabel.textColor = .label
titleLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(titleLabel)
NSLayoutConstraint.activate([
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0),
titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16.0),
titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
])
}
private func setupPromptLabel() {
promptLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
promptLabel.textAlignment = .center
promptLabel.textColor = .label
promptLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(promptLabel)
NSLayoutConstraint.activate([
promptLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8.0),
promptLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8.0),
promptLabel.topAnchor.constraint(equalTo: topAnchor, constant: 9.5),
])
}
}
+26 -17
View File
@@ -4,7 +4,7 @@ source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '13.0'
use_frameworks!
target 'GradientLoadingBar_Example' do
target 'Example' do
pod 'GradientLoadingBar', :path => '../'
# Development pods.
@@ -12,22 +12,41 @@ target 'GradientLoadingBar_Example' do
pod 'SwiftLint', '~> 0.42'
pod 'SwiftConfigurationFiles', :git => 'https://github.com/fxm90/SwiftConfigurationFiles.git'
target 'GradientLoadingBar_Tests' do
target 'ExampleTests' do
inherit! :search_paths
# Pods for testing.
# Pods for testing
end
target 'GradientLoadingBar_SnapshotTests' do
target 'ExampleSnapshotTests' do
inherit! :search_paths
# Pods for snapshot testing.
pod 'SnapshotTesting', '~> 1.7', :inhibit_warnings => true
pod 'SnapshotTesting', '~> 1.9', :inhibit_warnings => true
end
post_install do |installer|
# Fix issues with interface builder and cocoapods.
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if target.name == 'GradientLoadingBar' || target.name == 'LightweightObservable'
# Explicitly set the iOS deployment target for `GradientLoadingBar` in our pods project, as this will be read by Carthage.
# To make the project compile we have to do this for the dependency 'LightweightObservable' as well.
#
# - Note: This value has to match `s.ios.deployment_target` from the `.podspec` file!!
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
else
# Remove the deployment target from all other pods in our project and let them inherit
# the project/workspace deployment target that has been specified at the top of the Podfile.
# Source: https://stackoverflow.com/a/63489366
config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
end
end
end
#
# Fix issues with interface builder and CocoaPods.
#
# Source: https://github.com/CocoaPods/CocoaPods/issues/7606#issuecomment-484294739
#
installer.pods_project.build_configurations.each do |config|
next unless config.name == 'Debug'
@@ -35,15 +54,5 @@ target 'GradientLoadingBar_Example' do
'$(FRAMEWORK_SEARCH_PATHS)'
]
end
# We support all iOS versions starting from 9.0. Therefore we manually decrease the deployment target for `GradientLoadingBar` here,
# so other (development / testing related pods) can use a higher deployment target, which is defined using `platform :ios` above.
installer.pods_project.targets.each do |target|
next unless target.name == 'GradientLoadingBar'
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
end
end
end
end
+12 -12
View File
@@ -1,15 +1,15 @@
PODS:
- GradientLoadingBar (2.2.3):
- GradientLoadingBar (2.3.5):
- LightweightObservable (~> 2.1)
- LightweightObservable (2.1.2)
- LightweightObservable (2.2.2)
- SnapshotTesting (1.9.0)
- SwiftConfigurationFiles (0.0.1)
- SwiftFormat/CLI (0.49.1)
- SwiftLint (0.45.1)
- SwiftFormat/CLI (0.49.18)
- SwiftLint (0.49.1)
DEPENDENCIES:
- GradientLoadingBar (from `../`)
- SnapshotTesting (~> 1.7)
- SnapshotTesting (~> 1.9)
- SwiftConfigurationFiles (from `https://github.com/fxm90/SwiftConfigurationFiles.git`)
- SwiftFormat/CLI (~> 0.41)
- SwiftLint (~> 0.42)
@@ -29,17 +29,17 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
SwiftConfigurationFiles:
:commit: 5e499075b42f5c986a6ad5a274cf8efa743337b5
:commit: efe01ba39069e8957fb89217b8c7fed298254691
:git: https://github.com/fxm90/SwiftConfigurationFiles.git
SPEC CHECKSUMS:
GradientLoadingBar: 157bd321c74e6bd0b0d87de735336060011393ab
LightweightObservable: c5ac85423a5edbed9a920b4d5c7b8f94ab3688c4
GradientLoadingBar: 97d0b455027194409b50c3fd589728ea7d79f08d
LightweightObservable: 6a106f0d60d497ee1ebd90ff549b54ac7abf3c36
SnapshotTesting: 6141c48b6aa76ead61431ca665c14ab9a066c53b
SwiftConfigurationFiles: 1cf2228a911ebed9f42f8dec077bb634f04ca6c8
SwiftFormat: 16b41f3229f5e7edb130ac4cd631cceed7af7d5e
SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761
SwiftFormat: 2402d29b26746f169cce5454d5af88314cbb2e35
SwiftLint: 32ee33ded0636d0905ef6911b2b67bbaeeedafa5
PODFILE CHECKSUM: 36b90780cb508f9eaca4f0ac59660e3e748de601
PODFILE CHECKSUM: b928db44cd4f82e38d7edb0c066f5b366277d6ef
COCOAPODS: 1.11.2
COCOAPODS: 1.11.3
@@ -11,35 +11,37 @@ import Foundation
/// Helper to allow storing multiple disposables and matching name from [RxSwift](https://github.com/ReactiveX/RxSwift).
public typealias DisposeBag = [Disposable]
/// Executes a given closure on it's deallocation.
/// Invokes a closure when this instance is deallocated.
public final class Disposable {
// MARK: - Types
/// Type for closure to be executed on deallocation.
/// Type for the closure to be called on deallocation.
public typealias Dispose = () -> Void
// MARK: - Private properties
/// Closure to be executed on deallocation.
/// The closure to be called on deallocation.
private let dispose: Dispose
// MARK: - Initializer
// MARK: - Instance Lifecycle
/// Creates a new instance.
///
/// - Parameter dispose: The closure that is executed on deallocation.
/// - Parameter dispose: The closure that is called on deallocation.
public init(_ dispose: @escaping Dispose) {
self.dispose = dispose
}
/// Executes our closure.
deinit {
dispose()
}
// MARK: - Public methods
/// Adds the current instance to the given array of disposables.
/// Adds the current instance to the given array of `Disposable`.
///
/// - Parameter bag: Reference to the array of `Disposable`.
public func disposed(by bag: inout DisposeBag) {
bag.append(self)
}
@@ -0,0 +1,77 @@
//
// Observable+Combine.swift
// LightweightObservable
//
// Created by Felix Mau on 04.02.22.
// Copyright © 2022 Felix Mau. All rights reserved.
//
import Combine
// Based on:
// https://thoughtbot.com/blog/lets-build-a-custom-publisher-in-combine
@available(iOS 13.0, *)
extension Observable: Publisher {
// MARK: - Types
public typealias Output = T
public typealias Failure = Never
// MARK: - Public methods
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
let subscription = Subscription<S>()
subscription.subscriber = subscriber
subscriber.receive(subscription: subscription)
// We explicitly subscribe to our `Observable` instance after passing the `Combine.Subscription` to the `Combine.Subscriber`.
// This makes sure when the underlying type of the `Observable` is a `Variable´, we correctly forward the initial value.
subscription.subscribe(to: self)
}
}
@available(iOS 13.0, *)
private extension Observable {
/// A custom subscription to forward events from an `Observable` instance.
final class Subscription<S: Subscriber> where S.Input == Output, S.Failure == Failure {
// MARK: - Public properties
var subscriber: S?
// MARK: - Private properties
private var disposable: Disposable?
// MARK: - Public methods
/// Updates our `subscriber` (`Combine.Subscriber`) with the values from the observable.
///
/// - Note: We explicitly avoid storing a reference to the observable from this instance (`Combine.Subscription`),
/// as this would create a retain cycle!!
func subscribe(to observable: Observable<S.Input>) {
disposable = observable.subscribe { [weak self] value, _ in
_ = self?.subscriber?.receive(value)
}
}
}
}
// MARK: - `Subscription` conformance
@available(iOS 13.0, *)
extension Observable.Subscription: Subscription {
func request(_: Subscribers.Demand) {
// This subscription doesn't respond to demand, since it'll only emit events
// according to its underlying `Observable` instance.
}
func cancel() {
// When the subscription was cancelled, we'll release the reference to our observable-subscription
// in order to prevent any additional events from being sent.
disposable = nil
}
}
@@ -10,6 +10,7 @@ import Foundation
/// Additional helper methods for an observable that that underlying type conforms to `Equatable`.
public extension Observable where T: Equatable {
// MARK: - Types
/// The type for the filter closure.
@@ -30,7 +31,7 @@ public extension Observable where T: Equatable {
/// - observer: The closure that is notified on changes if the filter succeeds.
///
/// - Note:
/// The `oldValue` of the observer always contains the previous value that passed the filter! E.g. if you filter for even numbers:
/// The `oldValue` of the observer always contains the previous value that passed the filter! E.g. if you filter for **even numbers**:
/// ```
/// | Emitted values: | 0 | 1 | 2 | 3 | 4 | 5 |
/// | -------------------------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -10,6 +10,7 @@ import Foundation
/// Additional helper methods for binding an observable to a property using Swifts `KeyPath` feature.
public extension Observable {
/// Updates the property at the given key-path on changes to our property `value`.
///
/// - Parameters:
@@ -27,8 +28,8 @@ public extension Observable {
/// - keyPath: The key-path that indicates the property to assign.
/// - object: The object containing the property to update.
///
/// - Note: We need to explicitly define this method for an optional type of `Value`, as otherwise we e.g. could not bind a `String` to the
/// optional string property `text` of an `UILabel`
/// - Note: We explicitly have to define this method for an optional type of `Value`, as otherwise we e.g. could not bind a
/// `String` to the property `text` of an `UILabel`, as this is of type `String?`.
func bind<Root>(to keyPath: ReferenceWritableKeyPath<Root, Value?>, on object: Root) -> Disposable {
subscribe { newValue, _ in
object[keyPath: keyPath] = newValue
@@ -15,6 +15,7 @@ import Foundation
/// - Remark: I'd prefer having a protocol definition here, but casting an instance with a generic (e.g. `Variable<Int>(0)`) to a protocol
/// with an associated type (`Observable<Int>`) doesn't work yet. Therefore we use an "abstract" class as a workaround.
public class Observable<T> {
// MARK: - Types
/// The type for the new value of the observable.
@@ -38,8 +39,6 @@ public class Observable<T> {
/// The current (readonly) value of the observable (if available).
///
/// - Note: We're using a computed property here, cause we need to override this property without nullability in the subclass `Variable`.
///
/// - Attention: It's always better to subscribe to a given observable! This **shortcut** should only be used during **testing**.
public var value: Value? {
fatalError("⚠️ Trying to access an abstract property! Subclasses need to overwrite and implement this computed property.")
}
@@ -52,7 +51,7 @@ public class Observable<T> {
/// Map with all **active** observers.
private var observers = [Index: Observer]()
// MARK: - Initalizer
// MARK: - Instance Lifecycle
/// Initializes a new observable.
///
@@ -61,6 +60,14 @@ public class Observable<T> {
// MARK: - Public methods
/// Updates the current value.
///
/// - Parameter value: The new value to apply.
public func update(_: Value) {
// swiftlint:disable:previous unavailable_function
fatalError("⚠️ Trying to call an abstract function! Subclasses need to overwrite and implement this method.")
}
/// Informs the given observer on changes to our underlying property `value`.
///
/// - Parameter observer: The closure that is notified on changes.
@@ -86,6 +93,7 @@ public class Observable<T> {
/// Starts empty and only emits new elements to subscribers.
public final class PublishSubject<T>: Observable<T> {
// MARK: - Public properties
/// The current (readonly) value of the observable (if available).
@@ -100,7 +108,7 @@ public final class PublishSubject<T>: Observable<T> {
/// - Note: Workaround for compiler error `Cannot override with a stored property 'value'`.
private var _value: Value?
// MARK: - Initializer
// MARK: - Instance Lifecycle
/// Initializes a new publish subject.
///
@@ -111,8 +119,7 @@ public final class PublishSubject<T>: Observable<T> {
// MARK: - Public methods
/// Updates the publish subject using the given value.
public func update(_ value: Value) {
override public func update(_ value: Value) {
let oldValue = _value
_value = value
@@ -124,6 +131,7 @@ public final class PublishSubject<T>: Observable<T> {
/// Starts with an initial value and replays it or the latest element to new subscribers.
public final class Variable<T>: Observable<T> {
// MARK: - Public properties
/// The current (read- and writeable) value of the variable.
@@ -143,7 +151,7 @@ public final class Variable<T>: Observable<T> {
}
}
// MARK: - Initializer
// MARK: - Instance Lifecycle
/// Initializes a new variable with the given value.
///
@@ -156,6 +164,10 @@ public final class Variable<T>: Observable<T> {
// MARK: - Public methods
override public func update(_ value: Value) {
self.value = value
}
override public func subscribe(_ observer: @escaping Observer) -> Disposable {
let disposable = super.subscribe(observer)
+70 -26
View File
@@ -2,7 +2,7 @@
<p align="center">
<img src="https://img.shields.io/badge/Swift-5.0-green.svg?style=flat" alt="Swift Version" />
<img src="http://img.shields.io/travis/com/fxm90/LightweightObservable.svg?style=flat" alt="CI Status" />
<img src="https://img.shields.io/github/workflow/status/fxm90/LightweightObservable/Continuous%20Integration" alt="CI Status" />
<img src="https://img.shields.io/codecov/c/github/fxm90/LightweightObservable.svg?style=flat" alt="Code Coverage" />
<img src="https://img.shields.io/cocoapods/v/LightweightObservable.svg?style=flat" alt="Version" />
<img src="https://img.shields.io/cocoapods/l/LightweightObservable.svg?style=flat" alt="License" />
@@ -24,10 +24,52 @@ If you want to update from version 1.x.x, please have a look at the [Lightweight
To run the example project, clone the repo, and open the workspace from the Example directory.
### Requirements
- Swift 5.0
- Xcode 10.2+
- Swift 5.5
- Xcode 13.2+
- iOS 9.0+
### Projects targeting iOS >= 13.0
In case your minimum required version is greater equal iOS 13.0, I recommend using [Combine](https://developer.apple.com/documentation/combine) instead of adding `Lightweight Observable` as a dependency.
If you rely on having a current and previous value in your subscription closure, please have a look at this extension: [Combine+Pairwise.swift](https://gist.github.com/fxm90/be62335d987016c84d2f8b3731197c98).
#### Update: Since version `2.2` an `Observable` instance conforms to the [`Publisher`](https://developer.apple.com/documentation/combine/publisher) protocol from Swift's `Combine` 🎉
This makes transitioning from `LightweightObservable` to `Combine` a lot easier, as you can use features from `Combine` without having to change the underlying `Observable` to a `Publisher`.
Example Code for using `Combine` functions on an instance of `PublishSubject`:
```swift
var subscriptions = Set<AnyCancellable>()
let publishSubject = PublishSubject<Int>()
publishSubject
.map { $0 * 2 }
.sink { print($0) }
.store(in: &subscriptions)
publishSubject.update(1) // Prints "2"
publishSubject.update(2) // Prints "4"
publishSubject.update(3) // Prints "6"
```
**Cheatsheet**
| `LightweightObservable` | `Combine` |
| ----------------------- | --------------------- |
| `PublishSubject` | `PassthroughSubject` |
| `Variable` | `CurrentValueSubject` |
Furthermore, using the property [`values`](https://developer.apple.com/documentation/combine/publisher/values-1dm9r) of a `Combine.Publisher`, you can use an `Observable` in an asynchronous sequence:
```swift
for await value in observable.values {
// ...
}
```
### Integration
##### CocoaPods
[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Lightweight Observable into your Xcode project using CocoaPods, specify it in your `Podfile`:
@@ -84,6 +126,8 @@ let formattedTimeSubject = Variable("4:20 PM")
// ...
formattedTimeSubject.value = "4:21 PM"
// or
formattedTimeSubject.update("4:21 PM")
```
#### Create an `Observable`
@@ -99,7 +143,7 @@ lazy var formattedTime: Observable<String> = formattedTimeSubject
```
#### Subscribe to changes
A subscriber will be informed at different times, depending on the corresponding subclass of the observable:
A subscriber will be informed at different times, depending on the subclass of the corresponding observable:
- `PublishSubject`: Starts empty and only emits new elements to subscribers.
- `Variable`: Starts with an initial value and replays it or the latest element to new subscribers.
@@ -121,7 +165,7 @@ formattedTime.subscribe { [weak self] newFormattedTime, oldFormattedTime in
Please notice that the old value (`oldFormattedTime`) is an optional of the underlying type, as we might not have this value on the initial call to the subscriber.
**Important:** To avoid retain cycles and/or crashes, **always** use `[weak self]` when self is needed by an observer.
**Important:** To avoid retain cycles and/or crashes, **always** use `[weak self]` when an instance of `self` is needed by an observer.
##### - KeyPath based subscription
**Declaration**
@@ -205,9 +249,9 @@ typealias Filter = (NewValue, OldValue) -> Bool
func subscribe(filter: @escaping Filter, observer: @escaping Observer) -> Disposable {}
```
Using this method, the observer will only be notified on changes if the corresponding filter matches.
Using this method, the observer will only be notified on changes if the corresponding filter matches (returns `true`).
This pod comes with one predefined filter method, called `subscribeDistinct`. Subscribing to an observable using this method, will only notify the observer if the new value is different from the old value. This is useful to prevent unnecessary UI-Updates.
This pod comes with one predefined filter method, called `subscribeDistinct`. Subscribing to an observable using this method will only notify the observer, if the new value is different from the old value. This is useful to prevent unnecessary UI-Updates.
Feel free to add more filters, by extending the `Observable` like this:
@@ -215,7 +259,6 @@ Feel free to add more filters, by extending the `Observable` like this:
extension Observable where T: Equatable {}
```
#### Getting the current value synchronously
You can get the current value of the `Observable` by accessing the property `value`. However it is always better to subscribe to a given observable! This **shortcut** should only be used during **testing**.
@@ -227,43 +270,44 @@ XCTAssertEqual(viewModel.formattedTime.value, "4:20")
Using the given approach, your view-model could look like this:
```swift
class TimeViewModel {
final class ViewModel {
// MARK: - Public properties
/// The current time as a formatted string (**immutable**).
var formattedTime: Observable<String> {
formattedTimeSubject
/// The current date and time as a formatted string (**immutable**).
var formattedDate: Observable<String> {
formattedDateSubject
}
// MARK: - Private properties
/// The current time as a formatted string (**mutable**).
private let formattedTimeSubject: Variable<String> = Variable("\(Date())")
/// The current date and time as a formatted string (**mutable**).
private let formattedDateSubject: Variable<String> = Variable("\(Date())")
private var timer: Timer?
// MARK: - Initializer
// MARK: - Instance Lifecycle
init() {
// Update variable with current time every second.
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in
self?.formattedTimeSubject.value = "\(Date())"
})
// Update variable with current date and time every second.
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
self?.formattedDateSubject.value = "\(Date())"
}
}
```
And your view controller like this:
```swift
class TimeViewController: UIViewController {
final class ViewController: UIViewController {
// MARK: - Outlets
@IBOutlet private var timeLabel: UILabel!
@IBOutlet private var dateLabel: UILabel!
// MARK: - Private properties
/// The view model calculating the current time.
private let timeViewModel = TimeViewModel()
private let viewModel = ViewModel()
/// The dispose bag for this view controller. On it's deallocation, it removes the
/// subscription-closures from the corresponding observable-properties.
@@ -274,9 +318,9 @@ class TimeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
timeViewModel
.formattedTime
.bind(to: \.text, on: timeLabel)
viewModel
.formattedDate
.bind(to: \.text, on: dateLabel)
.disposed(by: &disposeBag)
}
```
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "GradientLoadingBar",
"version": "2.2.3",
"version": "2.3.5",
"summary": "A customizable animated gradient loading bar.",
"description": "A customizable animated gradient loading bar.\nInspired by https://codepen.io/marcobiedermann/pen/LExXWW",
"homepage": "https://github.com/fxm90/GradientLoadingBar",
@@ -14,17 +14,17 @@
},
"source": {
"git": "https://github.com/fxm90/GradientLoadingBar.git",
"tag": "2.2.3"
"tag": "2.3.5"
},
"swift_versions": "5.1",
"swift_versions": "5.5",
"platforms": {
"ios": "9.0"
},
"source_files": "GradientLoadingBar/Classes/**/*",
"source_files": "GradientLoadingBar/**/*",
"dependencies": {
"LightweightObservable": [
"~> 2.1"
]
},
"swift_version": "5.1"
"swift_version": "5.5"
}
+12 -12
View File
@@ -1,15 +1,15 @@
PODS:
- GradientLoadingBar (2.2.3):
- GradientLoadingBar (2.3.5):
- LightweightObservable (~> 2.1)
- LightweightObservable (2.1.2)
- LightweightObservable (2.2.2)
- SnapshotTesting (1.9.0)
- SwiftConfigurationFiles (0.0.1)
- SwiftFormat/CLI (0.49.1)
- SwiftLint (0.45.1)
- SwiftFormat/CLI (0.49.18)
- SwiftLint (0.49.1)
DEPENDENCIES:
- GradientLoadingBar (from `../`)
- SnapshotTesting (~> 1.7)
- SnapshotTesting (~> 1.9)
- SwiftConfigurationFiles (from `https://github.com/fxm90/SwiftConfigurationFiles.git`)
- SwiftFormat/CLI (~> 0.41)
- SwiftLint (~> 0.42)
@@ -29,17 +29,17 @@ EXTERNAL SOURCES:
CHECKOUT OPTIONS:
SwiftConfigurationFiles:
:commit: 5e499075b42f5c986a6ad5a274cf8efa743337b5
:commit: efe01ba39069e8957fb89217b8c7fed298254691
:git: https://github.com/fxm90/SwiftConfigurationFiles.git
SPEC CHECKSUMS:
GradientLoadingBar: 157bd321c74e6bd0b0d87de735336060011393ab
LightweightObservable: c5ac85423a5edbed9a920b4d5c7b8f94ab3688c4
GradientLoadingBar: 97d0b455027194409b50c3fd589728ea7d79f08d
LightweightObservable: 6a106f0d60d497ee1ebd90ff549b54ac7abf3c36
SnapshotTesting: 6141c48b6aa76ead61431ca665c14ab9a066c53b
SwiftConfigurationFiles: 1cf2228a911ebed9f42f8dec077bb634f04ca6c8
SwiftFormat: 16b41f3229f5e7edb130ac4cd631cceed7af7d5e
SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761
SwiftFormat: 2402d29b26746f169cce5454d5af88314cbb2e35
SwiftLint: 32ee33ded0636d0905ef6911b2b67bbaeeedafa5
PODFILE CHECKSUM: 36b90780cb508f9eaca4f0ac59660e3e748de601
PODFILE CHECKSUM: b928db44cd4f82e38d7edb0c066f5b366277d6ef
COCOAPODS: 1.11.2
COCOAPODS: 1.11.3
+1005 -932
View File
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A29550F398D14038E3DD88D91573885C"
BlueprintIdentifier = "AD9297F9E6CC3E50EDCFECA0A77800B7"
BuildableName = "GradientLoadingBar.framework"
BlueprintName = "GradientLoadingBar"
ReferencedContainer = "container:Pods.xcodeproj">
@@ -29,8 +29,6 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -42,17 +40,6 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A29550F398D14038E3DD88D91573885C"
BuildableName = "GradientLoadingBar.framework"
BlueprintName = "GradientLoadingBar"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
+3 -2
View File
@@ -22,11 +22,12 @@
# Rules
#
--disable andOperator
--disable sortedImports
--disable blankLinesAtStartOfScope
--disable wrapMultilineStatementBraces
#
# Rule Configuration
#
--wraparguments "after-first"
--wrapcollections "before-first"
--wrapcollections "before-first"
--importgrouping testable-last
+8 -1
View File
@@ -1,2 +1,9 @@
# Swift Configuration Files 🛠
Repository containing configuration files for Swift development, e.g. for tools like [SwiftLint](https://github.com/realm/SwiftLint) or [SwiftFormat](https://github.com/nicklockwood/SwiftFormat).
Repository containing configuration files for Swift development, e.g. for tools like [SwiftLint](https://github.com/realm/SwiftLint) or [SwiftFormat](https://github.com/nicklockwood/SwiftFormat).
### Author
Felix Mau (me(@)felix.hamburg)
### License
Swift Configuration Files is available under the MIT license. See the LICENSE file for more info.
Binary file not shown.
+74 -15
View File
@@ -22,6 +22,7 @@ Table of Contents
- [Git pre-commit hook](#git-pre-commit-hook)
- [On CI using Danger](#on-ci-using-danger)
- [Bazel build](#bazel-build)
- [Docker](#docker)
- [Configuration](#configuration)
- [Options](#options)
- [Rules](#rules)
@@ -45,6 +46,7 @@ SwiftFormat is a code library and command-line tool for reformatting Swift code
SwiftFormat goes above and beyond what you might expect from a code formatter. In addition to adjusting white space it can insert or remove implicit `self`, remove redundant parentheses, and correct many other deviations from the standard Swift idioms.
Why would I want to do that?
-----------------------------
@@ -73,7 +75,7 @@ Command-line tool
**Installation:**
You can install the `swiftformat` command-line tool on macOS using [Homebrew](http://brew.sh/). Assuming you already have Homebrew installed, just type:
You can install the `swiftformat` command-line tool on macOS or Linux using [Homebrew](http://brew.sh/). Assuming you already have Homebrew installed, just type:
```bash
$ brew install swiftformat
@@ -91,13 +93,7 @@ Alternatively, you can install the tool on macOS or Linux by using [Mint](https:
$ mint install nicklockwood/SwiftFormat
```
And then run it using:
```bash
$ mint run swiftformat
```
Or if you prefer, you can check out and build SwiftFormat manually on macOS or Linux as follows:
Or if you prefer, you can check out and build SwiftFormat manually on macOS, Linux or Windows as follows:
```bash
$ git clone https://github.com/nicklockwood/SwiftFormat
@@ -107,6 +103,16 @@ $ swift build -c release
If you are installing SwiftFormat into your project directory, you can use [CocoaPods](https://cocoapods.org/) on macOS to automatically install the swiftformat binary along with your other pods - see the Xcode build phase instructions below for details.
Another option is to include the binary artifactbundle in your `Package.swift`:
```swift
.binaryTarget(
name: "SwiftFormat",
url: "https://github.com/nicklockwood/SwiftFormat/releases/download/0.49.12/swiftformat-macos.artifactbundle.zip",
checksum: "CHECKSUM"
),
```
If you would prefer not to use a package manager, you can build the command-line app manually:
1. open `SwiftFormat.xcodeproj` and build the `SwiftFormat (Application)` scheme.
@@ -211,7 +217,7 @@ Alternatively, if you prefer not to use Homebrew, you'll find the latest version
**Usage:**
Once you have launched the app and restarted Xcode, you'll find a SwiftFormat option under Xcode's Editor menu.
Once you have launched the app and restarted Xcode, you'll find a SwiftFormat option under Xcode's Editor menu. If the SwiftFormat menu does not appear [this thread](https://github.com/nicklockwood/SwiftFormat/issues/494) may help.
You can configure the formatting [rules](#rules) and [options](#options) using the SwiftFormat for Xcode host application. There is currently no way to override these per-project, however, you can import and export different configurations using the File menu. You will need to do this again each time you switch projects.
@@ -231,7 +237,7 @@ Alternatively, you might want to consider running SwiftFormat in [lint](#linting
To set up SwiftFormat as an Xcode build phase, do the following:
#### 1) Create a BuildTools folder & Package.swift
#### 1) Create a BuildTools folder and Package.swift
1. Create a folder called `BuildTools` in the same folder as your xcodeproj file
2. In this folder, create a file called `Package.swift`, with the following contents:
@@ -250,7 +256,7 @@ let package = Package(
```
3. If you are running Xcode 11.4 or later, in the `BuildTools` folder create a file called `Empty.swift` with nothing in it. This is to satisfy a change in Swift Package Manager.
#### 2) Add a Build phases to your app target
#### 2) Add a Build phase to your app target
1. Click on your project in the file list, choose your target under `TARGETS`, click the `Build Phases` tab
2. Add a `New Run Script Phase` by clicking the little plus icon in the top left
@@ -267,7 +273,7 @@ You can also use `swift run -c release --package-path BuildTools swiftformat "$S
**NOTE:** You may wish to check BuildTools/Package.swift into your source control so that the version used by your run-script phase is kept in version control. It is recommended to add the following to your .gitignore file: `BuildTools/.build` and `BuildTools/.swiftpm`.
### Using Cocoapods
### Using CocoaPods
#### 1) Add the SwiftFormat CLI to your Podfile
@@ -384,6 +390,39 @@ Bazel Build
If you use [Bazel](https://bazel.build/) to build your Swift projects and want to ensure that only properly formatted code is merged to your main branch, try [rules_swiftformat](https://github.com/cgrindel/rules_swiftformat). The repository contains Bazel rules and macros that format Swift source files using SwiftFormat, test that the formatted files exist in the workspace directory, and copy the formatted files to the workspace directory.
Docker
-----------
SwiftFormat publishes releases into [GitHub Packages](https://github.com/features/packages) Docker registry. To pull the image call:
```bash
$ docker pull ghcr.io/nicklockwood/swiftformat:latest
```
By default, the container runs `swiftformat .` Therefore, you need to provide a path either via an argument:
```bash
docker run --rm -v /local/source/path:/work ghcr.io/nicklockwood/swiftformat:latest /work
```
or by changing the working dir:
```bash
docker run --rm -v /local/source/path:/work -w /work ghcr.io/nicklockwood/swiftformat:latest
```
To check the installed SwiftFormat version:
```bash
docker run --rm ghcr.io/nicklockwood/swiftformat:latest --version
```
Linting example:
```bash
docker run --rm -v /local/source/path:/work ghcr.io/nicklockwood/swiftformat:latest /work --lint
```
Configuration
-------------
@@ -446,7 +485,13 @@ Alternatively, you can use the line continuation character `\` to wrap a single
redundantSelf
```
To avoid automatically opting-in to new rules when SwiftFormat is updated, use the`--rules` argument to *only* enable the rules you specify:
To avoid automatically opting-in to new rules when SwiftFormat is updated, you can disable all rules using:
```bash
--disable all
```
And then individually enable just the rules you want. Alternatively, use the`--rules` argument to *only* enable the rules you specify:
```bash
--rules indent,linebreaks
@@ -623,6 +668,13 @@ By default, `--lint` will only report lines that require formatting, but you can
If you would prefer not to see a warning for each and every formatting change, you can use the `--quiet` flag to suppress all output except errors.
Sometimes you may wish to autoformat some rules, but only lint others. To do that, use the `--lintonly` option in your config file to specify rules that should only be applied in `--lint` mode:
```
--rules braces,indent
--lintonly trailingClosures,unusedArguments
```
Error codes
-----------
@@ -709,7 +761,7 @@ FAQ
*Q. What platforms does SwiftFormat support?*
> A. SwiftFormat works on macOS 10.13 (High Sierra) and above, and also runs on Ubuntu Linux.
> A. SwiftFormat works on macOS 10.13 (High Sierra) and above, and also runs on Ubuntu Linux and Windows.
*Q. What versions of Swift are supported?*
@@ -766,6 +818,12 @@ Q. I don't want to be surprised by new rules added when I upgrade SwiftFormat. H
Known issues
---------------
* When using the Xcode Source Editor Extension, the SwiftFormat menu sometimes disappears from Xcode. If this happens, try moving or renaming Xcode temporarily and then changing it back. Failing that, the suggestions in [this thread](https://github.com/nicklockwood/SwiftFormat/issues/494) may help.
* The `enumNamespaces` rule replaces classes that have only static members with an `enum`. If the class is subclassed, or if there is code that depends on the class exposing certain runtime behaviors, this may break the program. To solve this you can either fix it on a per-case basis by adding a `// swiftformat:disable:next enumNamespaces` comment directive above the class declaration, or just disable the `enumNamespaces` rule completely.
* The `redundantVoidReturnType` rule can inadvertently alter the type signature for closures, for example in cases where the closure calls a `@discardableResult` function. To solve this you can either fix it on a per-case basis by adding a `// swiftformat:disable:next redundantVoidReturnType` comment directive to disable the rule for a specific call site, or you can add `--closurevoid preserve` to your [configuration](#configuration) to disable the rule completely for closures (regular functions or methods aren't affected).
* The `redundantType` rule can introduce ambiguous code in certain cases when using the default mode of `--redundanttype inferred`. This can be worked around by by using `--redundanttype explicit`, or by manually removing the redundant type reference on the affected line, or by using the `// swiftformat:disable:next redundantType` comment directive to disable the rule at the call site (or just disable the `redundantType` rule completely).
* If a type initializer or factory method returns an implicitly unwrapped optional value then the `redundantType` rule may remove the explicit type in a situation where it's actually required. To work around this you can either use `--redundanttype explicit`, or use the `// swiftformat:disable:next redundantType` comment directive to disable the rule at the call site (or just disable the `redundantType` rule completely).
@@ -778,7 +836,7 @@ Known issues
* When using the `--self remove` option, the `redundantSelf` rule will remove references to `self` in autoclosure arguments, which may change the meaning of the code, or cause it not to compile. To work around this issue, use the `--selfrequired` option to provide a comma-delimited list of methods to be excluded from the rule. The `expect()` function from the popular [Nimble](https://github.com/Quick/Nimble) unit testing framework is already excluded by default. If you are using the `--self insert` option then this is not an issue.
* If you assign `SomeClass.self` to a variable and then instantiate an instance of the class using that variable, Swift requires that you use an explicit `.init()`, however, the `redundantInit` rule is not currently capable of detecting this situation and will remove the `.init`. To work around this issue, use the `// swiftformat:disable:next redundantInit` comment directive to disable the rule for any affected lines of code (or just disable the `redundantInit` rule completely).
* If you assign `SomeClass.self` to a variable and then instantiate an instance of the class using that variable, Swift requires that you use an explicit `.init()`, however, the `redundantInit` rule is not currently capable of detecting this situation in all cases, and may remove the `.init`. To work around this issue, use the `// swiftformat:disable:next redundantInit` comment directive to disable the rule for any affected lines of code (or just disable the `redundantInit` rule completely).
* The `--self insert` option can only recognize locally declared member variables, not ones inherited from superclasses or extensions in other files, so it cannot insert missing `self` references for those. Note that the reverse is not true: `--self remove` should remove *all* redundant `self` references.
@@ -822,6 +880,7 @@ Credits
* [Jim Puls](https://github.com/puls) - Big Sur icon update
* [Daniele Formichelli](https://github.com/danyf90) - JSON reporter
* [Mahdi Bchatnia](https://github.com/inket) - Linux build workflow
* [Arthur Semenyutin](https://github.com/vox-humana) - Docker image
* [Nick Lockwood](https://github.com/nicklockwood) - Everything else
([Full list of contributors](https://github.com/nicklockwood/SwiftFormat/graphs/contributors))
BIN
View File
Binary file not shown.
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.2.3</string>
<string>2.3.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -1,11 +0,0 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GradientLoadingBar
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LightweightObservable"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
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,26 +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>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>1.1.15</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.1.2</string>
<string>2.2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -1,10 +0,0 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/LightweightObservable
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
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}/LightweightObservable
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
@@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_Example : NSObject
@end
@implementation PodsDummy_Pods_Example
@end
@@ -0,0 +1,3 @@
${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh
${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework
${BUILT_PRODUCTS_DIR}/LightweightObservable/LightweightObservable.framework
@@ -0,0 +1,2 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GradientLoadingBar.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LightweightObservable.framework
@@ -0,0 +1,3 @@
${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh
${BUILT_PRODUCTS_DIR}/GradientLoadingBar/GradientLoadingBar.framework
${BUILT_PRODUCTS_DIR}/LightweightObservable/LightweightObservable.framework
@@ -0,0 +1,2 @@
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GradientLoadingBar.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LightweightObservable.framework
@@ -11,6 +11,6 @@
#endif
FOUNDATION_EXPORT double Pods_GradientLoadingBar_TestsVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_GradientLoadingBar_TestsVersionString[];
FOUNDATION_EXPORT double Pods_ExampleVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_ExampleVersionString[];
@@ -0,0 +1,6 @@
framework module Pods_Example {
umbrella header "Pods-Example-umbrella.h"
export *
module * { export * }
}

Some files were not shown because too many files have changed in this diff Show More