├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CHANGELOG.md ├── CheckmarkCollectionViewCell.podspec ├── Example ├── CheckmarkCollectionViewCellDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── CheckmarkCollectionViewCellDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── CheckmarkCollectionViewCellDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── Info.plist ├── CheckmarkCollectionViewCellDemoUITests │ ├── CheckmarkCollectionViewCellDemoUITests.swift │ └── Info.plist ├── Podfile └── Podfile.lock ├── LICENSE.txt ├── Package.swift ├── README.md ├── Screenshots └── CheckmarkCollectionViewCell.png └── Sources ├── CheckmarkCollectionViewCell.swift ├── PrivacyInfo.xcprivacy ├── checked.png └── unchecked.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [yonat] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: yonat 7 | 8 | --- 9 | 10 | **Description of the problem:** 11 | [description] 12 | 13 | **Minimal project that reproduces the problem (so I'll be able to figure out how to fix it):** 14 | [link to a Minimal Reproducible Example as described at https://ootips.org/yonat/repex ] 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: yonat 7 | 8 | --- 9 | 10 | **Description:** 11 | [description] 12 | 13 | **Problems I encountered when trying to implement this myself:** 14 | [if none, please submit a pull request.] 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Example/Pods 2 | 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.1.0] - 2024-11-01 8 | 9 | ### Fixed 10 | - fix privacy manifest PrivacyInfo.xcprivacy. 11 | 12 | ## [1.0.6] - 2023-08-19 13 | 14 | ### Added 15 | - add privacy manifest PrivacyInfo.xcprivacy. 16 | 17 | ## [1.0.5] - 2019-08-22 18 | 19 | ### Added 20 | - support Swift Package Manager. 21 | 22 | ### Fixed 23 | - fix Interface Builder render error. 24 | 25 | ## [1.0.4] - 2019-07-13 26 | 27 | ### Changed 28 | - MiniLayout moved to SweeterSwift. 29 | 30 | ## [1.0.3] - 2019-06-21 31 | 32 | ### Changed 33 | - Swift 5, CocoaPods 1.7. 34 | 35 | ## [1.0.2] - 2019-06-07 36 | 37 | ### Added 38 | - UIAppearance support. 39 | 40 | ## [1.0.1] - 2018-10-14 41 | 42 | ### Fixed 43 | - correctly change checkmark location after its creation. 44 | 45 | ## [1.0.0] - 2018-10-08 46 | 47 | ### Added 48 | - initial release. 49 | -------------------------------------------------------------------------------- /CheckmarkCollectionViewCell.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "CheckmarkCollectionViewCell" 4 | s.version = "1.1.0" 5 | s.summary = "UICollectionViewCell with checkbox when it isSelected and empty circle when not - like Photos.app Select mode." 6 | 7 | s.homepage = "https://github.com/yonat/CheckmarkCollectionViewCell" 8 | s.screenshots = "https://raw.githubusercontent.com/yonat/CheckmarkCollectionViewCell/master/Screenshots/CheckmarkCollectionViewCell.png" 9 | 10 | s.license = { :type => "MIT", :file => "LICENSE.txt" } 11 | 12 | s.author = { "Yonat Sharon" => "yonat@ootips.org" } 13 | s.social_media_url = "https://twitter.com/yonatsharon" 14 | 15 | s.swift_version = '4.2' 16 | s.swift_versions = ['4.2', '5.0'] 17 | s.platform = :ios, "9.3" 18 | s.requires_arc = true 19 | 20 | s.source = { :git => "https://github.com/yonat/CheckmarkCollectionViewCell.git", :tag => s.version } 21 | s.source_files = "Sources/*.swift" 22 | s.resource_bundles = {s.name => ['Sources/PrivacyInfo.xcprivacy']} 23 | s.subspec 'Resources' do |resources| 24 | resources.resource_bundle = {s.name => 'Sources/*.png'} 25 | end 26 | 27 | s.dependency 'SweeterSwift' 28 | 29 | s.pod_target_xcconfig = { 'LD_RUNPATH_SEARCH_PATHS' => '$(FRAMEWORK_SEARCH_PATHS)' } # fix Interface Builder render error 30 | 31 | end 32 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 728F899FE6307C7D92D226CA /* Pods_CheckmarkCollectionViewCellDemoUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19057CA1C9B98930CABAE098 /* Pods_CheckmarkCollectionViewCellDemoUITests.framework */; }; 11 | 73E6B4756B8465DBF0B07BCC /* Pods_CheckmarkCollectionViewCellDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA2F9DBB5E26B7985CFC6CC /* Pods_CheckmarkCollectionViewCellDemo.framework */; }; 12 | DC4EAF65216B6AEB00E51171 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4EAF64216B6AEB00E51171 /* AppDelegate.swift */; }; 13 | DC4EAF6A216B6AEB00E51171 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC4EAF68216B6AEB00E51171 /* Main.storyboard */; }; 14 | DC4EAF6C216B6AF000E51171 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC4EAF6B216B6AF000E51171 /* Assets.xcassets */; }; 15 | DC4EAF6F216B6AF000E51171 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC4EAF6D216B6AF000E51171 /* LaunchScreen.storyboard */; }; 16 | DC52B517220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC52B516220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | DC52B519220914C100A01098 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = DC4EAF59216B6AEB00E51171 /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = DC4EAF60216B6AEB00E51171; 25 | remoteInfo = CheckmarkCollectionViewCellDemo; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 19057CA1C9B98930CABAE098 /* Pods_CheckmarkCollectionViewCellDemoUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CheckmarkCollectionViewCellDemoUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 58BCED1A5B7E318D5D941DEE /* Pods-CheckmarkCollectionViewCellDemoUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CheckmarkCollectionViewCellDemoUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CheckmarkCollectionViewCellDemoUITests/Pods-CheckmarkCollectionViewCellDemoUITests.debug.xcconfig"; sourceTree = ""; }; 32 | 602EC5F537EB0FFAA88F1F70 /* Pods-CheckmarkCollectionViewCellDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CheckmarkCollectionViewCellDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CheckmarkCollectionViewCellDemo/Pods-CheckmarkCollectionViewCellDemo.debug.xcconfig"; sourceTree = ""; }; 33 | B066D7D9AD80D7F199C2A9DE /* Pods-CheckmarkCollectionViewCellDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CheckmarkCollectionViewCellDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-CheckmarkCollectionViewCellDemo/Pods-CheckmarkCollectionViewCellDemo.release.xcconfig"; sourceTree = ""; }; 34 | DC4EAF61216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CheckmarkCollectionViewCellDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | DC4EAF64216B6AEB00E51171 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 36 | DC4EAF69216B6AEB00E51171 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 37 | DC4EAF6B216B6AF000E51171 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | DC4EAF6E216B6AF000E51171 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 39 | DC4EAF70216B6AF000E51171 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | DC4EAF76216B6B6D00E51171 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 41 | DC4EAF77216B6B6D00E51171 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = ""; }; 42 | DC52B514220914BF00A01098 /* CheckmarkCollectionViewCellDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CheckmarkCollectionViewCellDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | DC52B516220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckmarkCollectionViewCellDemoUITests.swift; sourceTree = ""; }; 44 | DC52B518220914C100A01098 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | EAA2F9DBB5E26B7985CFC6CC /* Pods_CheckmarkCollectionViewCellDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CheckmarkCollectionViewCellDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | F55C945A5A2D738411057BB7 /* Pods-CheckmarkCollectionViewCellDemoUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CheckmarkCollectionViewCellDemoUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CheckmarkCollectionViewCellDemoUITests/Pods-CheckmarkCollectionViewCellDemoUITests.release.xcconfig"; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | DC4EAF5E216B6AEB00E51171 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 73E6B4756B8465DBF0B07BCC /* Pods_CheckmarkCollectionViewCellDemo.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | DC52B511220914BF00A01098 /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | 728F899FE6307C7D92D226CA /* Pods_CheckmarkCollectionViewCellDemoUITests.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 1A935C1E5A2B1C9F0DE5FFE1 /* Frameworks */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | EAA2F9DBB5E26B7985CFC6CC /* Pods_CheckmarkCollectionViewCellDemo.framework */, 73 | 19057CA1C9B98930CABAE098 /* Pods_CheckmarkCollectionViewCellDemoUITests.framework */, 74 | ); 75 | name = Frameworks; 76 | sourceTree = ""; 77 | }; 78 | 2D97D714034268BCA014E735 /* Pods */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 602EC5F537EB0FFAA88F1F70 /* Pods-CheckmarkCollectionViewCellDemo.debug.xcconfig */, 82 | B066D7D9AD80D7F199C2A9DE /* Pods-CheckmarkCollectionViewCellDemo.release.xcconfig */, 83 | 58BCED1A5B7E318D5D941DEE /* Pods-CheckmarkCollectionViewCellDemoUITests.debug.xcconfig */, 84 | F55C945A5A2D738411057BB7 /* Pods-CheckmarkCollectionViewCellDemoUITests.release.xcconfig */, 85 | ); 86 | name = Pods; 87 | sourceTree = ""; 88 | }; 89 | DC4EAF58216B6AEB00E51171 = { 90 | isa = PBXGroup; 91 | children = ( 92 | DC4EAF76216B6B6D00E51171 /* README.md */, 93 | DC4EAF77216B6B6D00E51171 /* CHANGELOG.md */, 94 | DC4EAF63216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo */, 95 | DC52B515220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests */, 96 | DC4EAF62216B6AEB00E51171 /* Products */, 97 | 2D97D714034268BCA014E735 /* Pods */, 98 | 1A935C1E5A2B1C9F0DE5FFE1 /* Frameworks */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | DC4EAF62216B6AEB00E51171 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | DC4EAF61216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo.app */, 106 | DC52B514220914BF00A01098 /* CheckmarkCollectionViewCellDemoUITests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | DC4EAF63216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | DC4EAF64216B6AEB00E51171 /* AppDelegate.swift */, 115 | DC4EAF68216B6AEB00E51171 /* Main.storyboard */, 116 | DC4EAF6B216B6AF000E51171 /* Assets.xcassets */, 117 | DC4EAF6D216B6AF000E51171 /* LaunchScreen.storyboard */, 118 | DC4EAF70216B6AF000E51171 /* Info.plist */, 119 | ); 120 | path = CheckmarkCollectionViewCellDemo; 121 | sourceTree = ""; 122 | }; 123 | DC52B515220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | DC52B516220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests.swift */, 127 | DC52B518220914C100A01098 /* Info.plist */, 128 | ); 129 | path = CheckmarkCollectionViewCellDemoUITests; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | DC4EAF60216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = DC4EAF73216B6AF000E51171 /* Build configuration list for PBXNativeTarget "CheckmarkCollectionViewCellDemo" */; 138 | buildPhases = ( 139 | B33370CB4ACBA4BCA0B20225 /* [CP] Check Pods Manifest.lock */, 140 | 044C6C4C6215A1D4C2E477C2 /* [CP-User] SwiftFormat */, 141 | 5D8DD2BE19F0D31DE91C5AE8 /* [CP-User] SwiftLintAutocorrect */, 142 | DC4EAF5D216B6AEB00E51171 /* Sources */, 143 | DC4EAF5E216B6AEB00E51171 /* Frameworks */, 144 | DC4EAF5F216B6AEB00E51171 /* Resources */, 145 | 38EC46886BAD9906B2FB521B /* [CP] Embed Pods Frameworks */, 146 | 06075094733240BEB4B1F8EE /* [CP-User] SwiftLint */, 147 | ); 148 | buildRules = ( 149 | ); 150 | dependencies = ( 151 | ); 152 | name = CheckmarkCollectionViewCellDemo; 153 | productName = CheckmarkCollectionViewCellDemo; 154 | productReference = DC4EAF61216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo.app */; 155 | productType = "com.apple.product-type.application"; 156 | }; 157 | DC52B513220914BF00A01098 /* CheckmarkCollectionViewCellDemoUITests */ = { 158 | isa = PBXNativeTarget; 159 | buildConfigurationList = DC52B51D220914C100A01098 /* Build configuration list for PBXNativeTarget "CheckmarkCollectionViewCellDemoUITests" */; 160 | buildPhases = ( 161 | 9DAA1DF7C3D5C4D5F50D9442 /* [CP] Check Pods Manifest.lock */, 162 | DC52B510220914BF00A01098 /* Sources */, 163 | DC52B511220914BF00A01098 /* Frameworks */, 164 | DC52B512220914BF00A01098 /* Resources */, 165 | 5B0A788D94DAB73B93AB7E2F /* [CP] Embed Pods Frameworks */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | DC52B51A220914C100A01098 /* PBXTargetDependency */, 171 | ); 172 | name = CheckmarkCollectionViewCellDemoUITests; 173 | productName = CheckmarkCollectionViewCellDemoUITests; 174 | productReference = DC52B514220914BF00A01098 /* CheckmarkCollectionViewCellDemoUITests.xctest */; 175 | productType = "com.apple.product-type.bundle.ui-testing"; 176 | }; 177 | /* End PBXNativeTarget section */ 178 | 179 | /* Begin PBXProject section */ 180 | DC4EAF59216B6AEB00E51171 /* Project object */ = { 181 | isa = PBXProject; 182 | attributes = { 183 | DefaultBuildSystemTypeForWorkspace = Original; 184 | LastSwiftUpdateCheck = 1010; 185 | LastUpgradeCheck = 1000; 186 | ORGANIZATIONNAME = "Yonat Sharon"; 187 | TargetAttributes = { 188 | DC4EAF60216B6AEB00E51171 = { 189 | CreatedOnToolsVersion = 10.0; 190 | LastSwiftMigration = 1020; 191 | }; 192 | DC52B513220914BF00A01098 = { 193 | CreatedOnToolsVersion = 10.1; 194 | LastSwiftMigration = 1020; 195 | TestTargetID = DC4EAF60216B6AEB00E51171; 196 | }; 197 | }; 198 | }; 199 | buildConfigurationList = DC4EAF5C216B6AEB00E51171 /* Build configuration list for PBXProject "CheckmarkCollectionViewCellDemo" */; 200 | compatibilityVersion = "Xcode 9.3"; 201 | developmentRegion = en; 202 | hasScannedForEncodings = 0; 203 | knownRegions = ( 204 | en, 205 | Base, 206 | ); 207 | mainGroup = DC4EAF58216B6AEB00E51171; 208 | productRefGroup = DC4EAF62216B6AEB00E51171 /* Products */; 209 | projectDirPath = ""; 210 | projectRoot = ""; 211 | targets = ( 212 | DC4EAF60216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo */, 213 | DC52B513220914BF00A01098 /* CheckmarkCollectionViewCellDemoUITests */, 214 | ); 215 | }; 216 | /* End PBXProject section */ 217 | 218 | /* Begin PBXResourcesBuildPhase section */ 219 | DC4EAF5F216B6AEB00E51171 /* Resources */ = { 220 | isa = PBXResourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | DC4EAF6F216B6AF000E51171 /* LaunchScreen.storyboard in Resources */, 224 | DC4EAF6C216B6AF000E51171 /* Assets.xcassets in Resources */, 225 | DC4EAF6A216B6AEB00E51171 /* Main.storyboard in Resources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | DC52B512220914BF00A01098 /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | /* End PBXResourcesBuildPhase section */ 237 | 238 | /* Begin PBXShellScriptBuildPhase section */ 239 | 044C6C4C6215A1D4C2E477C2 /* [CP-User] SwiftFormat */ = { 240 | isa = PBXShellScriptBuildPhase; 241 | alwaysOutOfDate = 1; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | ); 245 | name = "[CP-User] SwiftFormat"; 246 | runOnlyForDeploymentPostprocessing = 0; 247 | shellPath = /bin/sh; 248 | shellScript = "if [[ \"Debug\" == \"${CONFIGURATION}\" && ! $ENABLE_PREVIEWS == \"YES\" ]]; then \"${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat\" --swiftversion ${SWIFT_VERSION} --config \"${PODS_ROOT}/SwiftQuality/.swiftformat\" \"${SRCROOT}/..\" ; fi"; 249 | showEnvVarsInLog = 0; 250 | }; 251 | 06075094733240BEB4B1F8EE /* [CP-User] SwiftLint */ = { 252 | isa = PBXShellScriptBuildPhase; 253 | alwaysOutOfDate = 1; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | name = "[CP-User] SwiftLint"; 258 | runOnlyForDeploymentPostprocessing = 0; 259 | shellPath = /bin/sh; 260 | shellScript = "if [ \"Debug\" == \"${CONFIGURATION}\" && ! $ENABLE_PREVIEWS == \"YES\" ]; then \"${PODS_ROOT}/SwiftLint/swiftlint\" --config \"${PODS_ROOT}/SwiftQuality/.swiftlint.yml\" \"${SRCROOT}/..\" ; fi"; 261 | showEnvVarsInLog = 0; 262 | }; 263 | 38EC46886BAD9906B2FB521B /* [CP] Embed Pods Frameworks */ = { 264 | isa = PBXShellScriptBuildPhase; 265 | alwaysOutOfDate = 1; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | ); 269 | inputFileListPaths = ( 270 | "${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemo/Pods-CheckmarkCollectionViewCellDemo-frameworks-${CONFIGURATION}-input-files.xcfilelist", 271 | ); 272 | name = "[CP] Embed Pods Frameworks"; 273 | outputFileListPaths = ( 274 | "${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemo/Pods-CheckmarkCollectionViewCellDemo-frameworks-${CONFIGURATION}-output-files.xcfilelist", 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemo/Pods-CheckmarkCollectionViewCellDemo-frameworks.sh\"\n"; 279 | showEnvVarsInLog = 0; 280 | }; 281 | 5B0A788D94DAB73B93AB7E2F /* [CP] Embed Pods Frameworks */ = { 282 | isa = PBXShellScriptBuildPhase; 283 | alwaysOutOfDate = 1; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | ); 287 | inputFileListPaths = ( 288 | "${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemoUITests/Pods-CheckmarkCollectionViewCellDemoUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", 289 | ); 290 | name = "[CP] Embed Pods Frameworks"; 291 | outputFileListPaths = ( 292 | "${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemoUITests/Pods-CheckmarkCollectionViewCellDemoUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | shellPath = /bin/sh; 296 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CheckmarkCollectionViewCellDemoUITests/Pods-CheckmarkCollectionViewCellDemoUITests-frameworks.sh\"\n"; 297 | showEnvVarsInLog = 0; 298 | }; 299 | 5D8DD2BE19F0D31DE91C5AE8 /* [CP-User] SwiftLintAutocorrect */ = { 300 | isa = PBXShellScriptBuildPhase; 301 | alwaysOutOfDate = 1; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | ); 305 | name = "[CP-User] SwiftLintAutocorrect"; 306 | runOnlyForDeploymentPostprocessing = 0; 307 | shellPath = /bin/sh; 308 | shellScript = "if [[ \"Debug\" == \"${CONFIGURATION}\" && ! $ENABLE_PREVIEWS == \"YES\" ]]; then \"${PODS_ROOT}/SwiftLint/swiftlint\" --fix --config \"${PODS_ROOT}/SwiftQuality/.swiftlint.yml\" \"${SRCROOT}/..\" ; fi"; 309 | showEnvVarsInLog = 0; 310 | }; 311 | 9DAA1DF7C3D5C4D5F50D9442 /* [CP] Check Pods Manifest.lock */ = { 312 | isa = PBXShellScriptBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | ); 316 | inputFileListPaths = ( 317 | ); 318 | inputPaths = ( 319 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 320 | "${PODS_ROOT}/Manifest.lock", 321 | ); 322 | name = "[CP] Check Pods Manifest.lock"; 323 | outputFileListPaths = ( 324 | ); 325 | outputPaths = ( 326 | "$(DERIVED_FILE_DIR)/Pods-CheckmarkCollectionViewCellDemoUITests-checkManifestLockResult.txt", 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 331 | showEnvVarsInLog = 0; 332 | }; 333 | B33370CB4ACBA4BCA0B20225 /* [CP] Check Pods Manifest.lock */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | inputFileListPaths = ( 339 | ); 340 | inputPaths = ( 341 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 342 | "${PODS_ROOT}/Manifest.lock", 343 | ); 344 | name = "[CP] Check Pods Manifest.lock"; 345 | outputFileListPaths = ( 346 | ); 347 | outputPaths = ( 348 | "$(DERIVED_FILE_DIR)/Pods-CheckmarkCollectionViewCellDemo-checkManifestLockResult.txt", 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | shellPath = /bin/sh; 352 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 353 | showEnvVarsInLog = 0; 354 | }; 355 | /* End PBXShellScriptBuildPhase section */ 356 | 357 | /* Begin PBXSourcesBuildPhase section */ 358 | DC4EAF5D216B6AEB00E51171 /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | DC4EAF65216B6AEB00E51171 /* AppDelegate.swift in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | DC52B510220914BF00A01098 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | DC52B517220914C100A01098 /* CheckmarkCollectionViewCellDemoUITests.swift in Sources */, 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | }; 374 | /* End PBXSourcesBuildPhase section */ 375 | 376 | /* Begin PBXTargetDependency section */ 377 | DC52B51A220914C100A01098 /* PBXTargetDependency */ = { 378 | isa = PBXTargetDependency; 379 | target = DC4EAF60216B6AEB00E51171 /* CheckmarkCollectionViewCellDemo */; 380 | targetProxy = DC52B519220914C100A01098 /* PBXContainerItemProxy */; 381 | }; 382 | /* End PBXTargetDependency section */ 383 | 384 | /* Begin PBXVariantGroup section */ 385 | DC4EAF68216B6AEB00E51171 /* Main.storyboard */ = { 386 | isa = PBXVariantGroup; 387 | children = ( 388 | DC4EAF69216B6AEB00E51171 /* Base */, 389 | ); 390 | name = Main.storyboard; 391 | sourceTree = ""; 392 | }; 393 | DC4EAF6D216B6AF000E51171 /* LaunchScreen.storyboard */ = { 394 | isa = PBXVariantGroup; 395 | children = ( 396 | DC4EAF6E216B6AF000E51171 /* Base */, 397 | ); 398 | name = LaunchScreen.storyboard; 399 | sourceTree = ""; 400 | }; 401 | /* End PBXVariantGroup section */ 402 | 403 | /* Begin XCBuildConfiguration section */ 404 | DC4EAF71216B6AF000E51171 /* Debug */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ALWAYS_SEARCH_USER_PATHS = NO; 408 | CLANG_ANALYZER_NONNULL = YES; 409 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_ENABLE_OBJC_WEAK = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 420 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 421 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 422 | CLANG_WARN_EMPTY_BODY = YES; 423 | CLANG_WARN_ENUM_CONVERSION = YES; 424 | CLANG_WARN_INFINITE_RECURSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 431 | CLANG_WARN_STRICT_PROTOTYPES = YES; 432 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 433 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 434 | CLANG_WARN_UNREACHABLE_CODE = YES; 435 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 436 | CODE_SIGN_IDENTITY = "iPhone Developer"; 437 | COPY_PHASE_STRIP = NO; 438 | DEBUG_INFORMATION_FORMAT = dwarf; 439 | ENABLE_STRICT_OBJC_MSGSEND = YES; 440 | ENABLE_TESTABILITY = YES; 441 | GCC_C_LANGUAGE_STANDARD = gnu11; 442 | GCC_DYNAMIC_NO_PIC = NO; 443 | GCC_NO_COMMON_BLOCKS = YES; 444 | GCC_OPTIMIZATION_LEVEL = 0; 445 | GCC_PREPROCESSOR_DEFINITIONS = ( 446 | "DEBUG=1", 447 | "$(inherited)", 448 | ); 449 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 450 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 451 | GCC_WARN_UNDECLARED_SELECTOR = YES; 452 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 453 | GCC_WARN_UNUSED_FUNCTION = YES; 454 | GCC_WARN_UNUSED_VARIABLE = YES; 455 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 456 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 457 | MTL_FAST_MATH = YES; 458 | ONLY_ACTIVE_ARCH = YES; 459 | SDKROOT = iphoneos; 460 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 461 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 462 | SWIFT_VERSION = 5.0; 463 | }; 464 | name = Debug; 465 | }; 466 | DC4EAF72216B6AF000E51171 /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | ALWAYS_SEARCH_USER_PATHS = NO; 470 | CLANG_ANALYZER_NONNULL = YES; 471 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 472 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 473 | CLANG_CXX_LIBRARY = "libc++"; 474 | CLANG_ENABLE_MODULES = YES; 475 | CLANG_ENABLE_OBJC_ARC = YES; 476 | CLANG_ENABLE_OBJC_WEAK = YES; 477 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 478 | CLANG_WARN_BOOL_CONVERSION = YES; 479 | CLANG_WARN_COMMA = YES; 480 | CLANG_WARN_CONSTANT_CONVERSION = YES; 481 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 483 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 484 | CLANG_WARN_EMPTY_BODY = YES; 485 | CLANG_WARN_ENUM_CONVERSION = YES; 486 | CLANG_WARN_INFINITE_RECURSION = YES; 487 | CLANG_WARN_INT_CONVERSION = YES; 488 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 489 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 490 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 491 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 492 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 493 | CLANG_WARN_STRICT_PROTOTYPES = YES; 494 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 495 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 496 | CLANG_WARN_UNREACHABLE_CODE = YES; 497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 498 | CODE_SIGN_IDENTITY = "iPhone Developer"; 499 | COPY_PHASE_STRIP = NO; 500 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 501 | ENABLE_NS_ASSERTIONS = NO; 502 | ENABLE_STRICT_OBJC_MSGSEND = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu11; 504 | GCC_NO_COMMON_BLOCKS = YES; 505 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 506 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 507 | GCC_WARN_UNDECLARED_SELECTOR = YES; 508 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 509 | GCC_WARN_UNUSED_FUNCTION = YES; 510 | GCC_WARN_UNUSED_VARIABLE = YES; 511 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 512 | MTL_ENABLE_DEBUG_INFO = NO; 513 | MTL_FAST_MATH = YES; 514 | SDKROOT = iphoneos; 515 | SWIFT_COMPILATION_MODE = wholemodule; 516 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 517 | SWIFT_VERSION = 5.0; 518 | VALIDATE_PRODUCT = YES; 519 | }; 520 | name = Release; 521 | }; 522 | DC4EAF74216B6AF000E51171 /* Debug */ = { 523 | isa = XCBuildConfiguration; 524 | baseConfigurationReference = 602EC5F537EB0FFAA88F1F70 /* Pods-CheckmarkCollectionViewCellDemo.debug.xcconfig */; 525 | buildSettings = { 526 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 527 | CODE_SIGN_STYLE = Automatic; 528 | INFOPLIST_FILE = CheckmarkCollectionViewCellDemo/Info.plist; 529 | LD_RUNPATH_SEARCH_PATHS = ( 530 | "$(inherited)", 531 | "@executable_path/Frameworks", 532 | ); 533 | PRODUCT_BUNDLE_IDENTIFIER = com.roysharon.CheckmarkCollectionViewCellDemo; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | TARGETED_DEVICE_FAMILY = "1,2"; 536 | }; 537 | name = Debug; 538 | }; 539 | DC4EAF75216B6AF000E51171 /* Release */ = { 540 | isa = XCBuildConfiguration; 541 | baseConfigurationReference = B066D7D9AD80D7F199C2A9DE /* Pods-CheckmarkCollectionViewCellDemo.release.xcconfig */; 542 | buildSettings = { 543 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 544 | CODE_SIGN_STYLE = Automatic; 545 | INFOPLIST_FILE = CheckmarkCollectionViewCellDemo/Info.plist; 546 | LD_RUNPATH_SEARCH_PATHS = ( 547 | "$(inherited)", 548 | "@executable_path/Frameworks", 549 | ); 550 | PRODUCT_BUNDLE_IDENTIFIER = com.roysharon.CheckmarkCollectionViewCellDemo; 551 | PRODUCT_NAME = "$(TARGET_NAME)"; 552 | TARGETED_DEVICE_FAMILY = "1,2"; 553 | }; 554 | name = Release; 555 | }; 556 | DC52B51B220914C100A01098 /* Debug */ = { 557 | isa = XCBuildConfiguration; 558 | baseConfigurationReference = 58BCED1A5B7E318D5D941DEE /* Pods-CheckmarkCollectionViewCellDemoUITests.debug.xcconfig */; 559 | buildSettings = { 560 | CODE_SIGN_STYLE = Automatic; 561 | INFOPLIST_FILE = CheckmarkCollectionViewCellDemoUITests/Info.plist; 562 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 563 | LD_RUNPATH_SEARCH_PATHS = ( 564 | "$(inherited)", 565 | "@executable_path/Frameworks", 566 | "@loader_path/Frameworks", 567 | ); 568 | PRODUCT_BUNDLE_IDENTIFIER = com.roysharon.CheckmarkCollectionViewCellDemoUITests; 569 | PRODUCT_NAME = "$(TARGET_NAME)"; 570 | TARGETED_DEVICE_FAMILY = "1,2"; 571 | TEST_TARGET_NAME = CheckmarkCollectionViewCellDemo; 572 | }; 573 | name = Debug; 574 | }; 575 | DC52B51C220914C100A01098 /* Release */ = { 576 | isa = XCBuildConfiguration; 577 | baseConfigurationReference = F55C945A5A2D738411057BB7 /* Pods-CheckmarkCollectionViewCellDemoUITests.release.xcconfig */; 578 | buildSettings = { 579 | CODE_SIGN_STYLE = Automatic; 580 | INFOPLIST_FILE = CheckmarkCollectionViewCellDemoUITests/Info.plist; 581 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 582 | LD_RUNPATH_SEARCH_PATHS = ( 583 | "$(inherited)", 584 | "@executable_path/Frameworks", 585 | "@loader_path/Frameworks", 586 | ); 587 | PRODUCT_BUNDLE_IDENTIFIER = com.roysharon.CheckmarkCollectionViewCellDemoUITests; 588 | PRODUCT_NAME = "$(TARGET_NAME)"; 589 | TARGETED_DEVICE_FAMILY = "1,2"; 590 | TEST_TARGET_NAME = CheckmarkCollectionViewCellDemo; 591 | }; 592 | name = Release; 593 | }; 594 | /* End XCBuildConfiguration section */ 595 | 596 | /* Begin XCConfigurationList section */ 597 | DC4EAF5C216B6AEB00E51171 /* Build configuration list for PBXProject "CheckmarkCollectionViewCellDemo" */ = { 598 | isa = XCConfigurationList; 599 | buildConfigurations = ( 600 | DC4EAF71216B6AF000E51171 /* Debug */, 601 | DC4EAF72216B6AF000E51171 /* Release */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | DC4EAF73216B6AF000E51171 /* Build configuration list for PBXNativeTarget "CheckmarkCollectionViewCellDemo" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | DC4EAF74216B6AF000E51171 /* Debug */, 610 | DC4EAF75216B6AF000E51171 /* Release */, 611 | ); 612 | defaultConfigurationIsVisible = 0; 613 | defaultConfigurationName = Release; 614 | }; 615 | DC52B51D220914C100A01098 /* Build configuration list for PBXNativeTarget "CheckmarkCollectionViewCellDemoUITests" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | DC52B51B220914C100A01098 /* Debug */, 619 | DC52B51C220914C100A01098 /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | /* End XCConfigurationList section */ 625 | }; 626 | rootObject = DC4EAF59216B6AEB00E51171 /* Project object */; 627 | } 628 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CheckmarkCollectionViewCellDemo 4 | // 5 | // Created by Yonat Sharon on 08.10.2018. 6 | // Copyright © 2018 Yonat Sharon. All rights reserved. 7 | // 8 | 9 | import CheckmarkCollectionViewCell 10 | import UIKit 11 | 12 | class CheckmarkCollectionViewController: UICollectionViewController { 13 | let cellColors = (0 ..< 42).map { _ in UIColor.randomColor(brightness: 1) } // swiftlint:disable:this numbers_smell 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | collectionView.allowsMultipleSelection = true 18 | } 19 | 20 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 21 | return cellColors.count 22 | } 23 | 24 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 25 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CheckmarkCollectionViewCell", for: indexPath) 26 | cell.contentView.backgroundColor = cellColors[indexPath.item] 27 | return cell 28 | } 29 | } 30 | 31 | @UIApplicationMain 32 | class AppDelegate: UIResponder, UIApplicationDelegate { 33 | var window: UIWindow? 34 | 35 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 36 | CheckmarkCollectionViewCell.appearance().checkmarkLocation = [NSLayoutConstraint.Attribute.top, NSLayoutConstraint.Attribute.left] 37 | return true 38 | } 39 | } 40 | 41 | public extension UIColor { 42 | class func randomColor(hue: CGFloat? = nil, saturation: CGFloat? = nil, brightness: CGFloat? = nil) -> UIColor { 43 | let hue = hue ?? CGFloat(arc4random() % 256) / 256 // 0.0 to 1.0 44 | let saturation = saturation ?? CGFloat(arc4random() % 128) / 256 + 0.5 // 0.5 to 1.0, away from white 45 | let brightness = brightness ?? CGFloat(arc4random() % 128) / 256 + 0.5 // 0.5 to 1.0, away from black 46 | return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.6 19 | CFBundleVersion 20 | 22 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemoUITests/CheckmarkCollectionViewCellDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CheckmarkCollectionViewCellDemoUITests.swift 3 | // CheckmarkCollectionViewCellDemoUITests 4 | // 5 | // Created by Yonat Sharon on 05.02.2019. 6 | // Copyright © 2019 Yonat Sharon. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | // swiftlint:disable force_cast 12 | class CheckmarkCollectionViewCellDemoUITests: XCTestCase { 13 | override func setUp() { 14 | super.setUp() 15 | XCUIApplication().launch() 16 | } 17 | 18 | func testCellReuse() { 19 | let app = XCUIApplication() 20 | let collectionView = app.collectionViews.element(boundBy: 0) 21 | let firstCell = collectionView.cells.firstMatch 22 | let firstCheckmark = firstCell.images["checkmark"] 23 | XCTAssert(firstCheckmark.exists) 24 | 25 | XCTAssertEqual(firstCheckmark.value as! String, "unchecked") 26 | firstCell.tap() 27 | sleep(1) 28 | XCTAssertEqual(firstCheckmark.value as! String, "checked") 29 | 30 | collectionView.swipeUp() 31 | sleep(1) 32 | collectionView.swipeDown() 33 | sleep(1) 34 | 35 | XCTAssertEqual(firstCheckmark.value as! String, "checked") 36 | firstCell.tap() 37 | sleep(1) 38 | XCTAssertEqual(firstCheckmark.value as! String, "unchecked") 39 | } 40 | } 41 | 42 | // swiftlint:enable force_cast 43 | -------------------------------------------------------------------------------- /Example/CheckmarkCollectionViewCellDemoUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '11.0' 2 | 3 | use_frameworks! 4 | pod 'CheckmarkCollectionViewCell', :path => '..' 5 | pod 'SwiftQuality', :git => 'https://github.com/yonat/SwiftQuality' 6 | 7 | target 'CheckmarkCollectionViewCellDemo' do 8 | script_phase :name => 'SwiftFormat', 9 | :execution_position => :before_compile, 10 | :script => 'if [[ "Debug" == "${CONFIGURATION}" && ! $ENABLE_PREVIEWS == "YES" ]]; then "${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" --swiftversion ${SWIFT_VERSION} --config "${PODS_ROOT}/SwiftQuality/.swiftformat" "${SRCROOT}/.." ; fi' 11 | 12 | script_phase :name => 'SwiftLintAutocorrect', 13 | :execution_position => :before_compile, 14 | :script => 'if [[ "Debug" == "${CONFIGURATION}" && ! $ENABLE_PREVIEWS == "YES" ]]; then "${PODS_ROOT}/SwiftLint/swiftlint" --fix --config "${PODS_ROOT}/SwiftQuality/.swiftlint.yml" "${SRCROOT}/.." ; fi' 15 | 16 | script_phase :name => 'SwiftLint', 17 | :execution_position => :after_compile, 18 | :script => 'if [ "Debug" == "${CONFIGURATION}" && ! $ENABLE_PREVIEWS == "YES" ]; then "${PODS_ROOT}/SwiftLint/swiftlint" --config "${PODS_ROOT}/SwiftQuality/.swiftlint.yml" "${SRCROOT}/.." ; fi' 19 | end 20 | 21 | target 'CheckmarkCollectionViewCellDemoUITests' do 22 | end 23 | 24 | # Fix Xcode 14 warnings "Run script build phase '[CP] _____' will be run during every build because it does not specify any outputs." 25 | # Based on https://github.com/CocoaPods/CocoaPods/issues/11444#issuecomment-1300023416 26 | post_integrate do |installer| 27 | main_project = installer.aggregate_targets[0].user_project 28 | main_project.targets.each do |target| 29 | target.build_phases.each do |phase| 30 | next unless phase.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) 31 | next unless phase.name.start_with?("[CP") 32 | next unless (phase.input_paths || []).empty? && (phase.output_paths || []).empty? 33 | phase.always_out_of_date = "1" 34 | end 35 | end 36 | main_project.save 37 | end 38 | 39 | # Workaround for Xcode 15 error DT_TOOLCHAIN_DIR cannot be used to evaluate LIBRARY_SEARCH_PATHS 40 | post_install do |installer| 41 | installer.aggregate_targets.each do |target| 42 | target.xcconfigs.each do |variant, xcconfig| 43 | xcconfig_path = target.client_root + target.xcconfig_relative_path(variant) 44 | IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) 45 | end 46 | end 47 | installer.pods_project.targets.each do |target| 48 | target.build_configurations.each do |config| 49 | if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference 50 | xcconfig_path = config.base_configuration_reference.real_path 51 | IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CheckmarkCollectionViewCell (1.0.5): 3 | - CheckmarkCollectionViewCell/Resources (= 1.0.5) 4 | - SweeterSwift 5 | - CheckmarkCollectionViewCell/Resources (1.0.5): 6 | - SweeterSwift 7 | - SweeterSwift (1.2.2) 8 | - SwiftFormat/CLI (0.50.7) 9 | - SwiftLint (0.50.3) 10 | - SwiftQuality (2.0.1): 11 | - SwiftFormat/CLI (= 0.50.7) 12 | - SwiftLint (= 0.50.3) 13 | 14 | DEPENDENCIES: 15 | - CheckmarkCollectionViewCell (from `..`) 16 | - SwiftQuality (from `https://github.com/yonat/SwiftQuality`) 17 | 18 | SPEC REPOS: 19 | trunk: 20 | - SweeterSwift 21 | - SwiftFormat 22 | - SwiftLint 23 | 24 | EXTERNAL SOURCES: 25 | CheckmarkCollectionViewCell: 26 | :path: ".." 27 | SwiftQuality: 28 | :git: https://github.com/yonat/SwiftQuality 29 | 30 | CHECKOUT OPTIONS: 31 | SwiftQuality: 32 | :commit: f192ce833f082501a51269c1cb08cf6cf01fa3a3 33 | :git: https://github.com/yonat/SwiftQuality 34 | 35 | SPEC CHECKSUMS: 36 | CheckmarkCollectionViewCell: 8547861b1e8b12827d799c078f55bc44733d605e 37 | SweeterSwift: a875c6c0242ed0fb5f7859bf9832fd3648c3822f 38 | SwiftFormat: 4fcf72ee44c7198255108c22ed7135c38a36ba6b 39 | SwiftLint: 77f7cb2b9bb81ab4a12fcc86448ba3f11afa50c6 40 | SwiftQuality: 8d69820e0f82a25563c3cb33d31b0a11f124ea0c 41 | 42 | PODFILE CHECKSUM: e6f140035691d0c6401a4fe6611be4a150e65920 43 | 44 | COCOAPODS: 1.12.1 45 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yonat Sharon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.6 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "CheckmarkCollectionViewCell", 7 | platforms: [ 8 | .iOS(.v9), 9 | ], 10 | products: [ 11 | .library(name: "CheckmarkCollectionViewCell", targets: ["CheckmarkCollectionViewCell"]), 12 | ], 13 | dependencies: [ 14 | .package(url: "https://github.com/yonat/SweeterSwift", from: "1.0.2"), 15 | ], 16 | targets: [ 17 | .target(name: "CheckmarkCollectionViewCell", dependencies: ["SweeterSwift"], path: "Sources", resources: [.process("PrivacyInfo.xcprivacy")]), 18 | ], 19 | swiftLanguageVersions: [.v5] 20 | ) 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CheckmarkCollectionViewCell 2 | 3 | 4 | [![Swift Version][swift-image]][swift-url] 5 | [![Build Status][travis-image]][travis-url] 6 | [![License][license-image]][license-url] 7 | [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/CheckmarkCollectionViewCell.svg)](https://img.shields.io/cocoapods/v/CheckmarkCollectionViewCell.svg) 8 | [![Platform](https://img.shields.io/cocoapods/p/CheckmarkCollectionViewCell.svg?style=flat)](http://cocoapods.org/pods/CheckmarkCollectionViewCell) 9 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) 10 | 11 | `UICollectionViewCell` with checkbox when it `isSelected` and empty circle when not - like Photos.app "Select" mode. 12 | 13 | 14 | ## Usage 15 | 16 | ```swift 17 | class MyCell: CheckmarkCollectionViewCell { 18 | // get checkmark for free 19 | } 20 | ``` 21 | 22 | ### Changing Appearance 23 | 24 | The properties below can be set in Interface Builder, in code, or through a UIAppearance proxy (e.g., `CheckmarkCollectionViewCell.appearance().deselectedImage = nil`). 25 | 26 | Shape: 27 | 28 | ```swift 29 | cell.selectedImage = UIImage(named: "x") 30 | cell.deselectedImage = UIImage(named: "o") 31 | ``` 32 | 33 | Color: 34 | 35 | ```swift 36 | cell.tintColor = .red 37 | ``` 38 | 39 | Size: 40 | 41 | ```swift 42 | cell.checkmarkSize = 42.0 43 | ``` 44 | 45 | Layout: 46 | 47 | ```swift 48 | cell.checkmarkMargin = 17.0 49 | cell.checkmarkLocation = [NSLayoutConstraint.Attribute.top, NSLayoutConstraint.Attribute.left] 50 | ``` 51 | 52 | ## Installation 53 | 54 | ### CocoaPods: 55 | 56 | ```ruby 57 | pod 'CheckmarkCollectionViewCell' 58 | ``` 59 | 60 | 61 | ### Swift Package Manager: 62 | 63 | ```swift 64 | dependencies: [ 65 | .package(url: "https://github.com/yonat/CheckmarkCollectionViewCell", from: "1.1.0") 66 | ] 67 | ``` 68 | 69 | ## Meta 70 | 71 | [@yonatsharon](https://twitter.com/yonatsharon) 72 | 73 | [https://github.com/yonat/CheckmarkCollectionViewCell](https://github.com/yonat/CheckmarkCollectionViewCell) 74 | 75 | [swift-image]:https://img.shields.io/badge/swift-4.2-orange.svg 76 | [swift-url]: https://swift.org/ 77 | [license-image]: https://img.shields.io/badge/License-MIT-blue.svg 78 | [license-url]: LICENSE.txt 79 | [travis-image]: https://img.shields.io/travis/dbader/node-datadog-metrics/master.svg?style=flat-square 80 | [travis-url]: https://travis-ci.org/dbader/node-datadog-metrics 81 | [codebeat-image]: https://codebeat.co/badges/c19b47ea-2f9d-45df-8458-b2d952fe9dad 82 | [codebeat-url]: https://codebeat.co/projects/github-com-vsouza-awesomeios-com 83 | -------------------------------------------------------------------------------- /Screenshots/CheckmarkCollectionViewCell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonat/CheckmarkCollectionViewCell/2d992014648c97540b05cd84742cfd265a7cd215/Screenshots/CheckmarkCollectionViewCell.png -------------------------------------------------------------------------------- /Sources/CheckmarkCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CheckmarkCollectionViewCell.swift 3 | // Cell with checkbox when it isSelected, empty circle when not. 4 | // 5 | // Created by Yonat Sharon on 08.10.2018. 6 | // Copyright © 2018 Yonat Sharon. All rights reserved. 7 | // 8 | 9 | import SweeterSwift 10 | import UIKit 11 | 12 | @IBDesignable open class CheckmarkCollectionViewCell: UICollectionViewCell { 13 | // MARK: - Properties 14 | 15 | @IBInspectable open dynamic var selectedImage: UIImage? = UIImage(podAssetName: "checked") { didSet { updateCheckmarkImage() } } 16 | @IBInspectable open dynamic var deselectedImage: UIImage? = UIImage(podAssetName: "unchecked") { didSet { updateCheckmarkImage() } } 17 | 18 | @IBInspectable open dynamic var checkmarkSize: CGFloat = 24 { 19 | didSet { 20 | checkmarkView.constrain(.width, to: checkmarkSize) 21 | } 22 | } 23 | 24 | @IBInspectable open dynamic var checkmarkMargin: CGFloat = 8 { 25 | didSet { 26 | checkmarkConstraints.forEach { 27 | let sign = $0.constant / abs($0.constant) 28 | $0.constant = checkmarkMargin * sign 29 | } 30 | } 31 | } 32 | 33 | /// Set of `NSLayoutConstraint.Attribute` specifying how to locate the checkmark in relation to the cell 34 | @objc open dynamic var checkmarkLocation: NSSet = [NSLayoutConstraint.Attribute.bottom, NSLayoutConstraint.Attribute.right] { 35 | didSet { 36 | guard checkmarkView.superview == contentView else { return } 37 | contentView.removeConstraints(checkmarkConstraints) 38 | checkmarkConstraints = checkmarkLocation.compactMap { $0 as? NSLayoutConstraint.Attribute }.map { attribute in 39 | contentView.constrain(checkmarkView, at: attribute, diff: attribute.inwardSign * checkmarkMargin) 40 | } 41 | } 42 | } 43 | 44 | // MARK: - Subviews 45 | 46 | public let checkmarkView: UIImageView = { 47 | let checkmarkView = UIImageView() 48 | checkmarkView.contentMode = .scaleAspectFit 49 | checkmarkView.layoutMargins = .zero 50 | checkmarkView.translatesAutoresizingMaskIntoConstraints = false 51 | checkmarkView.heightAnchor.constraint(equalTo: checkmarkView.widthAnchor).isActive = true 52 | checkmarkView.accessibilityLabel = "checkmark" 53 | return checkmarkView 54 | }() 55 | 56 | var checkmarkConstraints: [NSLayoutConstraint] = [] 57 | 58 | // MARK: - Overrides 59 | 60 | override open var isSelected: Bool { 61 | didSet { 62 | let animation = CATransition() 63 | animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) 64 | animation.duration = 0.1 65 | checkmarkView.layer.add(animation, forKey: CATransitionType.fade.rawValue) 66 | 67 | updateCheckmarkImage() 68 | } 69 | } 70 | 71 | override open func layoutSubviews() { 72 | super.layoutSubviews() 73 | if contentView != checkmarkView.superview { 74 | setup() 75 | } else if checkmarkView != contentView.subviews.last { 76 | contentView.bringSubviewToFront(checkmarkView) 77 | } 78 | } 79 | 80 | // MARK: - Privates 81 | 82 | private func updateCheckmarkImage() { 83 | checkmarkView.image = (isSelected ? selectedImage : deselectedImage)?.withRenderingMode(.alwaysTemplate) 84 | checkmarkView.accessibilityValue = isSelected ? "checked" : "unchecked" 85 | } 86 | 87 | private func setup() { 88 | contentView.addSubview(checkmarkView) 89 | updateCheckmarkImage() 90 | checkmarkSize = { checkmarkSize }() 91 | checkmarkLocation = { checkmarkLocation }() 92 | } 93 | } 94 | 95 | extension NSLayoutConstraint.Attribute { 96 | var inwardSign: CGFloat { 97 | switch self { 98 | case .top, .topMargin: return 1 99 | case .bottom, .bottomMargin: return -1 100 | case .left, .leading, .leftMargin, .leadingMargin: return 1 101 | case .right, .trailing, .rightMargin, .trailingMargin: return -1 102 | default: return 1 103 | } 104 | } 105 | } 106 | 107 | extension UIImage { 108 | convenience init?(podAssetName: String) { 109 | let podBundle = Bundle(for: CheckmarkCollectionViewCell.self) 110 | guard let url = podBundle.url(forResource: "CheckmarkCollectionViewCell", withExtension: "bundle") else { return nil } 111 | self.init(named: podAssetName, in: Bundle(url: url), compatibleWith: nil) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Sources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyCollectedDataTypes 8 | 9 | NSPrivacyAccessedAPITypes 10 | 11 | NSPrivacyTrackingDomains 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Sources/checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonat/CheckmarkCollectionViewCell/2d992014648c97540b05cd84742cfd265a7cd215/Sources/checked.png -------------------------------------------------------------------------------- /Sources/unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonat/CheckmarkCollectionViewCell/2d992014648c97540b05cd84742cfd265a7cd215/Sources/unchecked.png --------------------------------------------------------------------------------