├── .github └── workflows │ ├── carthage.yml │ ├── cocoapods.yml │ ├── swiftlint.yml │ ├── upload-assets.yml │ ├── xcframework.yml │ └── xcodebuild.yml ├── .gitignore ├── .swiftlint.yml ├── Images ├── BackgroundAxial.png ├── BackgroundRadial.png ├── ForegroundAxial.png ├── ForegroundRadial.png └── JNGradientLabel.png ├── JNGradientLabel.podspec ├── JNGradientLabel.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── JNGradientLabel tvOS Example.xcscheme │ ├── JNGradientLabel tvOS.xcscheme │ ├── JNGradientLabel.xcscheme │ ├── JNGradientLabelExample.xcscheme │ ├── Run SwiftLint.xcscheme │ └── XCFramework.xcscheme ├── LICENSE ├── Package.swift ├── Plists └── JNGradientLabel-Info.plist ├── README.md ├── Resources ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon-iOS.appiconset │ │ └── Contents.json │ ├── AppIcon-tvOS.brandassets │ │ ├── App Icon - App Store.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ ├── App Icon.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Top Shelf Image Wide.imageset │ │ │ └── Contents.json │ │ └── Top Shelf Image.imageset │ │ │ └── Contents.json │ └── Contents.json ├── iOS │ └── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard └── tvOS │ └── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Sources ├── JNGradientLabel │ └── JNGradientLabel.swift └── JNGradientLabelExample │ ├── AppDelegate.swift │ └── ViewController.swift ├── codecov.yml └── scripts ├── carthage.sh ├── resolvepath.sh ├── versions.sh ├── workflowtests.sh └── xcframework.sh /.github/workflows/carthage.yml: -------------------------------------------------------------------------------- 1 | name: Carthage 2 | on: [push, workflow_dispatch] 3 | 4 | jobs: 5 | build: 6 | name: Build 7 | runs-on: macOS-latest 8 | steps: 9 | - name: Checkout Code 10 | uses: actions/checkout@v2 11 | 12 | - name: Install Carthage 13 | run: | 14 | brew update 15 | brew install carthage 16 | 17 | - name: Create Cartfile 18 | run: | 19 | # Delete all of the old tags (if any) and create a new tag for building 20 | git tag | xargs git tag -d 21 | git tag 1.0 22 | 23 | echo "git \"file://$(pwd)\"" > ./Cartfile 24 | 25 | - name: Build 26 | run: | 27 | ./scripts/carthage.sh update 28 | -------------------------------------------------------------------------------- /.github/workflows/cocoapods.yml: -------------------------------------------------------------------------------- 1 | name: Cocoapods 2 | on: [push, workflow_dispatch] 3 | 4 | jobs: 5 | lint: 6 | name: Lint 7 | runs-on: macOS-latest 8 | steps: 9 | - name: Checkout Code 10 | uses: actions/checkout@v2 11 | 12 | - name: Setup Cocoapods 13 | uses: maxim-lobanov/setup-cocoapods@v1 14 | with: 15 | version: latest 16 | 17 | - name: Lint (Dynamic Library) 18 | run: | 19 | pod lib lint 20 | 21 | - name: Lint (Static Library) 22 | run: | 23 | pod lib lint --use-libraries 24 | -------------------------------------------------------------------------------- /.github/workflows/swiftlint.yml: -------------------------------------------------------------------------------- 1 | name: SwiftLint 2 | on: [push, workflow_dispatch] 3 | 4 | jobs: 5 | build: 6 | name: Run SwiftLint 7 | runs-on: macOS-latest 8 | 9 | steps: 10 | - name: Checkout Code 11 | uses: actions/checkout@v2 12 | 13 | - name: Run SwiftLint 14 | run: | 15 | swiftlint lint --reporter github-actions-logging 16 | -------------------------------------------------------------------------------- /.github/workflows/upload-assets.yml: -------------------------------------------------------------------------------- 1 | name: Upload Assets 2 | on: 3 | release: 4 | types: [published] 5 | 6 | jobs: 7 | build: 8 | name: Upload Assets 9 | runs-on: macOS-latest 10 | env: 11 | TMPDIR: /tmp/.jngradientlabel.xcframework.build 12 | 13 | steps: 14 | - name: Checkout Code 15 | uses: actions/checkout@v2 16 | 17 | - name: Build 18 | run: | 19 | ./scripts/xcframework.sh -output ${TMPDIR}/JNGradientLabel.xcframework 20 | 21 | - name: Create Zip 22 | run: | 23 | cd ${TMPDIR} 24 | zip -rX JNGradientLabel.xcframework.zip JNGradientLabel.xcframework 25 | 26 | - name: Upload Zip 27 | uses: actions/upload-release-asset@v1 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | with: 31 | upload_url: ${{ github.event.release.upload_url }} 32 | asset_path: ${{ env.TMPDIR }}/JNGradientLabel.xcframework.zip 33 | asset_name: JNGradientLabel.xcframework.zip 34 | asset_content_type: application/zip 35 | 36 | - name: Create Tar 37 | run: | 38 | cd ${TMPDIR} 39 | tar -zcvf JNGradientLabel.xcframework.tar.gz JNGradientLabel.xcframework 40 | 41 | - name: Upload Tar 42 | uses: actions/upload-release-asset@v1 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | with: 46 | upload_url: ${{ github.event.release.upload_url }} 47 | asset_path: ${{ env.TMPDIR }}/JNGradientLabel.xcframework.tar.gz 48 | asset_name: JNGradientLabel.xcframework.tar.gz 49 | asset_content_type: application/gzip 50 | -------------------------------------------------------------------------------- /.github/workflows/xcframework.yml: -------------------------------------------------------------------------------- 1 | name: XCFramework 2 | on: [push, workflow_dispatch] 3 | 4 | jobs: 5 | build: 6 | name: Build 7 | runs-on: macOS-latest 8 | env: 9 | TMPDIR: /tmp/.jngradientlabel.xcframework.build 10 | 11 | steps: 12 | - name: Checkout Code 13 | uses: actions/checkout@v2 14 | 15 | - name: Build 16 | run: | 17 | ./scripts/xcframework.sh -output ${TMPDIR}/JNGradientLabel.xcframework 18 | -------------------------------------------------------------------------------- /.github/workflows/xcodebuild.yml: -------------------------------------------------------------------------------- 1 | name: Xcode Project 2 | on: [push, workflow_dispatch] 3 | 4 | jobs: 5 | ios: 6 | name: iOS 7 | runs-on: macOS-latest 8 | 9 | steps: 10 | - name: Checkout Code 11 | uses: actions/checkout@v2 12 | 13 | - name: Build iOS 14 | run: | 15 | xcodebuild -project JNGradientLabel.xcodeproj -scheme "JNGradientLabel" -destination "generic/platform=iOS" -configuration Debug 16 | 17 | - name: Build iOS Simulator 18 | run: | 19 | xcodebuild -project JNGradientLabel.xcodeproj -scheme "JNGradientLabel" -destination "generic/platform=iOS Simulator" -configuration Debug 20 | 21 | maccatalyst: 22 | name: Mac Catalyst 23 | runs-on: macOS-latest 24 | 25 | steps: 26 | - name: Checkout Code 27 | uses: actions/checkout@v2 28 | 29 | - name: Build 30 | run: | 31 | xcodebuild -project JNGradientLabel.xcodeproj -scheme "JNGradientLabel" -destination "generic/platform=macOS,variant=Mac Catalyst" -configuration Debug 32 | 33 | tvos: 34 | name: tvOS 35 | runs-on: macOS-latest 36 | 37 | steps: 38 | - name: Checkout Code 39 | uses: actions/checkout@v2 40 | 41 | - name: Build tvOS 42 | run: | 43 | xcodebuild -project JNGradientLabel.xcodeproj -scheme "JNGradientLabel tvOS" -destination "generic/platform=tvOS" -configuration Debug 44 | 45 | - name: Build tvOS Simulator 46 | run: | 47 | xcodebuild -project JNGradientLabel.xcodeproj -scheme "JNGradientLabel tvOS" -destination "generic/platform=tvOS Simulator" -configuration Debug 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | JNGradientLabel.xcodeproj/project.xcworkspace 2 | JNGradientLabel.xcodeproj/xcuserdata 3 | 4 | .build 5 | .swiftpm 6 | scripts/build 7 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - file_length 3 | - line_length 4 | - cyclomatic_complexity 5 | - type_body_length 6 | - type_name 7 | 8 | opt_in_rules: 9 | - anyobject_protocol 10 | - array_init 11 | - closure_end_indentation 12 | - closure_spacing 13 | - contains_over_first_not_nil 14 | - discouraged_optional_boolean 15 | - discouraged_optional_collection 16 | - empty_count 17 | - empty_string 18 | - empty_xctest_method 19 | - explicit_init 20 | - fallthrough 21 | - first_where 22 | - force_unwrapping 23 | - function_default_parameter_at_end 24 | - inert_defer 25 | - no_extension_access_modifier 26 | - overridden_super_call 27 | - prohibited_super_call 28 | - redundant_nil_coalescing 29 | - vertical_parameter_alignment_on_call 30 | - pattern_matching_keywords 31 | - fatal_error_message 32 | - implicitly_unwrapped_optional 33 | - joined_default_parameter 34 | - let_var_whitespace 35 | - literal_expression_end_indentation 36 | - lower_acl_than_parent 37 | - modifier_order 38 | - multiline_arguments 39 | - multiline_function_chains 40 | - multiline_parameters 41 | - multiple_closures_with_trailing_closure 42 | - nesting 43 | - notification_center_detachment 44 | - number_separator 45 | - object_literal 46 | - operator_usage_whitespace 47 | - override_in_extension 48 | - private_action 49 | - private_outlet 50 | - redundant_type_annotation 51 | - single_test_class 52 | - sorted_imports 53 | - sorted_first_last 54 | - trailing_closure 55 | - unavailable_function 56 | - unneeded_parentheses_in_closure_argument 57 | - yoda_condition 58 | 59 | reporter: "xcode" 60 | 61 | function_body_length: 62 | - 60 #warning 63 | 64 | identifier_name: 65 | excluded: 66 | - i 67 | -------------------------------------------------------------------------------- /Images/BackgroundAxial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SomeRandomiOSDev/JNGradientLabel/bc9919979ce65e278c23241ac0c9117518ac89a9/Images/BackgroundAxial.png -------------------------------------------------------------------------------- /Images/BackgroundRadial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SomeRandomiOSDev/JNGradientLabel/bc9919979ce65e278c23241ac0c9117518ac89a9/Images/BackgroundRadial.png -------------------------------------------------------------------------------- /Images/ForegroundAxial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SomeRandomiOSDev/JNGradientLabel/bc9919979ce65e278c23241ac0c9117518ac89a9/Images/ForegroundAxial.png -------------------------------------------------------------------------------- /Images/ForegroundRadial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SomeRandomiOSDev/JNGradientLabel/bc9919979ce65e278c23241ac0c9117518ac89a9/Images/ForegroundRadial.png -------------------------------------------------------------------------------- /Images/JNGradientLabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SomeRandomiOSDev/JNGradientLabel/bc9919979ce65e278c23241ac0c9117518ac89a9/Images/JNGradientLabel.png -------------------------------------------------------------------------------- /JNGradientLabel.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "JNGradientLabel" 4 | s.version = "1.0.3" 5 | s.summary = "An `UILabel` subclass with a gradient color" 6 | s.description = <<-DESC 7 | An iOS/tvOS Swift framework that that provides a `UILabel` subclass that renders its text with a gradient color 8 | DESC 9 | 10 | s.homepage = "https://github.com/SomeRandomiOSDev/JNGradientLabel" 11 | s.license = "MIT" 12 | s.author = { "Joe Newton" => "somerandomiosdev@gmail.com" } 13 | s.source = { :git => "https://github.com/SomeRandomiOSDev/JNGradientLabel.git", :tag => s.version.to_s } 14 | 15 | s.ios.deployment_target = '9.0' 16 | s.tvos.deployment_target = '9.0' 17 | 18 | s.source_files = 'Sources/JNGradientLabel/*.swift' 19 | s.swift_versions = ['5.0'] 20 | s.cocoapods_version = '>= 1.7.3' 21 | 22 | end 23 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | DD2FBC27258BE8BB00DB3211 /* XCFramework */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = DD2FBC2A258BE8BB00DB3211 /* Build configuration list for PBXAggregateTarget "XCFramework" */; 13 | buildPhases = ( 14 | DD2FBC33258BE8C600DB3211 /* Build XCFramework */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = XCFramework; 19 | productName = XCFramework; 20 | }; 21 | DD86D56423D11C4B0046E63E /* Run SwiftLint */ = { 22 | isa = PBXAggregateTarget; 23 | buildConfigurationList = DD86D56523D11C4B0046E63E /* Build configuration list for PBXAggregateTarget "Run SwiftLint" */; 24 | buildPhases = ( 25 | DD86D56823D11C550046E63E /* Run SwiftLint */, 26 | ); 27 | dependencies = ( 28 | ); 29 | name = "Run SwiftLint"; 30 | productName = "Run SwiftLint"; 31 | }; 32 | /* End PBXAggregateTarget section */ 33 | 34 | /* Begin PBXBuildFile section */ 35 | DD7D53E627272E4B00E9D123 /* JNGradientLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D53E527272E4B00E9D123 /* JNGradientLabel.swift */; }; 36 | DD7D53E827272E4B00E9D123 /* JNGradientLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D53E527272E4B00E9D123 /* JNGradientLabel.swift */; }; 37 | DD7D540527272FEF00E9D123 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D540327272FEF00E9D123 /* ViewController.swift */; }; 38 | DD7D540627272FEF00E9D123 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D540427272FEF00E9D123 /* AppDelegate.swift */; }; 39 | DD7D540D2727303000E9D123 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7D54082727303000E9D123 /* LaunchScreen.storyboard */; }; 40 | DD7D540E2727303000E9D123 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7D540A2727303000E9D123 /* Main.storyboard */; }; 41 | DD7D540F2727303000E9D123 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD7D540C2727303000E9D123 /* Assets.xcassets */; }; 42 | DD7D54122727309500E9D123 /* JNGradientLabel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD86D53D23D11B3E0046E63E /* JNGradientLabel.framework */; }; 43 | DD7D54132727309500E9D123 /* JNGradientLabel.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD86D53D23D11B3E0046E63E /* JNGradientLabel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 44 | DD7D542D2727460600E9D123 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D540427272FEF00E9D123 /* AppDelegate.swift */; }; 45 | DD7D542E2727460600E9D123 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7D540327272FEF00E9D123 /* ViewController.swift */; }; 46 | DD7D542F2727461500E9D123 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD7D540C2727303000E9D123 /* Assets.xcassets */; }; 47 | DD7D5432272746DC00E9D123 /* JNGradientLabel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD86D58C23D11CA00046E63E /* JNGradientLabel.framework */; }; 48 | DD7D5433272746DC00E9D123 /* JNGradientLabel.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DD86D58C23D11CA00046E63E /* JNGradientLabel.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 49 | DD7D543D272747F400E9D123 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7D5439272747F400E9D123 /* Main.storyboard */; }; 50 | DD7D543E272747F400E9D123 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DD7D543B272747F400E9D123 /* LaunchScreen.storyboard */; }; 51 | /* End PBXBuildFile section */ 52 | 53 | /* Begin PBXContainerItemProxy section */ 54 | DD7D54142727309500E9D123 /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = DD86D53423D11B3E0046E63E /* Project object */; 57 | proxyType = 1; 58 | remoteGlobalIDString = DD86D53C23D11B3E0046E63E; 59 | remoteInfo = JNGradientLabel; 60 | }; 61 | DD7D5434272746DC00E9D123 /* PBXContainerItemProxy */ = { 62 | isa = PBXContainerItemProxy; 63 | containerPortal = DD86D53423D11B3E0046E63E /* Project object */; 64 | proxyType = 1; 65 | remoteGlobalIDString = DD86D58B23D11CA00046E63E; 66 | remoteInfo = "JNGradientLabel tvOS"; 67 | }; 68 | DD86D56923D11C6C0046E63E /* PBXContainerItemProxy */ = { 69 | isa = PBXContainerItemProxy; 70 | containerPortal = DD86D53423D11B3E0046E63E /* Project object */; 71 | proxyType = 1; 72 | remoteGlobalIDString = DD86D56423D11C4B0046E63E; 73 | remoteInfo = "Run SwiftLint"; 74 | }; 75 | DD86D5DA23D11DC90046E63E /* PBXContainerItemProxy */ = { 76 | isa = PBXContainerItemProxy; 77 | containerPortal = DD86D53423D11B3E0046E63E /* Project object */; 78 | proxyType = 1; 79 | remoteGlobalIDString = DD86D56423D11C4B0046E63E; 80 | remoteInfo = "Run SwiftLint"; 81 | }; 82 | /* End PBXContainerItemProxy section */ 83 | 84 | /* Begin PBXCopyFilesBuildPhase section */ 85 | DD7D54162727309500E9D123 /* Embed Frameworks */ = { 86 | isa = PBXCopyFilesBuildPhase; 87 | buildActionMask = 2147483647; 88 | dstPath = ""; 89 | dstSubfolderSpec = 10; 90 | files = ( 91 | DD7D54132727309500E9D123 /* JNGradientLabel.framework in Embed Frameworks */, 92 | ); 93 | name = "Embed Frameworks"; 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | DD7D5436272746DC00E9D123 /* Embed Frameworks */ = { 97 | isa = PBXCopyFilesBuildPhase; 98 | buildActionMask = 2147483647; 99 | dstPath = ""; 100 | dstSubfolderSpec = 10; 101 | files = ( 102 | DD7D5433272746DC00E9D123 /* JNGradientLabel.framework in Embed Frameworks */, 103 | ); 104 | name = "Embed Frameworks"; 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | /* End PBXCopyFilesBuildPhase section */ 108 | 109 | /* Begin PBXFileReference section */ 110 | DD17A9F9257744BC00D30599 /* scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scripts; sourceTree = ""; }; 111 | DD7D53E527272E4B00E9D123 /* JNGradientLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JNGradientLabel.swift; sourceTree = ""; }; 112 | DD7D53EE27272FA200E9D123 /* JNGradientLabelExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JNGradientLabelExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 113 | DD7D540327272FEF00E9D123 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 114 | DD7D540427272FEF00E9D123 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 115 | DD7D54092727303000E9D123 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 116 | DD7D540B2727303000E9D123 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 117 | DD7D540C2727303000E9D123 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 118 | DD7D541C2727459700E9D123 /* JNGradientLabelExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JNGradientLabelExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 119 | DD7D543A272747F400E9D123 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 120 | DD7D543C272747F400E9D123 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 121 | DD86D53D23D11B3E0046E63E /* JNGradientLabel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JNGradientLabel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 122 | DD86D54123D11B3E0046E63E /* JNGradientLabel-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "JNGradientLabel-Info.plist"; path = "Plists/JNGradientLabel-Info.plist"; sourceTree = ""; }; 123 | DD86D58C23D11CA00046E63E /* JNGradientLabel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JNGradientLabel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 124 | DD86D5DE23D22DB90046E63E /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; 125 | DD86D5DF23D22DB90046E63E /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; }; 126 | DD86D5E023D22DB90046E63E /* JNGradientLabel.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = JNGradientLabel.podspec; sourceTree = SOURCE_ROOT; }; 127 | DD86D5E123D22DB90046E63E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 128 | DD86D5E323D22DC30046E63E /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = SOURCE_ROOT; }; 129 | DDA26DBD256EA4D700E1C6D7 /* workflows */ = {isa = PBXFileReference; lastKnownFileType = folder; name = workflows; path = .github/workflows; sourceTree = ""; }; 130 | DDB1DE5C2405EEE300C20FED /* codecov.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = codecov.yml; sourceTree = ""; }; 131 | /* End PBXFileReference section */ 132 | 133 | /* Begin PBXFrameworksBuildPhase section */ 134 | DD7D53EB27272FA200E9D123 /* Frameworks */ = { 135 | isa = PBXFrameworksBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | DD7D54122727309500E9D123 /* JNGradientLabel.framework in Frameworks */, 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | DD7D54192727459700E9D123 /* Frameworks */ = { 143 | isa = PBXFrameworksBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | DD7D5432272746DC00E9D123 /* JNGradientLabel.framework in Frameworks */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | DD86D53A23D11B3E0046E63E /* Frameworks */ = { 151 | isa = PBXFrameworksBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | DD86D58923D11CA00046E63E /* Frameworks */ = { 158 | isa = PBXFrameworksBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXFrameworksBuildPhase section */ 165 | 166 | /* Begin PBXGroup section */ 167 | DD5D04E52621361600BA0FC2 /* JNGradientLabel */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | DD7D53E527272E4B00E9D123 /* JNGradientLabel.swift */, 171 | ); 172 | path = JNGradientLabel; 173 | sourceTree = ""; 174 | }; 175 | DD7D540227272FEF00E9D123 /* JNGradientLabelExample */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | DD7D540427272FEF00E9D123 /* AppDelegate.swift */, 179 | DD7D540327272FEF00E9D123 /* ViewController.swift */, 180 | ); 181 | path = JNGradientLabelExample; 182 | sourceTree = ""; 183 | }; 184 | DD7D54072727303000E9D123 /* Resources */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | DD7D54372727473C00E9D123 /* iOS */, 188 | DD7D54382727474700E9D123 /* tvOS */, 189 | DD7D540C2727303000E9D123 /* Assets.xcassets */, 190 | ); 191 | path = Resources; 192 | sourceTree = ""; 193 | }; 194 | DD7D54112727309500E9D123 /* Frameworks */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | ); 198 | name = Frameworks; 199 | sourceTree = ""; 200 | }; 201 | DD7D54372727473C00E9D123 /* iOS */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | DD7D54082727303000E9D123 /* LaunchScreen.storyboard */, 205 | DD7D540A2727303000E9D123 /* Main.storyboard */, 206 | ); 207 | path = iOS; 208 | sourceTree = ""; 209 | }; 210 | DD7D54382727474700E9D123 /* tvOS */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | DD7D543B272747F400E9D123 /* LaunchScreen.storyboard */, 214 | DD7D5439272747F400E9D123 /* Main.storyboard */, 215 | ); 216 | path = tvOS; 217 | sourceTree = ""; 218 | }; 219 | DD86D53323D11B3E0046E63E = { 220 | isa = PBXGroup; 221 | children = ( 222 | DD86D53F23D11B3E0046E63E /* JNGradientLabel */, 223 | DD86D53E23D11B3E0046E63E /* Products */, 224 | DD7D54112727309500E9D123 /* Frameworks */, 225 | ); 226 | sourceTree = ""; 227 | }; 228 | DD86D53E23D11B3E0046E63E /* Products */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | DD86D53D23D11B3E0046E63E /* JNGradientLabel.framework */, 232 | DD86D58C23D11CA00046E63E /* JNGradientLabel.framework */, 233 | DD7D53EE27272FA200E9D123 /* JNGradientLabelExample.app */, 234 | DD7D541C2727459700E9D123 /* JNGradientLabelExample.app */, 235 | ); 236 | name = Products; 237 | sourceTree = ""; 238 | }; 239 | DD86D53F23D11B3E0046E63E /* JNGradientLabel */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | DD7D54072727303000E9D123 /* Resources */, 243 | DDB1DE252405EE5F00C20FED /* Sources */, 244 | DD86D55B23D11BA80046E63E /* Supporting Files */, 245 | ); 246 | name = JNGradientLabel; 247 | sourceTree = ""; 248 | }; 249 | DD86D55B23D11BA80046E63E /* Supporting Files */ = { 250 | isa = PBXGroup; 251 | children = ( 252 | DD17A9F9257744BC00D30599 /* scripts */, 253 | DDA26DBD256EA4D700E1C6D7 /* workflows */, 254 | DD86D5E023D22DB90046E63E /* JNGradientLabel.podspec */, 255 | DD86D5DF23D22DB90046E63E /* Package.swift */, 256 | DDB1DE5C2405EEE300C20FED /* codecov.yml */, 257 | DD86D5E323D22DC30046E63E /* .swiftlint.yml */, 258 | DD86D5E123D22DB90046E63E /* README.md */, 259 | DD86D5DE23D22DB90046E63E /* LICENSE */, 260 | DD86D54123D11B3E0046E63E /* JNGradientLabel-Info.plist */, 261 | ); 262 | name = "Supporting Files"; 263 | sourceTree = ""; 264 | }; 265 | DDB1DE252405EE5F00C20FED /* Sources */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | DD5D04E52621361600BA0FC2 /* JNGradientLabel */, 269 | DD7D540227272FEF00E9D123 /* JNGradientLabelExample */, 270 | ); 271 | path = Sources; 272 | sourceTree = ""; 273 | }; 274 | /* End PBXGroup section */ 275 | 276 | /* Begin PBXHeadersBuildPhase section */ 277 | DD86D53823D11B3E0046E63E /* Headers */ = { 278 | isa = PBXHeadersBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | DD86D58723D11CA00046E63E /* Headers */ = { 285 | isa = PBXHeadersBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXHeadersBuildPhase section */ 292 | 293 | /* Begin PBXNativeTarget section */ 294 | DD7D53ED27272FA200E9D123 /* JNGradientLabelExample */ = { 295 | isa = PBXNativeTarget; 296 | buildConfigurationList = DD7D53FF27272FA500E9D123 /* Build configuration list for PBXNativeTarget "JNGradientLabelExample" */; 297 | buildPhases = ( 298 | DD7D53EA27272FA200E9D123 /* Sources */, 299 | DD7D53EB27272FA200E9D123 /* Frameworks */, 300 | DD7D53EC27272FA200E9D123 /* Resources */, 301 | DD7D54162727309500E9D123 /* Embed Frameworks */, 302 | ); 303 | buildRules = ( 304 | ); 305 | dependencies = ( 306 | DD7D54152727309500E9D123 /* PBXTargetDependency */, 307 | ); 308 | name = JNGradientLabelExample; 309 | productName = JNGradientLabelExample; 310 | productReference = DD7D53EE27272FA200E9D123 /* JNGradientLabelExample.app */; 311 | productType = "com.apple.product-type.application"; 312 | }; 313 | DD7D541B2727459700E9D123 /* JNGradientLabel tvOS Example */ = { 314 | isa = PBXNativeTarget; 315 | buildConfigurationList = DD7D542A2727459D00E9D123 /* Build configuration list for PBXNativeTarget "JNGradientLabel tvOS Example" */; 316 | buildPhases = ( 317 | DD7D54182727459700E9D123 /* Sources */, 318 | DD7D54192727459700E9D123 /* Frameworks */, 319 | DD7D541A2727459700E9D123 /* Resources */, 320 | DD7D5436272746DC00E9D123 /* Embed Frameworks */, 321 | ); 322 | buildRules = ( 323 | ); 324 | dependencies = ( 325 | DD7D5435272746DC00E9D123 /* PBXTargetDependency */, 326 | ); 327 | name = "JNGradientLabel tvOS Example"; 328 | productName = "JNGradientLabel tvOS Example"; 329 | productReference = DD7D541C2727459700E9D123 /* JNGradientLabelExample.app */; 330 | productType = "com.apple.product-type.application"; 331 | }; 332 | DD86D53C23D11B3E0046E63E /* JNGradientLabel */ = { 333 | isa = PBXNativeTarget; 334 | buildConfigurationList = DD86D55123D11B3E0046E63E /* Build configuration list for PBXNativeTarget "JNGradientLabel" */; 335 | buildPhases = ( 336 | DD86D53823D11B3E0046E63E /* Headers */, 337 | DD86D53923D11B3E0046E63E /* Sources */, 338 | DD86D53A23D11B3E0046E63E /* Frameworks */, 339 | DD86D53B23D11B3E0046E63E /* Resources */, 340 | ); 341 | buildRules = ( 342 | ); 343 | dependencies = ( 344 | DD86D56A23D11C6C0046E63E /* PBXTargetDependency */, 345 | ); 346 | name = JNGradientLabel; 347 | productName = JNGradientLabel; 348 | productReference = DD86D53D23D11B3E0046E63E /* JNGradientLabel.framework */; 349 | productType = "com.apple.product-type.framework"; 350 | }; 351 | DD86D58B23D11CA00046E63E /* JNGradientLabel tvOS */ = { 352 | isa = PBXNativeTarget; 353 | buildConfigurationList = DD86D59D23D11CA00046E63E /* Build configuration list for PBXNativeTarget "JNGradientLabel tvOS" */; 354 | buildPhases = ( 355 | DD86D58723D11CA00046E63E /* Headers */, 356 | DD86D58823D11CA00046E63E /* Sources */, 357 | DD86D58923D11CA00046E63E /* Frameworks */, 358 | DD86D58A23D11CA00046E63E /* Resources */, 359 | ); 360 | buildRules = ( 361 | ); 362 | dependencies = ( 363 | DD86D5DB23D11DC90046E63E /* PBXTargetDependency */, 364 | ); 365 | name = "JNGradientLabel tvOS"; 366 | productName = "JNGradientLabel tvOS"; 367 | productReference = DD86D58C23D11CA00046E63E /* JNGradientLabel.framework */; 368 | productType = "com.apple.product-type.framework"; 369 | }; 370 | /* End PBXNativeTarget section */ 371 | 372 | /* Begin PBXProject section */ 373 | DD86D53423D11B3E0046E63E /* Project object */ = { 374 | isa = PBXProject; 375 | attributes = { 376 | LastSwiftUpdateCheck = 1300; 377 | LastUpgradeCheck = 1300; 378 | ORGANIZATIONNAME = SomeRandomiOSDev; 379 | TargetAttributes = { 380 | DD2FBC27258BE8BB00DB3211 = { 381 | CreatedOnToolsVersion = 13.0; 382 | LastSwiftMigration = 1300; 383 | }; 384 | DD7D53ED27272FA200E9D123 = { 385 | CreatedOnToolsVersion = 13.0; 386 | }; 387 | DD7D541B2727459700E9D123 = { 388 | CreatedOnToolsVersion = 13.0; 389 | }; 390 | DD86D53C23D11B3E0046E63E = { 391 | CreatedOnToolsVersion = 13.0; 392 | LastSwiftMigration = 1300; 393 | }; 394 | DD86D56423D11C4B0046E63E = { 395 | CreatedOnToolsVersion = 13.0; 396 | LastSwiftMigration = 1300; 397 | }; 398 | DD86D58B23D11CA00046E63E = { 399 | CreatedOnToolsVersion = 13.0; 400 | LastSwiftMigration = 1300; 401 | }; 402 | }; 403 | }; 404 | buildConfigurationList = DD86D53723D11B3E0046E63E /* Build configuration list for PBXProject "JNGradientLabel" */; 405 | compatibilityVersion = "Xcode 9.3"; 406 | developmentRegion = en; 407 | hasScannedForEncodings = 0; 408 | knownRegions = ( 409 | en, 410 | Base, 411 | ); 412 | mainGroup = DD86D53323D11B3E0046E63E; 413 | productRefGroup = DD86D53E23D11B3E0046E63E /* Products */; 414 | projectDirPath = ""; 415 | projectRoot = ""; 416 | targets = ( 417 | DD86D53C23D11B3E0046E63E /* JNGradientLabel */, 418 | DD86D58B23D11CA00046E63E /* JNGradientLabel tvOS */, 419 | DD7D53ED27272FA200E9D123 /* JNGradientLabelExample */, 420 | DD7D541B2727459700E9D123 /* JNGradientLabel tvOS Example */, 421 | DD86D56423D11C4B0046E63E /* Run SwiftLint */, 422 | DD2FBC27258BE8BB00DB3211 /* XCFramework */, 423 | ); 424 | }; 425 | /* End PBXProject section */ 426 | 427 | /* Begin PBXResourcesBuildPhase section */ 428 | DD7D53EC27272FA200E9D123 /* Resources */ = { 429 | isa = PBXResourcesBuildPhase; 430 | buildActionMask = 2147483647; 431 | files = ( 432 | DD7D540F2727303000E9D123 /* Assets.xcassets in Resources */, 433 | DD7D540D2727303000E9D123 /* LaunchScreen.storyboard in Resources */, 434 | DD7D540E2727303000E9D123 /* Main.storyboard in Resources */, 435 | ); 436 | runOnlyForDeploymentPostprocessing = 0; 437 | }; 438 | DD7D541A2727459700E9D123 /* Resources */ = { 439 | isa = PBXResourcesBuildPhase; 440 | buildActionMask = 2147483647; 441 | files = ( 442 | DD7D543D272747F400E9D123 /* Main.storyboard in Resources */, 443 | DD7D543E272747F400E9D123 /* LaunchScreen.storyboard in Resources */, 444 | DD7D542F2727461500E9D123 /* Assets.xcassets in Resources */, 445 | ); 446 | runOnlyForDeploymentPostprocessing = 0; 447 | }; 448 | DD86D53B23D11B3E0046E63E /* Resources */ = { 449 | isa = PBXResourcesBuildPhase; 450 | buildActionMask = 2147483647; 451 | files = ( 452 | ); 453 | runOnlyForDeploymentPostprocessing = 0; 454 | }; 455 | DD86D58A23D11CA00046E63E /* Resources */ = { 456 | isa = PBXResourcesBuildPhase; 457 | buildActionMask = 2147483647; 458 | files = ( 459 | ); 460 | runOnlyForDeploymentPostprocessing = 0; 461 | }; 462 | /* End PBXResourcesBuildPhase section */ 463 | 464 | /* Begin PBXShellScriptBuildPhase section */ 465 | DD2FBC33258BE8C600DB3211 /* Build XCFramework */ = { 466 | isa = PBXShellScriptBuildPhase; 467 | buildActionMask = 2147483647; 468 | files = ( 469 | ); 470 | inputFileListPaths = ( 471 | ); 472 | inputPaths = ( 473 | ); 474 | name = "Build XCFramework"; 475 | outputFileListPaths = ( 476 | ); 477 | outputPaths = ( 478 | ); 479 | runOnlyForDeploymentPostprocessing = 0; 480 | shellPath = /bin/sh; 481 | shellScript = "${PROJECT_DIR}/scripts/xcframework.sh -configuration ${CONFIGURATION} -output \"${BUILD_DIR}/${CONFIGURATION}-universal/JNGradientLabel.xcframework\" \n"; 482 | }; 483 | DD86D56823D11C550046E63E /* Run SwiftLint */ = { 484 | isa = PBXShellScriptBuildPhase; 485 | buildActionMask = 2147483647; 486 | files = ( 487 | ); 488 | inputFileListPaths = ( 489 | ); 490 | inputPaths = ( 491 | ); 492 | name = "Run SwiftLint"; 493 | outputFileListPaths = ( 494 | ); 495 | outputPaths = ( 496 | ); 497 | runOnlyForDeploymentPostprocessing = 0; 498 | shellPath = /bin/sh; 499 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; 500 | }; 501 | /* End PBXShellScriptBuildPhase section */ 502 | 503 | /* Begin PBXSourcesBuildPhase section */ 504 | DD7D53EA27272FA200E9D123 /* Sources */ = { 505 | isa = PBXSourcesBuildPhase; 506 | buildActionMask = 2147483647; 507 | files = ( 508 | DD7D540627272FEF00E9D123 /* AppDelegate.swift in Sources */, 509 | DD7D540527272FEF00E9D123 /* ViewController.swift in Sources */, 510 | ); 511 | runOnlyForDeploymentPostprocessing = 0; 512 | }; 513 | DD7D54182727459700E9D123 /* Sources */ = { 514 | isa = PBXSourcesBuildPhase; 515 | buildActionMask = 2147483647; 516 | files = ( 517 | DD7D542E2727460600E9D123 /* ViewController.swift in Sources */, 518 | DD7D542D2727460600E9D123 /* AppDelegate.swift in Sources */, 519 | ); 520 | runOnlyForDeploymentPostprocessing = 0; 521 | }; 522 | DD86D53923D11B3E0046E63E /* Sources */ = { 523 | isa = PBXSourcesBuildPhase; 524 | buildActionMask = 2147483647; 525 | files = ( 526 | DD7D53E627272E4B00E9D123 /* JNGradientLabel.swift in Sources */, 527 | ); 528 | runOnlyForDeploymentPostprocessing = 0; 529 | }; 530 | DD86D58823D11CA00046E63E /* Sources */ = { 531 | isa = PBXSourcesBuildPhase; 532 | buildActionMask = 2147483647; 533 | files = ( 534 | DD7D53E827272E4B00E9D123 /* JNGradientLabel.swift in Sources */, 535 | ); 536 | runOnlyForDeploymentPostprocessing = 0; 537 | }; 538 | /* End PBXSourcesBuildPhase section */ 539 | 540 | /* Begin PBXTargetDependency section */ 541 | DD7D54152727309500E9D123 /* PBXTargetDependency */ = { 542 | isa = PBXTargetDependency; 543 | target = DD86D53C23D11B3E0046E63E /* JNGradientLabel */; 544 | targetProxy = DD7D54142727309500E9D123 /* PBXContainerItemProxy */; 545 | }; 546 | DD7D5435272746DC00E9D123 /* PBXTargetDependency */ = { 547 | isa = PBXTargetDependency; 548 | target = DD86D58B23D11CA00046E63E /* JNGradientLabel tvOS */; 549 | targetProxy = DD7D5434272746DC00E9D123 /* PBXContainerItemProxy */; 550 | }; 551 | DD86D56A23D11C6C0046E63E /* PBXTargetDependency */ = { 552 | isa = PBXTargetDependency; 553 | target = DD86D56423D11C4B0046E63E /* Run SwiftLint */; 554 | targetProxy = DD86D56923D11C6C0046E63E /* PBXContainerItemProxy */; 555 | }; 556 | DD86D5DB23D11DC90046E63E /* PBXTargetDependency */ = { 557 | isa = PBXTargetDependency; 558 | target = DD86D56423D11C4B0046E63E /* Run SwiftLint */; 559 | targetProxy = DD86D5DA23D11DC90046E63E /* PBXContainerItemProxy */; 560 | }; 561 | /* End PBXTargetDependency section */ 562 | 563 | /* Begin PBXVariantGroup section */ 564 | DD7D54082727303000E9D123 /* LaunchScreen.storyboard */ = { 565 | isa = PBXVariantGroup; 566 | children = ( 567 | DD7D54092727303000E9D123 /* Base */, 568 | ); 569 | name = LaunchScreen.storyboard; 570 | sourceTree = ""; 571 | }; 572 | DD7D540A2727303000E9D123 /* Main.storyboard */ = { 573 | isa = PBXVariantGroup; 574 | children = ( 575 | DD7D540B2727303000E9D123 /* Base */, 576 | ); 577 | name = Main.storyboard; 578 | sourceTree = ""; 579 | }; 580 | DD7D5439272747F400E9D123 /* Main.storyboard */ = { 581 | isa = PBXVariantGroup; 582 | children = ( 583 | DD7D543A272747F400E9D123 /* Base */, 584 | ); 585 | name = Main.storyboard; 586 | sourceTree = ""; 587 | }; 588 | DD7D543B272747F400E9D123 /* LaunchScreen.storyboard */ = { 589 | isa = PBXVariantGroup; 590 | children = ( 591 | DD7D543C272747F400E9D123 /* Base */, 592 | ); 593 | name = LaunchScreen.storyboard; 594 | sourceTree = ""; 595 | }; 596 | /* End PBXVariantGroup section */ 597 | 598 | /* Begin XCBuildConfiguration section */ 599 | DD2FBC28258BE8BB00DB3211 /* Debug */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | CODE_SIGN_STYLE = Automatic; 603 | PRODUCT_NAME = "$(TARGET_NAME)"; 604 | }; 605 | name = Debug; 606 | }; 607 | DD2FBC29258BE8BB00DB3211 /* Release */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | CODE_SIGN_STYLE = Automatic; 611 | PRODUCT_NAME = "$(TARGET_NAME)"; 612 | }; 613 | name = Release; 614 | }; 615 | DD7D540027272FA500E9D123 /* Debug */ = { 616 | isa = XCBuildConfiguration; 617 | buildSettings = { 618 | ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-iOS"; 619 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 620 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 621 | CODE_SIGN_IDENTITY = ""; 622 | CODE_SIGN_STYLE = Automatic; 623 | CURRENT_PROJECT_VERSION = 1; 624 | GENERATE_INFOPLIST_FILE = YES; 625 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 626 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 627 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 628 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 629 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 630 | LD_RUNPATH_SEARCH_PATHS = ( 631 | "$(inherited)", 632 | "@executable_path/Frameworks", 633 | ); 634 | MARKETING_VERSION = 1.0; 635 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabelexample; 636 | PRODUCT_NAME = "$(TARGET_NAME)"; 637 | SUPPORTS_MACCATALYST = NO; 638 | SWIFT_EMIT_LOC_STRINGS = YES; 639 | SWIFT_VERSION = 5.0; 640 | TARGETED_DEVICE_FAMILY = "1,2"; 641 | }; 642 | name = Debug; 643 | }; 644 | DD7D540127272FA500E9D123 /* Release */ = { 645 | isa = XCBuildConfiguration; 646 | buildSettings = { 647 | ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-iOS"; 648 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 649 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 650 | CODE_SIGN_IDENTITY = ""; 651 | CODE_SIGN_STYLE = Automatic; 652 | CURRENT_PROJECT_VERSION = 1; 653 | GENERATE_INFOPLIST_FILE = YES; 654 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 655 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 656 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 657 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 658 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 659 | LD_RUNPATH_SEARCH_PATHS = ( 660 | "$(inherited)", 661 | "@executable_path/Frameworks", 662 | ); 663 | MARKETING_VERSION = 1.0; 664 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabelexample; 665 | PRODUCT_NAME = "$(TARGET_NAME)"; 666 | SUPPORTS_MACCATALYST = NO; 667 | SWIFT_EMIT_LOC_STRINGS = YES; 668 | SWIFT_VERSION = 5.0; 669 | TARGETED_DEVICE_FAMILY = "1,2"; 670 | }; 671 | name = Release; 672 | }; 673 | DD7D542B2727459D00E9D123 /* Debug */ = { 674 | isa = XCBuildConfiguration; 675 | buildSettings = { 676 | ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-tvOS"; 677 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 678 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 679 | CODE_SIGN_IDENTITY = ""; 680 | CODE_SIGN_STYLE = Automatic; 681 | CURRENT_PROJECT_VERSION = 1; 682 | GENERATE_INFOPLIST_FILE = YES; 683 | INFOPLIST_KEY_CFBundleDisplayName = JNGradientLabelExample; 684 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 685 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 686 | INFOPLIST_KEY_UIRequiredDeviceCapabilities = armv7; 687 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 688 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 689 | INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; 690 | LD_RUNPATH_SEARCH_PATHS = ( 691 | "$(inherited)", 692 | "@executable_path/Frameworks", 693 | ); 694 | MARKETING_VERSION = 1.0; 695 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabelexample; 696 | PRODUCT_NAME = JNGradientLabelExample; 697 | SDKROOT = appletvos; 698 | SWIFT_EMIT_LOC_STRINGS = YES; 699 | SWIFT_VERSION = 5.0; 700 | TARGETED_DEVICE_FAMILY = 3; 701 | }; 702 | name = Debug; 703 | }; 704 | DD7D542C2727459D00E9D123 /* Release */ = { 705 | isa = XCBuildConfiguration; 706 | buildSettings = { 707 | ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-tvOS"; 708 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 709 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 710 | CODE_SIGN_IDENTITY = ""; 711 | CODE_SIGN_STYLE = Automatic; 712 | CURRENT_PROJECT_VERSION = 1; 713 | GENERATE_INFOPLIST_FILE = YES; 714 | INFOPLIST_KEY_CFBundleDisplayName = JNGradientLabelExample; 715 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 716 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 717 | INFOPLIST_KEY_UIRequiredDeviceCapabilities = armv7; 718 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 719 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 720 | INFOPLIST_KEY_UIUserInterfaceStyle = Automatic; 721 | LD_RUNPATH_SEARCH_PATHS = ( 722 | "$(inherited)", 723 | "@executable_path/Frameworks", 724 | ); 725 | MARKETING_VERSION = 1.0; 726 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabelexample; 727 | PRODUCT_NAME = JNGradientLabelExample; 728 | SDKROOT = appletvos; 729 | SWIFT_EMIT_LOC_STRINGS = YES; 730 | SWIFT_VERSION = 5.0; 731 | TARGETED_DEVICE_FAMILY = 3; 732 | }; 733 | name = Release; 734 | }; 735 | DD86D54F23D11B3E0046E63E /* Debug */ = { 736 | isa = XCBuildConfiguration; 737 | buildSettings = { 738 | ALWAYS_SEARCH_USER_PATHS = NO; 739 | CLANG_ANALYZER_NONNULL = YES; 740 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 741 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 742 | CLANG_CXX_LIBRARY = "libc++"; 743 | CLANG_ENABLE_MODULES = YES; 744 | CLANG_ENABLE_OBJC_ARC = YES; 745 | CLANG_ENABLE_OBJC_WEAK = YES; 746 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 747 | CLANG_WARN_BOOL_CONVERSION = YES; 748 | CLANG_WARN_COMMA = YES; 749 | CLANG_WARN_CONSTANT_CONVERSION = YES; 750 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 751 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 752 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 753 | CLANG_WARN_EMPTY_BODY = YES; 754 | CLANG_WARN_ENUM_CONVERSION = YES; 755 | CLANG_WARN_INFINITE_RECURSION = YES; 756 | CLANG_WARN_INT_CONVERSION = YES; 757 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 758 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 759 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 760 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 761 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 762 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 763 | CLANG_WARN_STRICT_PROTOTYPES = YES; 764 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 765 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 766 | CLANG_WARN_UNREACHABLE_CODE = YES; 767 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 768 | CODE_SIGN_IDENTITY = "iPhone Developer"; 769 | COPY_PHASE_STRIP = NO; 770 | CURRENT_PROJECT_VERSION = 1; 771 | DEBUG_INFORMATION_FORMAT = dwarf; 772 | ENABLE_STRICT_OBJC_MSGSEND = YES; 773 | ENABLE_TESTABILITY = YES; 774 | GCC_C_LANGUAGE_STANDARD = gnu11; 775 | GCC_DYNAMIC_NO_PIC = NO; 776 | GCC_NO_COMMON_BLOCKS = YES; 777 | GCC_OPTIMIZATION_LEVEL = 0; 778 | GCC_PREPROCESSOR_DEFINITIONS = ( 779 | "DEBUG=1", 780 | "$(inherited)", 781 | ); 782 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 783 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 784 | GCC_WARN_UNDECLARED_SELECTOR = YES; 785 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 786 | GCC_WARN_UNUSED_FUNCTION = YES; 787 | GCC_WARN_UNUSED_VARIABLE = YES; 788 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 789 | MACOSX_DEPLOYMENT_TARGET = 10.10; 790 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 791 | MTL_FAST_MATH = YES; 792 | ONLY_ACTIVE_ARCH = YES; 793 | SDKROOT = iphoneos; 794 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 795 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 796 | SWIFT_VERSION = 5.0; 797 | TVOS_DEPLOYMENT_TARGET = 9.0; 798 | VERSIONING_SYSTEM = "apple-generic"; 799 | VERSION_INFO_PREFIX = ""; 800 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 801 | }; 802 | name = Debug; 803 | }; 804 | DD86D55023D11B3E0046E63E /* Release */ = { 805 | isa = XCBuildConfiguration; 806 | buildSettings = { 807 | ALWAYS_SEARCH_USER_PATHS = NO; 808 | CLANG_ANALYZER_NONNULL = YES; 809 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 810 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 811 | CLANG_CXX_LIBRARY = "libc++"; 812 | CLANG_ENABLE_MODULES = YES; 813 | CLANG_ENABLE_OBJC_ARC = YES; 814 | CLANG_ENABLE_OBJC_WEAK = YES; 815 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 816 | CLANG_WARN_BOOL_CONVERSION = YES; 817 | CLANG_WARN_COMMA = YES; 818 | CLANG_WARN_CONSTANT_CONVERSION = YES; 819 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 820 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 821 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 822 | CLANG_WARN_EMPTY_BODY = YES; 823 | CLANG_WARN_ENUM_CONVERSION = YES; 824 | CLANG_WARN_INFINITE_RECURSION = YES; 825 | CLANG_WARN_INT_CONVERSION = YES; 826 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 827 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 828 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 829 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 830 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 831 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 832 | CLANG_WARN_STRICT_PROTOTYPES = YES; 833 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 834 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 835 | CLANG_WARN_UNREACHABLE_CODE = YES; 836 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 837 | CODE_SIGN_IDENTITY = "iPhone Developer"; 838 | COPY_PHASE_STRIP = NO; 839 | CURRENT_PROJECT_VERSION = 1; 840 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 841 | ENABLE_NS_ASSERTIONS = NO; 842 | ENABLE_STRICT_OBJC_MSGSEND = YES; 843 | GCC_C_LANGUAGE_STANDARD = gnu11; 844 | GCC_NO_COMMON_BLOCKS = YES; 845 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 846 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 847 | GCC_WARN_UNDECLARED_SELECTOR = YES; 848 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 849 | GCC_WARN_UNUSED_FUNCTION = YES; 850 | GCC_WARN_UNUSED_VARIABLE = YES; 851 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 852 | MACOSX_DEPLOYMENT_TARGET = 10.10; 853 | MTL_ENABLE_DEBUG_INFO = NO; 854 | MTL_FAST_MATH = YES; 855 | SDKROOT = iphoneos; 856 | SWIFT_COMPILATION_MODE = wholemodule; 857 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 858 | SWIFT_VERSION = 5.0; 859 | TVOS_DEPLOYMENT_TARGET = 9.0; 860 | VALIDATE_PRODUCT = YES; 861 | VERSIONING_SYSTEM = "apple-generic"; 862 | VERSION_INFO_PREFIX = ""; 863 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 864 | }; 865 | name = Release; 866 | }; 867 | DD86D55223D11B3E0046E63E /* Debug */ = { 868 | isa = XCBuildConfiguration; 869 | buildSettings = { 870 | CLANG_ENABLE_MODULES = YES; 871 | CODE_SIGN_IDENTITY = ""; 872 | CODE_SIGN_STYLE = Automatic; 873 | DEFINES_MODULE = YES; 874 | DYLIB_COMPATIBILITY_VERSION = 1; 875 | DYLIB_CURRENT_VERSION = 1; 876 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 877 | INFOPLIST_FILE = "Plists/JNGradientLabel-Info.plist"; 878 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 879 | LD_RUNPATH_SEARCH_PATHS = ( 880 | "$(inherited)", 881 | "@executable_path/Frameworks", 882 | "@loader_path/Frameworks", 883 | ); 884 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabel; 885 | PRODUCT_NAME = JNGradientLabel; 886 | SKIP_INSTALL = YES; 887 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 888 | SWIFT_VERSION = 5.0; 889 | TARGETED_DEVICE_FAMILY = "1,2,6"; 890 | }; 891 | name = Debug; 892 | }; 893 | DD86D55323D11B3E0046E63E /* Release */ = { 894 | isa = XCBuildConfiguration; 895 | buildSettings = { 896 | CLANG_ENABLE_MODULES = YES; 897 | CODE_SIGN_IDENTITY = ""; 898 | CODE_SIGN_STYLE = Automatic; 899 | DEFINES_MODULE = YES; 900 | DYLIB_COMPATIBILITY_VERSION = 1; 901 | DYLIB_CURRENT_VERSION = 1; 902 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 903 | INFOPLIST_FILE = "Plists/JNGradientLabel-Info.plist"; 904 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 905 | LD_RUNPATH_SEARCH_PATHS = ( 906 | "$(inherited)", 907 | "@executable_path/Frameworks", 908 | "@loader_path/Frameworks", 909 | ); 910 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabel; 911 | PRODUCT_NAME = JNGradientLabel; 912 | SKIP_INSTALL = YES; 913 | SWIFT_VERSION = 5.0; 914 | TARGETED_DEVICE_FAMILY = "1,2,6"; 915 | }; 916 | name = Release; 917 | }; 918 | DD86D56623D11C4B0046E63E /* Debug */ = { 919 | isa = XCBuildConfiguration; 920 | buildSettings = { 921 | CODE_SIGN_STYLE = Automatic; 922 | PRODUCT_NAME = "$(TARGET_NAME)"; 923 | }; 924 | name = Debug; 925 | }; 926 | DD86D56723D11C4B0046E63E /* Release */ = { 927 | isa = XCBuildConfiguration; 928 | buildSettings = { 929 | CODE_SIGN_STYLE = Automatic; 930 | PRODUCT_NAME = "$(TARGET_NAME)"; 931 | }; 932 | name = Release; 933 | }; 934 | DD86D59E23D11CA00046E63E /* Debug */ = { 935 | isa = XCBuildConfiguration; 936 | buildSettings = { 937 | CLANG_ENABLE_MODULES = YES; 938 | CODE_SIGN_IDENTITY = ""; 939 | CODE_SIGN_STYLE = Automatic; 940 | DEFINES_MODULE = YES; 941 | DYLIB_COMPATIBILITY_VERSION = 1; 942 | DYLIB_CURRENT_VERSION = 1; 943 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 944 | INFOPLIST_FILE = "Plists/JNGradientLabel-Info.plist"; 945 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 946 | LD_RUNPATH_SEARCH_PATHS = ( 947 | "$(inherited)", 948 | "@executable_path/Frameworks", 949 | "@loader_path/Frameworks", 950 | ); 951 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabel; 952 | PRODUCT_NAME = JNGradientLabel; 953 | SDKROOT = appletvos; 954 | SKIP_INSTALL = YES; 955 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 956 | SWIFT_VERSION = 5.0; 957 | TARGETED_DEVICE_FAMILY = 3; 958 | }; 959 | name = Debug; 960 | }; 961 | DD86D59F23D11CA00046E63E /* Release */ = { 962 | isa = XCBuildConfiguration; 963 | buildSettings = { 964 | CLANG_ENABLE_MODULES = YES; 965 | CODE_SIGN_IDENTITY = ""; 966 | CODE_SIGN_STYLE = Automatic; 967 | DEFINES_MODULE = YES; 968 | DYLIB_COMPATIBILITY_VERSION = 1; 969 | DYLIB_CURRENT_VERSION = 1; 970 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 971 | INFOPLIST_FILE = "Plists/JNGradientLabel-Info.plist"; 972 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 973 | LD_RUNPATH_SEARCH_PATHS = ( 974 | "$(inherited)", 975 | "@executable_path/Frameworks", 976 | "@loader_path/Frameworks", 977 | ); 978 | PRODUCT_BUNDLE_IDENTIFIER = com.somerandomiosdev.jngradientlabel; 979 | PRODUCT_NAME = JNGradientLabel; 980 | SDKROOT = appletvos; 981 | SKIP_INSTALL = YES; 982 | SWIFT_VERSION = 5.0; 983 | TARGETED_DEVICE_FAMILY = 3; 984 | }; 985 | name = Release; 986 | }; 987 | /* End XCBuildConfiguration section */ 988 | 989 | /* Begin XCConfigurationList section */ 990 | DD2FBC2A258BE8BB00DB3211 /* Build configuration list for PBXAggregateTarget "XCFramework" */ = { 991 | isa = XCConfigurationList; 992 | buildConfigurations = ( 993 | DD2FBC28258BE8BB00DB3211 /* Debug */, 994 | DD2FBC29258BE8BB00DB3211 /* Release */, 995 | ); 996 | defaultConfigurationIsVisible = 0; 997 | defaultConfigurationName = Release; 998 | }; 999 | DD7D53FF27272FA500E9D123 /* Build configuration list for PBXNativeTarget "JNGradientLabelExample" */ = { 1000 | isa = XCConfigurationList; 1001 | buildConfigurations = ( 1002 | DD7D540027272FA500E9D123 /* Debug */, 1003 | DD7D540127272FA500E9D123 /* Release */, 1004 | ); 1005 | defaultConfigurationIsVisible = 0; 1006 | defaultConfigurationName = Release; 1007 | }; 1008 | DD7D542A2727459D00E9D123 /* Build configuration list for PBXNativeTarget "JNGradientLabel tvOS Example" */ = { 1009 | isa = XCConfigurationList; 1010 | buildConfigurations = ( 1011 | DD7D542B2727459D00E9D123 /* Debug */, 1012 | DD7D542C2727459D00E9D123 /* Release */, 1013 | ); 1014 | defaultConfigurationIsVisible = 0; 1015 | defaultConfigurationName = Release; 1016 | }; 1017 | DD86D53723D11B3E0046E63E /* Build configuration list for PBXProject "JNGradientLabel" */ = { 1018 | isa = XCConfigurationList; 1019 | buildConfigurations = ( 1020 | DD86D54F23D11B3E0046E63E /* Debug */, 1021 | DD86D55023D11B3E0046E63E /* Release */, 1022 | ); 1023 | defaultConfigurationIsVisible = 0; 1024 | defaultConfigurationName = Release; 1025 | }; 1026 | DD86D55123D11B3E0046E63E /* Build configuration list for PBXNativeTarget "JNGradientLabel" */ = { 1027 | isa = XCConfigurationList; 1028 | buildConfigurations = ( 1029 | DD86D55223D11B3E0046E63E /* Debug */, 1030 | DD86D55323D11B3E0046E63E /* Release */, 1031 | ); 1032 | defaultConfigurationIsVisible = 0; 1033 | defaultConfigurationName = Release; 1034 | }; 1035 | DD86D56523D11C4B0046E63E /* Build configuration list for PBXAggregateTarget "Run SwiftLint" */ = { 1036 | isa = XCConfigurationList; 1037 | buildConfigurations = ( 1038 | DD86D56623D11C4B0046E63E /* Debug */, 1039 | DD86D56723D11C4B0046E63E /* Release */, 1040 | ); 1041 | defaultConfigurationIsVisible = 0; 1042 | defaultConfigurationName = Release; 1043 | }; 1044 | DD86D59D23D11CA00046E63E /* Build configuration list for PBXNativeTarget "JNGradientLabel tvOS" */ = { 1045 | isa = XCConfigurationList; 1046 | buildConfigurations = ( 1047 | DD86D59E23D11CA00046E63E /* Debug */, 1048 | DD86D59F23D11CA00046E63E /* Release */, 1049 | ); 1050 | defaultConfigurationIsVisible = 0; 1051 | defaultConfigurationName = Release; 1052 | }; 1053 | /* End XCConfigurationList section */ 1054 | }; 1055 | rootObject = DD86D53423D11B3E0046E63E /* Project object */; 1056 | } 1057 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/JNGradientLabel tvOS Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/JNGradientLabel tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 35 | 36 | 37 | 47 | 48 | 54 | 55 | 61 | 62 | 63 | 64 | 66 | 67 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/JNGradientLabel.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 35 | 36 | 37 | 47 | 48 | 54 | 55 | 61 | 62 | 63 | 64 | 66 | 67 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/JNGradientLabelExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/Run SwiftLint.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /JNGradientLabel.xcodeproj/xcshareddata/xcschemes/XCFramework.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Joe Newton 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "JNGradientLabel", 6 | 7 | platforms: [ 8 | .iOS("9.0"), 9 | .tvOS("9.0") 10 | ], 11 | 12 | products: [ 13 | .library(name: "JNGradientLabel", targets: ["JNGradientLabel"]) 14 | ], 15 | 16 | targets: [ 17 | .target(name: "JNGradientLabel") 18 | ], 19 | 20 | swiftLanguageVersions: [.version("5")] 21 | ) 22 | -------------------------------------------------------------------------------- /Plists/JNGradientLabel-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Gradient Label](Images/JNGradientLabel.png) 2 | 3 | # JNGradientLabel 4 | 5 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/d30d31c29f17449481b97a04610ff5b9)](https://app.codacy.com/app/SomeRandomiOSDev/JNGradientLabel?utm_source=github.com&utm_medium=referral&utm_content=SomeRandomiOSDev/JNGradientLabel&utm_campaign=Badge_Grade_Dashboard) 6 | [![License MIT](https://img.shields.io/cocoapods/l/JNGradientLabel.svg)](https://cocoapods.org/pods/JNGradientLabel) 7 | [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/JNGradientLabel.svg)](https://cocoapods.org/pods/JNGradientLabel) 8 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 9 | [![Platform](https://img.shields.io/cocoapods/p/JNGradientLabel.svg)](https://cocoapods.org/pods/JNGradientLabel) 10 | [![Code Coverage](https://codecov.io/gh/SomeRandomiOSDev/JNGradientLabel/branch/master/graph/badge.svg)](https://codecov.io/gh/SomeRandomiOSDev/JNGradientLabel) 11 | 12 | ![Swift Package](https://github.com/SomeRandomiOSDev/JNGradientLabel/workflows/Swift%20Package/badge.svg) 13 | ![Xcode Project](https://github.com/SomeRandomiOSDev/JNGradientLabel/workflows/Xcode%20Project/badge.svg) 14 | ![Cocoapods](https://github.com/SomeRandomiOSDev/JNGradientLabel/workflows/Cocoapods/badge.svg) 15 | ![Carthage](https://github.com/SomeRandomiOSDev/JNGradientLabel/workflows/Carthage/badge.svg) 16 | 17 | An [UILabel](https://developer.apple.com/documentation/uikit/uilabel) subclass that uses gradients as its text or background color. 18 | 19 | ## Installation 20 | 21 | **JNGradientLabel** is available through [CocoaPods](https://cocoapods.org), [Carthage](https://github.com/Carthage/Carthage) and the [Swift Package Manager](https://swift.org/package-manager/). 22 | 23 | To install via CocoaPods, simply add the following line to your Podfile: 24 | 25 | ```ruby 26 | pod 'JNGradientLabel' 27 | ``` 28 | 29 | To install via Carthage, simply add the following line to your Cartfile: 30 | 31 | ```ruby 32 | github "SomeRandomiOSDev/JNGradientLabel" 33 | ``` 34 | 35 | To install via the Swift Package Manager add the following line to your `Package.swift` file's `dependencies`: 36 | 37 | ```swift 38 | .package(url: "https://github.com/SomeRandomiOSDev/JNGradientLabel.git", from: "1.0.0") 39 | ``` 40 | 41 | ## Usage 42 | 43 | First import JNGradientLabel at the top of your source file: 44 | 45 | Swift: 46 | 47 | ```swift 48 | import JNGradientLabel 49 | ``` 50 | 51 | Objective-C: 52 | 53 | ```objc 54 | @import JNGradientLabel; 55 | ``` 56 | 57 | After initializing the label (from a Storyboard/XIB or manually) call one of following methods: 58 | 59 | Swift: 60 | 61 | ```swift 62 | // To produce an `Axial` (Linear) gradient 63 | label.setAxialGradientParameters(startPoint: startPoint, 64 | endPoint: endPoint, 65 | colors: gradientColors, 66 | locations: gradientlocations, 67 | options: ... /* Optional CGGradientDrawingOptions parameter */) 68 | ``` 69 | 70 | OR 71 | 72 | ```swift 73 | // To produce a `Radial` gradient 74 | label.setRadialGradientParameters(startCenter: startCenter, 75 | startRadius: startRadius, 76 | endCenter: endCenter, 77 | endRadius: endRadius, 78 | colors: gradientColors, 79 | locations: gradientlocations, 80 | radiiScalingRule: ... /* Optional RadialGradientRadiiScalingRule parameter */, 81 | options: ... /* Optional CGGradientDrawingOptions parameter */) 82 | ``` 83 | 84 | Objective-C: 85 | 86 | ```objc 87 | // To produce an `Axial` (Linear) gradient 88 | [label setAxialGradientParametersWithStartPoint:startPoint 89 | endPoint:endPoint 90 | colors:gradientColors 91 | locations:gradientLocations 92 | options:gradientDrawingOptions]; 93 | ``` 94 | 95 | OR 96 | 97 | ```objc 98 | // To produce a `Radial` gradient 99 | [label setRadialGradientParametersWithStartCenter:startCenter 100 | startRadius:startRadius 101 | endCenter:endCenter 102 | endRadius:endRadius 103 | colors:gradientColors 104 | locations:gradientLocations 105 | radiiScalingRule:radiiScalingRule 106 | options:gradientDrawingOptions]; 107 | ``` 108 | 109 | And thats it! 110 | 111 | By default, the label draws the gradient as the color of the text. The label also supports drawing the gradient as the background of the text. To do this, simply set the `textGradientLocation` property as follows: 112 | 113 | Swift: 114 | 115 | ```swift 116 | label.textGradientLocation = .background 117 | ``` 118 | 119 | Objective-C: 120 | 121 | ```objc 122 | label.textGradientLocation = TextGradientLocationBackground; 123 | ``` 124 | 125 | OR 126 | 127 | ```objc 128 | [label setTextGradientLocation:TextGradientLocationBackground]; 129 | ``` 130 | 131 | Screenshots 132 | -------- 133 | 134 | Foreground Axial Gradient: 135 | ![Foreground Axial Gradient](Images/ForegroundAxial.png) 136 | 137 | Foreground Radial Gradient: 138 | ![Foreground Radial Gradient](Images/ForegroundRadial.png) 139 | 140 | Background Axial Gradient: 141 | ![Background Axial Gradient](Images/BackgroundAxial.png) 142 | 143 | Background Radial Gradient: 144 | ![Background Radial Gradient](Images/BackgroundRadial.png) 145 | 146 | ## Contributing 147 | 148 | If you have need for a specific feature or you encounter a bug, please open an issue. If you extend the functionality of **JNGradientLabel** yourself or you feel like fixing a bug yourself, please submit a pull request. 149 | 150 | ## Author 151 | 152 | Joe Newton, somerandomiosdev@gmail.com 153 | 154 | ## License 155 | 156 | **JNGradientLabel** is available under the MIT license. See the `LICENSE` file for more info. 157 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "gray-gamma-22", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "white" : "0.700" 9 | } 10 | }, 11 | "idiom" : "universal" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-iOS.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "filename" : "App Icon - App Store.imagestack", 5 | "idiom" : "tv", 6 | "role" : "primary-app-icon", 7 | "size" : "1280x768" 8 | }, 9 | { 10 | "filename" : "App Icon.imagestack", 11 | "idiom" : "tv", 12 | "role" : "primary-app-icon", 13 | "size" : "400x240" 14 | }, 15 | { 16 | "filename" : "Top Shelf Image Wide.imageset", 17 | "idiom" : "tv", 18 | "role" : "top-shelf-image-wide", 19 | "size" : "2320x720" 20 | }, 21 | { 22 | "filename" : "Top Shelf Image.imageset", 23 | "idiom" : "tv", 24 | "role" : "top-shelf-image", 25 | "size" : "1920x720" 26 | } 27 | ], 28 | "info" : { 29 | "author" : "xcode", 30 | "version" : 1 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon-tvOS.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Resources/iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Resources/iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /Resources/tvOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Resources/tvOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 33 | 39 | 47 | 53 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Sources/JNGradientLabel/JNGradientLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JNGradientLabel.swift 3 | // JNGradientLabel 4 | // 5 | // Copyright © 2021 SomeRandomiOSDev. All rights reserved. 6 | // 7 | 8 | import CoreGraphics 9 | import UIKit 10 | 11 | // swiftlint:disable discouraged_optional_collection 12 | 13 | // MARK: - TextGradientLocation Definition 14 | 15 | /// An enum that describes how a gradient should be drawn in relation to the text 16 | @objc public enum TextGradientLocation: Int { 17 | 18 | // MARK: Public Cases 19 | 20 | /// The gradient should be drawn as the color of the text. The `textColor` property of the label and any text color specified as attributes on `attributedText` are ignored. 21 | case foreground = 0 22 | 23 | /// The gradient should be drawn as the background color of the text. The `backgroundColor` property of the label is ignored. 24 | case background = 1 25 | 26 | // MARK: Private Constants 27 | 28 | fileprivate static let `default` = TextGradientLocation.foreground 29 | } 30 | 31 | // MARK: - RadialGradientRadiiScalingRule Definition 32 | 33 | /// An enum that describes how the radial gradient radius should be scaled when drawing 34 | @objc public enum RadialGradientRadiiScalingRule: Int { 35 | 36 | // MARK: Public Cases 37 | 38 | /// When scaling, the radial gradient radius should be multiplied by the current width of the label. `scaledRadius = radius * width` 39 | case width = 0 40 | 41 | /// When scaling, the radial gradient radius should be multiplied by the current height of the label. `scaledRadius = radius * height` 42 | case height = 1 43 | 44 | /// When scaling, the radial gradient radius should be multiplied by the smaller of the width and the height of the label. `scaledRadius = radius * min(width, height)` 45 | case minimumBound = 2 46 | 47 | /// When scaling, the radial gradient radius should be multiplied by the larger of the width and the height of the label. `scaledRadius = radius * max(width, height)` 48 | case maximumBound = 3 49 | 50 | // MARK: Public Constants 51 | 52 | /// Same as `.maximumBound` 53 | public static let `default` = RadialGradientRadiiScalingRule.maximumBound 54 | } 55 | 56 | // MARK: - JNGradientLabel Definition 57 | 58 | open class JNGradientLabel: UILabel { 59 | 60 | // MARK: Private Types 61 | 62 | private enum GradientType: Codable { 63 | 64 | // MARK: Public Cases 65 | 66 | case axial(startPoint: CGPoint, endPoint: CGPoint) 67 | case radial(startCenter: CGPoint, startRadius: CGFloat, endCenter: CGPoint, endRadius: CGFloat, radiiScalingRule: RadialGradientRadiiScalingRule) 68 | 69 | // MARK: Private Types 70 | 71 | // swiftlint:disable nesting 72 | private enum CodingKeys: String, CodingKey { 73 | 74 | // Axial/Radial 75 | case type 76 | case startPoint 77 | case endPoint 78 | 79 | // Radial 80 | case startRadius 81 | case endRadius 82 | case radiiScalingRule 83 | } 84 | // swiftlint:enable nesting 85 | 86 | // MARK: Encodable Protcol Requirements 87 | 88 | func encode(to encoder: Encoder) throws { 89 | switch self { 90 | case let .axial(startPoint, endPoint): 91 | var container = encoder.container(keyedBy: CodingKeys.self) 92 | try container.encode(0, forKey: .type) 93 | try container.encode(startPoint, forKey: .startPoint) 94 | try container.encode(endPoint, forKey: .endPoint) 95 | 96 | case let .radial(startCenter, startRadius, endCenter, endRadius, radiiScalingRule): 97 | var container = encoder.container(keyedBy: CodingKeys.self) 98 | try container.encode(1, forKey: .type) 99 | try container.encode(startCenter, forKey: .startPoint) 100 | try container.encode(startRadius, forKey: .startRadius) 101 | try container.encode(endCenter, forKey: .endPoint) 102 | try container.encode(endRadius, forKey: .endRadius) 103 | try container.encode(radiiScalingRule.rawValue, forKey: .radiiScalingRule) 104 | } 105 | } 106 | 107 | // MARK: Decodable Protocol Requirements 108 | 109 | init(from decoder: Decoder) throws { 110 | let values = try decoder.container(keyedBy: CodingKeys.self) 111 | 112 | switch try values.decode(Int.self, forKey: .type) { 113 | case 0: // Axial 114 | self = .axial(startPoint: try values.decode(CGPoint.self, forKey: .startPoint), 115 | endPoint: try values.decode(CGPoint.self, forKey: .endPoint)) 116 | 117 | case 1: // Radial 118 | self = .radial(startCenter: try values.decode(CGPoint.self, forKey: .startPoint), 119 | startRadius: try values.decode(CGFloat.self, forKey: .startRadius), 120 | endCenter: try values.decode(CGPoint.self, forKey: .endPoint), 121 | endRadius: try values.decode(CGFloat.self, forKey: .endRadius), 122 | radiiScalingRule: RadialGradientRadiiScalingRule(rawValue: try values.decode(Int.self, forKey: .radiiScalingRule)) ?? .default) 123 | 124 | default: 125 | fatalError("Invalid gradient type") 126 | } 127 | } 128 | } 129 | 130 | private enum EncodingKeys: String { 131 | 132 | // MARK: Cases 133 | 134 | case gradientType 135 | case gradientColors 136 | case gradientLocations 137 | case gradientOptions 138 | case textGradientLocation 139 | } 140 | 141 | // MARK: Private Properties 142 | 143 | private var gradientType: GradientType? 144 | private var textImage: UIImage? 145 | 146 | // MARK: Public Properties 147 | 148 | /// The colors to be used when drawing the gradient 149 | @objc open var gradientColors: [UIColor]? { 150 | didSet { 151 | if oldValue != gradientColors { 152 | super.setNeedsDisplay() 153 | } 154 | } 155 | } 156 | 157 | /// The locations of the gradient colors specified in 'gradientColors' 158 | @objc open var gradientLocations: [NSNumber]? { 159 | didSet { 160 | if oldValue != gradientLocations { 161 | super.setNeedsDisplay() 162 | } 163 | } 164 | } 165 | 166 | /// The drawing options used when drawing the gradient 167 | @objc open var gradientOptions: CGGradientDrawingOptions = [] { 168 | didSet { 169 | if oldValue != gradientOptions { 170 | super.setNeedsDisplay() 171 | } 172 | } 173 | } 174 | 175 | /// The gradient location 176 | @objc open var textGradientLocation: TextGradientLocation = .default { 177 | didSet { 178 | if oldValue != textGradientLocation { 179 | super.setNeedsDisplay() 180 | } 181 | } 182 | } 183 | 184 | // MARK: Initialization 185 | 186 | public required init?(coder aDecoder: NSCoder) { 187 | super.init(coder: aDecoder) 188 | 189 | if let data = aDecoder.decodeObject(of: NSData.self, forKey: EncodingKeys.gradientType.rawValue) { 190 | let type = try? JSONDecoder().decode(GradientType.self, from: data as Data) 191 | gradientType = type 192 | } 193 | if let colors = aDecoder.decodeObject(of: NSArray.self, forKey: EncodingKeys.gradientColors.rawValue) { 194 | gradientColors = (colors as Array).compactMap { $0 as? UIColor } 195 | } 196 | if let locations = aDecoder.decodeObject(of: NSArray.self, forKey: EncodingKeys.gradientLocations.rawValue) { 197 | gradientLocations = (locations as Array).compactMap { $0 as? NSNumber } 198 | } 199 | 200 | gradientOptions = CGGradientDrawingOptions(rawValue: UInt32(bitPattern: aDecoder.decodeInt32(forKey: EncodingKeys.gradientOptions.rawValue))) 201 | textGradientLocation = TextGradientLocation(rawValue: aDecoder.decodeInteger(forKey: EncodingKeys.textGradientLocation.rawValue)) ?? .default 202 | } 203 | 204 | // MARK: NSCoding Methods 205 | 206 | override open func encode(with aCoder: NSCoder) { 207 | super.encode(with: aCoder) 208 | 209 | if let type = gradientType, 210 | let data = try? JSONEncoder().encode(type) { 211 | aCoder.encode(data, forKey: EncodingKeys.gradientType.rawValue) 212 | } 213 | if let colors = gradientColors { 214 | aCoder.encode(colors as NSArray, forKey: EncodingKeys.gradientColors.rawValue) 215 | } 216 | if let locations = gradientLocations { 217 | aCoder.encode(locations as NSArray, forKey: EncodingKeys.gradientLocations.rawValue) 218 | } 219 | 220 | aCoder.encode(Int32(bitPattern: gradientOptions.rawValue), forKey: EncodingKeys.gradientOptions.rawValue) 221 | aCoder.encode(textGradientLocation.rawValue, forKey: EncodingKeys.textGradientLocation.rawValue) 222 | } 223 | 224 | // MARK: Public Methods 225 | 226 | /// Sets the gradient type to `axial` (also known as linear) and sets the start and end points, and optionally the gradient colors and locations. 227 | /// 228 | /// - parameter startPoint: The start point of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 229 | /// - parameter endPoint: The end point of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 230 | /// - parameter colors: The colors of the gradient 231 | /// - parameter locations: The locations of the gradient colors 232 | /// - parameter options: The gradient drawing options. 233 | @objc open func setAxialGradientParameters(startPoint: CGPoint, endPoint: CGPoint, colors: [UIColor]? = nil, locations: [NSNumber]? = nil, options: CGGradientDrawingOptions = []) { 234 | gradientOptions = options 235 | gradientType = .axial(startPoint: startPoint.clamped(min: 0.0, max: 1.0), 236 | endPoint: endPoint.clamped(min: 0.0, max: 1.0)) 237 | 238 | if let colors = colors { gradientColors = colors } 239 | if let locations = locations { gradientLocations = locations } 240 | 241 | super.setNeedsDisplay() 242 | } 243 | 244 | /// Sets the gradient type to `axial` (also known as linear) and sets the start and end points, and optionally the gradient colors and locations. 245 | /// 246 | /// - parameter startPoint: The start point of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 247 | /// - parameter endPoint: The end point of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 248 | /// - parameter colors: The colors of the gradient 249 | /// - parameter locations: The locations of the gradient colors 250 | /// - parameter options: The gradient drawing options. If unspecified, this defaults to a null option set 251 | @nonobjc open func setAxialGradientParameters(startPoint: CGPoint, endPoint: CGPoint, colors: [UIColor]? = nil, locations: [CGFloat]? = nil, options: CGGradientDrawingOptions = []) { 252 | setAxialGradientParameters(startPoint: startPoint, 253 | endPoint: endPoint, 254 | colors: colors, 255 | locations: locations?.map { NSNumber(value: Double($0)) }, 256 | options: options) 257 | } 258 | 259 | /// Sets the gradient type to `radial` and sets the start and end cneter points, the start and end radii, and optionally the gradient colors and locations. 260 | /// 261 | /// - parameter startCenter: The start center of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 262 | /// - parameter startRadius: The start radius of the gradient. The expected range of this value is [0.0, 1.0] and any value outside of this range will be clamped. 263 | /// - parameter endCenter: The end center of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 264 | /// - parameter endRadius: The end radius of the gradient. The expected range of this value is [0.0, 1.0] and any value outside of this range will be clamped. 265 | /// - parameter radiusScalingRule: The rule to use when scaling up the radii from their [0.0, 1.0] range to the coordinate space of the label. 266 | /// - parameter colors: The colors of the gradient 267 | /// - parameter locations: The locations of the gradient colors 268 | /// - parameter options: The gradient drawing options. 269 | @objc open func setRadialGradientParameters(startCenter: CGPoint, 270 | startRadius: CGFloat, 271 | endCenter: CGPoint, 272 | endRadius: CGFloat, 273 | colors: [UIColor]? = nil, 274 | locations: [NSNumber]? = nil, 275 | radiiScalingRule: RadialGradientRadiiScalingRule = .default, 276 | options: CGGradientDrawingOptions = []) { 277 | gradientOptions = options 278 | gradientType = .radial(startCenter: startCenter.clamped(min: 0.0, max: 1.0), 279 | startRadius: startRadius, 280 | endCenter: endCenter.clamped(min: 0.0, max: 1.0), 281 | endRadius: endRadius, 282 | radiiScalingRule: radiiScalingRule) 283 | 284 | if let colors = colors { gradientColors = colors } 285 | if let locations = locations { gradientLocations = locations } 286 | 287 | super.setNeedsDisplay() 288 | } 289 | 290 | /// Sets the gradient type to `radial` and sets the start and end cneter points, the start and end radii, and optionally the gradient colors and locations. 291 | /// 292 | /// - parameter startCenter: The start center of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 293 | /// - parameter startRadius: The start radius of the gradient. The expected range of this value is [0.0, 1.0] and any value outside of this range will be clamped. 294 | /// - parameter endCenter: The end center of the gradient with (0.0, 0.0) and (1.0, 1.0) representing the top-left and bottom-right corners of the label, respectively. Points whose coordinates lie outside of this range will be clamped 295 | /// - parameter endRadius: The end radius of the gradient. The expected range of this value is [0.0, 1.0] and any value outside of this range will be clamped. 296 | /// - parameter radiusScalingRule: The rule to use when scaling up the radii from their [0.0, 1.0] range to the coordinate space of the label. If unspecified, this defaults to `maximumBound` 297 | /// - parameter colors: The colors of the gradient 298 | /// - parameter locations: The locations of the gradient colors 299 | /// - parameter options: The gradient drawing options. If unspecified, this defaults to a null option set 300 | @nonobjc open func setRadialGradientParameters(startCenter: CGPoint, 301 | startRadius: CGFloat, 302 | endCenter: CGPoint, 303 | endRadius: CGFloat, 304 | colors: [UIColor]? = nil, 305 | locations: [CGFloat]? = nil, 306 | radiiScalingRule: RadialGradientRadiiScalingRule = .default, 307 | options: CGGradientDrawingOptions = []) { 308 | setRadialGradientParameters(startCenter: startCenter, 309 | startRadius: startRadius, 310 | endCenter: endCenter, 311 | endRadius: endRadius, 312 | colors: colors, 313 | locations: locations?.map { NSNumber(value: Double($0)) }, 314 | radiiScalingRule: radiiScalingRule, 315 | options: options) 316 | } 317 | 318 | @objc open func clearGradientParameters() { 319 | gradientType = nil 320 | gradientColors = nil 321 | gradientLocations = nil 322 | gradientOptions = [] 323 | 324 | super.setNeedsDisplay() 325 | } 326 | 327 | // MARK: UIView Overrides 328 | 329 | override open func setNeedsDisplay() { 330 | super.setNeedsDisplay() 331 | self.textImage = nil 332 | } 333 | 334 | override open func setNeedsDisplay(_ rect: CGRect) { 335 | super.setNeedsDisplay(rect) 336 | self.textImage = nil 337 | } 338 | 339 | override open func draw(_ rect: CGRect) { 340 | let size = bounds.size 341 | 342 | if textImage == nil { 343 | let drawText = { 344 | let backgroundColor = self.layer.backgroundColor 345 | 346 | self.layer.backgroundColor = UIColor.clear.cgColor 347 | super.draw(rect) 348 | self.layer.backgroundColor = backgroundColor 349 | } 350 | 351 | if #available(iOS 10.0, tvOS 10.0, *) { 352 | textImage = UIGraphicsImageRenderer(size: size).image { _ in drawText() } 353 | } else { 354 | UIGraphicsBeginImageContext(size) 355 | defer { UIGraphicsEndImageContext() } 356 | 357 | drawText() 358 | textImage = UIGraphicsGetImageFromCurrentImageContext() 359 | } 360 | } 361 | 362 | if let context = UIGraphicsGetCurrentContext(), 363 | let gradientColors = gradientColors, 364 | let gradientType = gradientType { 365 | var gradient: CGGradient? 366 | 367 | if let gradientLocations = gradientLocations { 368 | gradientLocations.map { CGFloat($0.doubleValue) }.withUnsafeBufferPointer { (buffer: UnsafeBufferPointer) in 369 | gradient = CGGradient(colorsSpace: nil, colors: (gradientColors.map { $0.cgColor } as CFArray), locations: buffer.baseAddress) 370 | } 371 | } else { 372 | gradient = CGGradient(colorsSpace: nil, colors: (gradientColors.map { $0.cgColor } as CFArray), locations: nil) 373 | } 374 | 375 | if let gradient = gradient { 376 | switch gradientType { 377 | case let .axial(start, end): 378 | context.drawLinearGradient(gradient, 379 | start: CGPoint(x: start.x * size.width, y: start.y * size.height), 380 | end: CGPoint(x: end.x * size.width, y: end.y * size.height), 381 | options: gradientOptions) 382 | 383 | case let .radial(startCenter, startRadius, endCenter, endRadius, radiiScalingRule): 384 | let radiiScale: CGFloat 385 | switch radiiScalingRule { 386 | case .width: radiiScale = size.width 387 | case .height: radiiScale = size.height 388 | case .minimumBound: radiiScale = min(size.width, size.height) 389 | case .maximumBound: radiiScale = max(size.width, size.height) 390 | } 391 | 392 | context.drawRadialGradient(gradient, 393 | startCenter: CGPoint(x: startCenter.x * size.width, y: startCenter.y * size.height), 394 | startRadius: startRadius * radiiScale, 395 | endCenter: CGPoint(x: endCenter.x * size.width, y: endCenter.y * size.height), 396 | endRadius: endRadius * radiiScale, 397 | options: gradientOptions) 398 | } 399 | } 400 | } 401 | 402 | switch textGradientLocation { 403 | case .foreground: textImage?.draw(at: .zero, blendMode: .destinationIn, alpha: 1.0) 404 | case .background: textImage?.draw(at: .zero) 405 | } 406 | } 407 | } 408 | 409 | // MARK: - CGPoint Extension 410 | 411 | extension CGPoint { 412 | 413 | fileprivate func clamped(minX: CGFloat, maxX: CGFloat, minY: CGFloat, maxY: CGFloat) -> CGPoint { 414 | precondition(minX <= maxX, "'minX' must be less than or equal to 'maxX'") 415 | precondition(minY <= maxY, "'minY' must be less than or equal to 'maxY'") 416 | 417 | var point = self 418 | 419 | if point.x < minX { point.x = minX } 420 | if point.y < minY { point.y = minY } 421 | 422 | if point.x > maxX { point.x = maxX } 423 | if point.y > maxY { point.y = maxY } 424 | 425 | return point 426 | } 427 | 428 | fileprivate func clamped(min: CGPoint, max: CGPoint) -> CGPoint { 429 | return clamped(minX: min.x, maxX: max.x, minY: min.y, maxY: max.y) 430 | } 431 | 432 | fileprivate func clamped(min: CGFloat, max: CGFloat) -> CGPoint { 433 | return clamped(minX: min, maxX: max, minY: min, maxY: max) 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /Sources/JNGradientLabelExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // JNGradientLabelExample 4 | // 5 | // Copyright © 2021 SomeRandomiOSDev. All rights reserved. 6 | // 7 | 8 | import UIKit 9 | 10 | // MARK: - AppDelegate Definition 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | // MARK: Properties 16 | 17 | var window: UIWindow? 18 | 19 | // MARK: UIApplicationDelegate Protocol Requirements 20 | 21 | // swiftlint:disable discouraged_optional_collection 22 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 23 | // Override point for customization after application launch. 24 | return true 25 | } 26 | // swiftlint:enable discouraged_optional_collection 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // 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. 30 | // 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. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // 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. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // 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. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // 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. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Sources/JNGradientLabelExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // JNGradientLabelExample 4 | // 5 | // Copyright © 2021 SomeRandomiOSDev. All rights reserved. 6 | // 7 | 8 | import JNGradientLabel 9 | import UIKit 10 | 11 | // MARK: - ViewController Definition 12 | 13 | class ViewController: UIViewController { 14 | 15 | // MARK: Interface Builder Outlets 16 | 17 | @IBOutlet private weak var foregroundAxialGradientLabel: JNGradientLabel! 18 | @IBOutlet private weak var backgroundAxialGradientLabel: JNGradientLabel! 19 | 20 | @IBOutlet private weak var foregroundRadialGradientLabel: JNGradientLabel! 21 | @IBOutlet private weak var backgroundRadialGradientLabel: JNGradientLabel! 22 | 23 | // MARK: View Lifecycle Methods 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | 28 | let gradientColors: [UIColor] = [.purple, .cyan] 29 | let gradientlocations: [CGFloat] = [1.0, 0.0] 30 | 31 | foregroundAxialGradientLabel.textGradientLocation = .foreground 32 | foregroundAxialGradientLabel.setAxialGradientParameters(startPoint: CGPoint(x: 0.0, y: 0.0), 33 | endPoint: CGPoint(x: 1.0, y: 0.0), 34 | colors: gradientColors, 35 | locations: gradientlocations) 36 | 37 | backgroundAxialGradientLabel.textColor = .white 38 | backgroundAxialGradientLabel.textGradientLocation = .background 39 | backgroundAxialGradientLabel.setAxialGradientParameters(startPoint: CGPoint(x: 0.0, y: 0.0), 40 | endPoint: CGPoint(x: 1.0, y: 0.0), 41 | colors: gradientColors, 42 | locations: gradientlocations) 43 | 44 | foregroundRadialGradientLabel.textGradientLocation = .foreground 45 | foregroundRadialGradientLabel.setRadialGradientParameters(startCenter: CGPoint(x: 0.5, y: 0.5), 46 | startRadius: 0.0, 47 | endCenter: CGPoint(x: 0.5, y: 0.5), 48 | endRadius: 0.5, 49 | colors: gradientColors, 50 | locations: gradientlocations, 51 | radiiScalingRule: .maximumBound) 52 | 53 | backgroundRadialGradientLabel.textColor = .white 54 | backgroundRadialGradientLabel.textGradientLocation = .background 55 | backgroundRadialGradientLabel.setRadialGradientParameters(startCenter: CGPoint(x: 0.5, y: 0.5), 56 | startRadius: 0.0, 57 | endCenter: CGPoint(x: 0.5, y: 0.5), 58 | endRadius: 0.5, 59 | colors: gradientColors, 60 | locations: gradientlocations, 61 | radiiScalingRule: .maximumBound) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | precision: 2 6 | round: down 7 | range: "70...100" 8 | 9 | parsers: 10 | gcov: 11 | branch_detection: 12 | conditional: yes 13 | loop: yes 14 | method: no 15 | macro: no 16 | 17 | comment: 18 | layout: "reach,diff,flags,tree" 19 | behavior: default 20 | require_changes: no 21 | 22 | ignore: 23 | - Tests/**/* 24 | -------------------------------------------------------------------------------- /scripts/carthage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Needed to circumvent an issue with Carthage version < 0.37.0: https://github.com/Carthage/Carthage/issues/3019 4 | # 5 | # carthage.sh 6 | # Usage example: ./carthage.sh build --platform iOS 7 | 8 | VERSION="$(carthage version)" 9 | "$(dirname "$0")/versions.sh" "$VERSION" "0.37.0" 10 | 11 | if [ $? -ge 0 ]; then 12 | # Carthage version is greater than or equal to 0.37.0 meaning we can use the --use-xcframeworks flag 13 | carthage "$@" --use-xcframeworks 14 | else 15 | # Workaround for Xcode 12 issue for Carthage versions prior to 0.37.0 16 | set -euo pipefail 17 | 18 | xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX) 19 | trap 'rm -f "$xcconfig"' INT TERM HUP EXIT 20 | 21 | # For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise 22 | # the build will fail on lipo due to duplicate architectures. 23 | for simulator in iphonesimulator appletvsimulator; do 24 | echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_${simulator}__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig 25 | done 26 | echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(PLATFORM_NAME)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig 27 | 28 | export XCODE_XCCONFIG_FILE="$xcconfig" 29 | cat $XCODE_XCCONFIG_FILE 30 | carthage "$@" 31 | fi 32 | -------------------------------------------------------------------------------- /scripts/resolvepath.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # resolvepath.sh 4 | # Usage example: ./resolvepath.sh "./some/random/path/../../" 5 | 6 | cd "$(dirname "$1")" &>/dev/null && echo "$PWD/${1##*/}" 7 | -------------------------------------------------------------------------------- /scripts/versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # versions.sh 4 | # Usage example: ./versions.sh "1.4.15" "1.7.0" 5 | 6 | # Copied & adapted from: https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash#answer-4025065 7 | function compare_versions() { 8 | if [ $1 = $2 ]; then 9 | return 0 10 | fi 11 | 12 | local IFS=. 13 | local i LHS=($1) RHS=($2) 14 | 15 | for ((i=${#LHS[@]}; i<${#RHS[@]}; i++)); do 16 | LHS[i]=0 17 | done 18 | 19 | for ((i=0; i<${#LHS[@]}; i++)); do 20 | if [ -z ${RHS[i]} ]; then 21 | RHS[i]=0 22 | fi 23 | 24 | if ((10#${LHS[i]} > 10#${RHS[i]})); then 25 | return 1 26 | elif ((10#${LHS[i]} < 10#${RHS[i]})); then 27 | return -1 28 | fi 29 | done 30 | 31 | return 0 32 | } 33 | 34 | exit $(compare_versions $1 $2) 35 | -------------------------------------------------------------------------------- /scripts/workflowtests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # workflowtests.sh 4 | # Usage example: ./workflowtests.sh --no-clean 5 | 6 | # Set Script Variables 7 | 8 | SCRIPT="$("$(dirname "$0")/resolvepath.sh" "$0")" 9 | SCRIPTS_DIR="$(dirname "$SCRIPT")" 10 | ROOT_DIR="$(dirname "$SCRIPTS_DIR")" 11 | CURRENT_DIR="$(pwd -P)" 12 | 13 | EXIT_CODE=0 14 | EXIT_MESSAGE="" 15 | 16 | # Help 17 | 18 | function print_help() { 19 | local HELP="workflowtests.sh [--help | -h] [--project-name ]\n" 20 | HELP+=" [--no-clean | --no-clean-on-fail]\n" 21 | HELP+=" [--is-running-in-temp-env]\n" 22 | HELP+="\n" 23 | HELP+="--help, -h) Print this help message and exit.\n" 24 | HELP+="\n" 25 | HELP+="--project-name) The name of the project to run tests against. If not\n" 26 | HELP+=" provided it will attempt to be resolved by searching\n" 27 | HELP+=" the working directory for an Xcode project and using\n" 28 | HELP+=" its name.\n" 29 | HELP+="\n" 30 | HELP+="--no-clean) When not running in a temporary environment, do not\n" 31 | HELP+=" clean up the temporary project created to run these\n" 32 | HELP+=" tests upon completion.\n" 33 | HELP+="\n" 34 | HELP+="--no-clean-on-fail) Same as --no-clean with the exception that if the\n" 35 | HELP+=" succeed clean up will continue as normal. This is\n" 36 | HELP+=" mutually exclusive with --no-clean with --no-clean\n" 37 | HELP+=" taking precedence.\n" 38 | HELP+="--is-running-in-temp-env) Setting this flag tells this script that the\n" 39 | HELP+=" environment (directory) in which it is running is a\n" 40 | HELP+=" temporary environment and it need not worry about\n" 41 | HELP+=" dirtying up the directory or creating/deleting files\n" 42 | HELP+=" and folders. USE CAUTION WITH THIS OPTION.\n" 43 | HELP+="\n" 44 | HELP+=" When this flag is NOT set, a copy of the containing\n" 45 | HELP+=" working folder is created in a temporary location and\n" 46 | HELP+=" removed (unless --no-clean is set) after the tests\n" 47 | HELP+=" have finished running." 48 | 49 | IFS='%' 50 | echo -e $HELP 51 | unset IFS 52 | 53 | exit 0 54 | } 55 | 56 | # Parse Arguments 57 | 58 | while [[ $# -gt 0 ]]; do 59 | case "$1" in 60 | --project-name) 61 | PROJECT_NAME="$2" 62 | shift # --project-name 63 | shift # 64 | ;; 65 | 66 | --is-running-in-temp-env) 67 | IS_RUNNING_IN_TEMP_ENV=1 68 | shift # --is-running-in-temp-env 69 | ;; 70 | 71 | --no-clean) 72 | NO_CLEAN=1 73 | shift # --no-clean 74 | ;; 75 | 76 | --no-clean-on-fail) 77 | NO_CLEAN_ON_FAIL=1 78 | shift # --no-clean-on-fail 79 | ;; 80 | 81 | --help | -h) 82 | print_help 83 | ;; 84 | 85 | *) 86 | echo "Unknown argument: $1" 87 | print_help 88 | esac 89 | done 90 | 91 | if [ -z ${PROJECT_NAME+x} ]; then 92 | PROJECTS=$(ls "$ROOT_DIR" | grep \.xcodeproj$) 93 | 94 | if [ "${#PROJECTS[@]}" == "0" ]; then 95 | echo "No Xcode projects found in root directory. Try specifying a project name:" 96 | print_help 97 | elif [ "${#PROJECTS[@]}" == "1" ]; then 98 | PROJECT_NAME="${PROJECTS[0]}" 99 | PROJECT_NAME="${PROJECT_NAME%.*}" 100 | else 101 | echo "More than 1 Xcode projects found in root directory. Specify which project to run tests against:" 102 | print_help 103 | fi 104 | elif [ ! -e "$ROOT_DIR/$PROJECT_NAME.xcodeproj" ]; then 105 | echo "Unable to locate Xcode project to run tests against: $ROOT_DIR/$PROJECT_NAME.xcodeproj" 106 | print_help 107 | fi 108 | 109 | if [ -z ${IS_RUNNING_IN_TEMP_ENV+x} ]; then 110 | IS_RUNNING_IN_TEMP_ENV=0 111 | fi 112 | 113 | if [ -z ${NO_CLEAN+x} ]; then 114 | NO_CLEAN=0 115 | fi 116 | 117 | if [ -z ${NO_CLEAN_ON_FAIL+x} ]; then 118 | NO_CLEAN_ON_FAIL=0 119 | fi 120 | 121 | # Function Definitions 122 | 123 | function cleanup() { 124 | if [ "$IS_RUNNING_IN_TEMP_ENV" == "0" ]; then 125 | if [[ "$NO_CLEAN" == "1" ]] || [[ "$NO_CLEAN_ON_FAIL" == "1" && "$EXIT_CODE" != "0" ]]; then 126 | echo "Test Project: $OUTPUT_DIR" 127 | else 128 | cd "$CURRENT_DIR" 129 | rm -rf "$TEMP_DIR" 130 | fi 131 | fi 132 | 133 | # 134 | 135 | local CARTHAGE_CACHE="$HOME/Library/Caches/org.carthage.CarthageKit" 136 | if [ -e "$CARTHAGE_CACHE" ]; then 137 | if [ -e "$CARTHAGE_CACHE/dependencies/$PROJECT_NAME" ]; then 138 | rm -rf "$CARTHAGE_CACHE/dependencies/$PROJECT_NAME" 139 | fi 140 | 141 | for DIR in $(find "$CARTHAGE_CACHE/DerivedData" -mindepth 1 -maxdepth 1 -type d); do 142 | if [ -e "$DIR/$PROJECT_NAME" ]; then 143 | rm -rf "$DIR/$PROJECT_NAME" 144 | fi 145 | done 146 | fi 147 | 148 | # 149 | 150 | if [ ${#EXIT_MESSAGE} -gt 0 ]; then 151 | echo -e "$EXIT_MESSAGE" 152 | fi 153 | 154 | exit $EXIT_CODE 155 | } 156 | 157 | function checkresult() { 158 | if [ "$1" != "0" ]; then 159 | EXIT_MESSAGE="\033[31m$2\033[0m" 160 | EXIT_CODE=$1 161 | 162 | cleanup 163 | fi 164 | } 165 | 166 | function printstep() { 167 | echo -e "\033[32m$1\033[0m" 168 | } 169 | 170 | function setuptemp() { 171 | local TEMP_DIR="$(mktemp -d)" 172 | local TEMP_NAME="$(basename "$(mktemp -u "$TEMP_DIR/${PROJECT_NAME}Tests_XXXXXX")")" 173 | local OUTPUT_DIR="$TEMP_DIR/$TEMP_NAME" 174 | 175 | cp -R "$ROOT_DIR" "$OUTPUT_DIR" 176 | if [ "$?" != "0" ]; then exit $?; fi 177 | 178 | if [ -e "$OUTPUT_DIR/.build" ]; then 179 | rm -rf "$OUTPUT_DIR/.build" 180 | fi 181 | if [ -e "$OUTPUT_DIR/.swiftpm" ]; then 182 | rm -rf "$OUTPUT_DIR/.swiftpm" 183 | fi 184 | 185 | echo "$OUTPUT_DIR" 186 | } 187 | 188 | # Setup 189 | 190 | if [ "$IS_RUNNING_IN_TEMP_ENV" == "1" ]; then 191 | OUTPUT_DIR="$ROOT_DIR" 192 | else 193 | OUTPUT_DIR="$(setuptemp)" 194 | echo -e "Testing from Temporary Directory: \033[33m$OUTPUT_DIR\033[0m" 195 | fi 196 | 197 | # Check For Dependencies 198 | 199 | cd "$OUTPUT_DIR" 200 | printstep "Checking for Test Dependencies..." 201 | 202 | ### Carthage 203 | 204 | if which carthage >/dev/null; then 205 | CARTHAGE_VERSION="$(carthage version)" 206 | echo "Carthage: $CARTHAGE_VERSION" 207 | 208 | "$SCRIPTS_DIR/versions.sh" "$CARTHAGE_VERSION" "0.37.0" 209 | 210 | if [ $? -lt 0 ]; then 211 | echo -e "\033[33mCarthage version of at least 0.37.0 is recommended for running these unit tests\033[0m" 212 | fi 213 | else 214 | checkresult -1 "Carthage is not installed and is required for running unit tests: \033[4;34mhttps://github.com/Carthage/Carthage#installing-carthage" 215 | fi 216 | 217 | ### CocoaPods 218 | 219 | if which pod >/dev/null; then 220 | PODS_VERSION="$(pod --version)" 221 | "$SCRIPTS_DIR/versions.sh" "$PODS_VERSION" "1.7.3" 222 | 223 | if [ $? -ge 0 ]; then 224 | echo "CocoaPods: $(pod --version)" 225 | else 226 | checkresult -1 "These unit tests require version 1.7.3 or later of CocoaPods: \033[4;34mhttps://guides.cocoapods.org/using/getting-started.html#updating-cocoapods" 227 | fi 228 | else 229 | checkresult -1 "CocoaPods is not installed and is required for running unit tests: \033[4;34mhttps://guides.cocoapods.org/using/getting-started.html#installation" 230 | fi 231 | 232 | # Run Tests 233 | 234 | printstep "Running Tests..." 235 | 236 | ### Carthage Workflow 237 | 238 | printstep "Testing 'carthage.yml' Workflow..." 239 | 240 | git add . 241 | git commit -m "Commit" --no-gpg-sign 242 | git tag | xargs git tag -d 243 | git tag --no-sign 1.0 244 | checkresult $? "'Create Cartfile' step of 'carthage.yml' workflow failed." 245 | 246 | echo "git \"file://$OUTPUT_DIR\"" > ./Cartfile 247 | 248 | ./scripts/carthage.sh update 249 | checkresult $? "'Build' step of 'carthage.yml' workflow failed." 250 | 251 | printstep "'carthage.yml' Workflow Tests Passed\n" 252 | 253 | ### CocoaPods Workflow 254 | 255 | printstep "Testing 'cocoapods.yml' Workflow..." 256 | 257 | pod lib lint 258 | checkresult $? "'Lint (Dynamic Library)' step of 'cocoapods.yml' workflow failed." 259 | 260 | pod lib lint --use-libraries 261 | checkresult $? "'Lint (Static Library)' step of 'cocoapods.yml' workflow failed." 262 | 263 | printstep "'cocoapods.yml' Workflow Tests Passed\n" 264 | 265 | ### XCFramework Workflow 266 | 267 | printstep "Testing 'xcframework.yml' Workflow..." 268 | 269 | ./scripts/xcframework.sh -output "./$PROJECT_NAME.xcframework" 270 | checkresult $? "'Build' step of 'xcframework.yml' workflow failed." 271 | 272 | printstep "'xcframework.yml' Workflow Tests Passed\n" 273 | 274 | ### Upload Assets Workflow 275 | 276 | printstep "Testing 'upload-assets.yml' Workflow..." 277 | 278 | zip -rX "$PROJECT_NAME.xcframework.zip" "$PROJECT_NAME.xcframework" 279 | checkresult $? "'Create Zip' step of 'upload-assets.yml' workflow failed." 280 | 281 | tar -zcvf "$PROJECT_NAME.xcframework.tar.gz" "$PROJECT_NAME.xcframework" 282 | checkresult $? "'Create Tar' step of 'upload-assets.yml' workflow failed." 283 | 284 | printstep "'upload-assets.yml' Workflow Tests Passed\n" 285 | 286 | ### Xcodebuild Workflow 287 | 288 | printstep "Testing 'xcodebuild.yml' Workflow..." 289 | 290 | xcodebuild -project "$PROJECT_NAME.xcodeproj" -scheme "$PROJECT_NAME" -destination "generic/platform=iOS" -configuration Debug 291 | checkresult $? "'Build iOS' step of 'xcodebuild.yml' workflow failed." 292 | 293 | xcodebuild -project "$PROJECT_NAME.xcodeproj" -scheme "$PROJECT_NAME" -destination "generic/platform=iOS Simulator" -configuration Debug 294 | checkresult $? "'Build iOS Simulator' step of 'xcodebuild.yml' workflow failed." 295 | 296 | ### 297 | 298 | xcodebuild -project "$PROJECT_NAME.xcodeproj" -scheme "$PROJECT_NAME" -destination "generic/platform=macOS,variant=Mac Catalyst" -configuration Debug 299 | checkresult $? "'Build MacCatalyst' step of 'xcodebuild.yml' workflow failed." 300 | 301 | ### 302 | 303 | xcodebuild -project "$PROJECT_NAME.xcodeproj" -scheme "$PROJECT_NAME tvOS" -destination "generic/platform=tvOS" -configuration Debug 304 | checkresult $? "'Build tvOS' step of 'xcodebuild.yml' workflow failed." 305 | 306 | xcodebuild -project "$PROJECT_NAME.xcodeproj" -scheme "$PROJECT_NAME tvOS" -destination "generic/platform=tvOS Simulator" -configuration Debug 307 | checkresult $? "'Build tvOS Simulator' step of 'xcodebuild.yml' workflow failed." 308 | 309 | printstep "'xcodebuild.yml' Workflow Tests Passed\n" 310 | 311 | ### Success 312 | 313 | cleanup 314 | -------------------------------------------------------------------------------- /scripts/xcframework.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # xcframework.sh 4 | # Usage example: ./xcframework.sh -output /JNGradientLabel.xcframework 5 | 6 | # Parse Arguments 7 | 8 | while [[ $# -gt 0 ]]; do 9 | case "$1" in 10 | -output) 11 | OUTPUT_DIR="$2" 12 | shift # -output 13 | shift # 14 | ;; 15 | 16 | -configuration) 17 | CONFIGURATION="$2" 18 | shift # -configuration 19 | shift # 20 | ;; 21 | 22 | *) 23 | echo "Unknown argument: $1" 24 | echo "./xcframework.sh [-output ]"] 25 | exit 1 26 | esac 27 | done 28 | 29 | if [ -z ${OUTPUT_DIR+x} ]; then 30 | OUTPUT_DIR="$(dirname "$0")/build/JNGradientLabel.xcframework" 31 | fi 32 | 33 | if [ -z ${CONFIGURATION+x} ]; then 34 | CONFIGURATION="Release" 35 | fi 36 | 37 | # Create Temporary Directory 38 | 39 | TMPDIR=`mktemp -d /tmp/.jngradientlabel.xcframework.build.XXXXXX` 40 | cd "$(dirname "$(dirname "$0")")" 41 | 42 | check_result() { 43 | if [ $1 -ne 0 ]; then 44 | rm -rf "${TMPDIR}" 45 | exit $1 46 | fi 47 | } 48 | 49 | # Build iOS 50 | xcodebuild -project "JNGradientLabel.xcodeproj" -scheme "JNGradientLabel" -destination "generic/platform=iOS" -archivePath "${TMPDIR}/iphoneos.xcarchive" -configuration ${CONFIGURATION} SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ONLY_ACTIVE_ARCH=NO ARCHS="armv7 armv7s arm64 arm64e" archive 51 | check_result $? 52 | 53 | # Build iOS Simulator 54 | xcodebuild -project "JNGradientLabel.xcodeproj" -scheme "JNGradientLabel" -destination "generic/platform=iOS Simulator" -archivePath "${TMPDIR}/iphonesimulator.xcarchive" -configuration ${CONFIGURATION} SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ONLY_ACTIVE_ARCH=NO ARCHS="i386 x86_64 arm64" archive 55 | check_result $? 56 | 57 | # Build Mac Catalyst 58 | xcodebuild -project "JNGradientLabel.xcodeproj" -scheme "JNGradientLabel" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath "${TMPDIR}/maccatalyst.xcarchive" -configuration ${CONFIGURATION} SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ONLY_ACTIVE_ARCH=NO ARCHS="x86_64 arm64 arm64e" archive 59 | check_result $? 60 | 61 | # Build tvOS 62 | xcodebuild -project "JNGradientLabel.xcodeproj" -scheme "JNGradientLabel tvOS" -destination "generic/platform=tvOS" -archivePath "${TMPDIR}/appletvos.xcarchive" -configuration ${CONFIGURATION} SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ONLY_ACTIVE_ARCH=NO ARCHS="arm64 arm64e" archive 63 | check_result $? 64 | 65 | # Build tvOS Simulator 66 | xcodebuild -project "JNGradientLabel.xcodeproj" -scheme "JNGradientLabel tvOS" -destination "generic/platform=tvOS Simulator" -archivePath "${TMPDIR}/appletvsimulator.xcarchive" -configuration ${CONFIGURATION} SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ONLY_ACTIVE_ARCH=NO ARCHS="x86_64 arm64" archive 67 | check_result $? 68 | 69 | # Make XCFramework 70 | 71 | if [[ -d "${OUTPUT_DIR}" ]]; then 72 | rm -rf "${OUTPUT_DIR}" 73 | fi 74 | 75 | ARGUMENTS=(-create-xcframework -output "${OUTPUT_DIR}") 76 | 77 | for ARCHIVE in ${TMPDIR}/*.xcarchive; do 78 | ARGUMENTS=(${ARGUMENTS[@]} -framework "${ARCHIVE}/Products/Library/Frameworks/JNGradientLabel.framework") 79 | 80 | if [[ -d "${ARCHIVE}/dSYMs/JNGradientLabel.framework.dSYM" ]]; then 81 | ARGUMENTS=(${ARGUMENTS[@]} -debug-symbols "${ARCHIVE}/dSYMs/JNGradientLabel.framework.dSYM") 82 | fi 83 | 84 | if [[ -d "${ARCHIVE}/BCSymbolMaps" ]]; then 85 | for SYMBOLMAP in ${ARCHIVE}/BCSymbolMaps/*.bcsymbolmap; do 86 | ARGUMENTS=(${ARGUMENTS[@]} -debug-symbols "${SYMBOLMAP}") 87 | done 88 | fi 89 | done 90 | 91 | xcodebuild "${ARGUMENTS[@]}" 92 | check_result $? 93 | 94 | # Cleanup 95 | 96 | rm -rf "${TMPDIR}" 97 | exit 0 98 | --------------------------------------------------------------------------------