├── .gitignore ├── .travis.yml ├── ASWeekSelectorView.podspec ├── Example ├── ASWeekSelectorView.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── ASWeekSelectorView.xcscheme └── ASWeekSelectorView │ ├── ASAppDelegate.h │ ├── ASAppDelegate.m │ ├── ASViewController.h │ ├── ASViewController.m │ ├── ASWeekSelectorView-Info.plist │ ├── ASWeekSelectorView-Prefix.pch │ ├── Base.lproj │ └── Main.storyboard │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Info.plist │ ├── en.lproj │ └── InfoPlist.strings │ └── main.m ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── ASWeekSelectorView │ ├── ASDaySelectionView.h │ ├── ASDaySelectionView.m │ ├── ASSingleWeekView.h │ ├── ASSingleWeekView.m │ ├── ASWeekSelectorView.m │ ├── Resources │ ├── ar.lproj │ │ └── ASWeekSelectorView.strings │ ├── de.lproj │ │ └── ASWeekSelectorView.strings │ ├── en.lproj │ │ └── ASWeekSelectorView.strings │ ├── es.lproj │ │ └── ASWeekSelectorView.strings │ ├── it.lproj │ │ └── ASWeekSelectorView.strings │ └── ja.lproj │ │ └── ASWeekSelectorView.strings │ └── include │ └── ASWeekSelectorView │ └── ASWeekSelectorView.h └── weekpicker.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .build 19 | .swiftpm -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11 3 | xcode_project: Example/ASWeekSelectorView.xcodeproj 4 | xcode_scheme: ASWeekSelectorView 5 | xcode_sdk: iphonesimulator13.0 6 | env: 7 | global: 8 | - FRAMEWORK_NAME=ASWeekSelectorView 9 | before_install: 10 | - brew update 11 | - brew outdated carthage || brew upgrade carthage 12 | before_deploy: 13 | - carthage build --no-skip-current 14 | - carthage archive $FRAMEWORK_NAME 15 | script: 16 | - xcodebuild clean build -sdk iphonesimulator -project Example/ASWeekSelectorView.xcodeproj -scheme ASWeekSelectorView CODE_SIGNING_REQUIRED=NO 17 | deploy: 18 | provider: releases 19 | api_key: 20 | secure: t7BNwlYdtueVSQBXAF+FcvjmLa3uBDXCaue3HVeFlXdA0lV04BQUpdCK6rRhfAw941LiKQxaCbfUFWAs1K4vm7AAkHhwvjdhlseG2hmlV4Jqx39g7mJAOl8s8DM5DJvvfiI764DzyUmHBNNB0l4IQ2eWzieOLBZdsdd4SrhvfkE= 21 | file: $FRAMEWORK_NAME.framework.zip 22 | skip_cleanup: true 23 | on: 24 | repo: nighthawk/ASWeekSelectorView 25 | tags: true 26 | -------------------------------------------------------------------------------- /ASWeekSelectorView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ASWeekSelectorView" 3 | s.version = "1.1.2" 4 | s.summary = "iOS calendar-inspired simple mini week view to select swipe through weeks and tap on days" 5 | s.description = <<-DESC 6 | A mini week view to select a day. You can swipe through weeks and tap on days to select them, somewhat similar to the iOS 7 calendar app. 7 | DESC 8 | s.homepage = "https://github.com/nighthawk/ASWeekSelectorView" 9 | s.license = 'FreeBSD' 10 | s.author = { "Adrian Schoenig" => "adrian@schoenig.me" } 11 | # s.source = { git: '.'} 12 | s.source = { :git => "https://github.com/nighthawk/ASWeekSelectorView.git", :tag => "#{s.version}" } 13 | s.platform = :ios, '10.0' 14 | s.source_files = [ 15 | 'Sources/**/*.{h,m}' 16 | ] 17 | s.resource_bundles = { "ASWeekSelectorView" => "Sources/ASWeekSelectorView/Resources/*" } 18 | s.requires_arc = true 19 | end 20 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3AAC012D18FE027600EBD85D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC012C18FE027600EBD85D /* Foundation.framework */; }; 11 | 3AAC012F18FE027700EBD85D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC012E18FE027700EBD85D /* CoreGraphics.framework */; }; 12 | 3AAC013118FE027700EBD85D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC013018FE027700EBD85D /* UIKit.framework */; }; 13 | 3AAC013718FE027700EBD85D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3AAC013518FE027700EBD85D /* InfoPlist.strings */; }; 14 | 3AAC013918FE027700EBD85D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC013818FE027700EBD85D /* main.m */; }; 15 | 3AAC013D18FE027700EBD85D /* ASAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC013C18FE027700EBD85D /* ASAppDelegate.m */; }; 16 | 3AAC014018FE027700EBD85D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3AAC013E18FE027700EBD85D /* Main.storyboard */; }; 17 | 3AAC014318FE027700EBD85D /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC014218FE027700EBD85D /* ASViewController.m */; }; 18 | 3AAC014518FE027700EBD85D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AAC014418FE027700EBD85D /* Images.xcassets */; }; 19 | 3AAC014C18FE027700EBD85D /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC014B18FE027700EBD85D /* XCTest.framework */; }; 20 | 3AAC014D18FE027700EBD85D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC012C18FE027600EBD85D /* Foundation.framework */; }; 21 | 3AAC014E18FE027700EBD85D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AAC013018FE027700EBD85D /* UIKit.framework */; }; 22 | 3AAC015618FE027700EBD85D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3AAC015418FE027700EBD85D /* InfoPlist.strings */; }; 23 | 3AAC015818FE027700EBD85D /* ASWeekSelectorViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC015718FE027700EBD85D /* ASWeekSelectorViewTests.m */; }; 24 | 3AF0FE6F1D363ADD00859505 /* ASWeekSelectorView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF0FE681D363ADD00859505 /* ASWeekSelectorView.framework */; }; 25 | 3AF0FE701D363ADD00859505 /* ASWeekSelectorView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF0FE681D363ADD00859505 /* ASWeekSelectorView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 26 | 3AF0FE751D363C0300859505 /* ASWeekSelectorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AAC016218FE04C800EBD85D /* ASWeekSelectorView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | 3AF0FE761D363C0800859505 /* ASDaySelectionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A278F7019062FB9009DDB4D /* ASDaySelectionView.h */; }; 28 | 3AF0FE771D363C0E00859505 /* ASSingleWeekView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AAC016518FE0A0400EBD85D /* ASSingleWeekView.h */; }; 29 | 3AF0FE781D363C1300859505 /* ASSingleWeekView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC016618FE0A0400EBD85D /* ASSingleWeekView.m */; }; 30 | 3AF0FE791D363C1300859505 /* ASDaySelectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A278F7119062FB9009DDB4D /* ASDaySelectionView.m */; }; 31 | 3AF0FE7A1D363C1300859505 /* ASWeekSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AAC016318FE04C800EBD85D /* ASWeekSelectorView.m */; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXContainerItemProxy section */ 35 | 3AAC014F18FE027700EBD85D /* PBXContainerItemProxy */ = { 36 | isa = PBXContainerItemProxy; 37 | containerPortal = 3AAC012118FE027600EBD85D /* Project object */; 38 | proxyType = 1; 39 | remoteGlobalIDString = 3AAC012818FE027600EBD85D; 40 | remoteInfo = ASWeekSelectorView; 41 | }; 42 | 3AF0FE6D1D363ADD00859505 /* PBXContainerItemProxy */ = { 43 | isa = PBXContainerItemProxy; 44 | containerPortal = 3AAC012118FE027600EBD85D /* Project object */; 45 | proxyType = 1; 46 | remoteGlobalIDString = 3AF0FE671D363ADD00859505; 47 | remoteInfo = ASWeekSelectorView; 48 | }; 49 | /* End PBXContainerItemProxy section */ 50 | 51 | /* Begin PBXCopyFilesBuildPhase section */ 52 | 3AF0FE741D363ADD00859505 /* Embed Frameworks */ = { 53 | isa = PBXCopyFilesBuildPhase; 54 | buildActionMask = 2147483647; 55 | dstPath = ""; 56 | dstSubfolderSpec = 10; 57 | files = ( 58 | 3AF0FE701D363ADD00859505 /* ASWeekSelectorView.framework in Embed Frameworks */, 59 | ); 60 | name = "Embed Frameworks"; 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXCopyFilesBuildPhase section */ 64 | 65 | /* Begin PBXFileReference section */ 66 | 3A278F7019062FB9009DDB4D /* ASDaySelectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASDaySelectionView.h; path = ../Classes/ASDaySelectionView.h; sourceTree = ""; }; 67 | 3A278F7119062FB9009DDB4D /* ASDaySelectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASDaySelectionView.m; path = ../Classes/ASDaySelectionView.m; sourceTree = ""; }; 68 | 3AAC012918FE027600EBD85D /* ASWeekSelectorViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ASWeekSelectorViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 3AAC012C18FE027600EBD85D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 70 | 3AAC012E18FE027700EBD85D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 71 | 3AAC013018FE027700EBD85D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 72 | 3AAC013418FE027700EBD85D /* ASWeekSelectorView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ASWeekSelectorView-Info.plist"; sourceTree = ""; }; 73 | 3AAC013618FE027700EBD85D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 74 | 3AAC013818FE027700EBD85D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 75 | 3AAC013A18FE027700EBD85D /* ASWeekSelectorView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ASWeekSelectorView-Prefix.pch"; sourceTree = ""; }; 76 | 3AAC013B18FE027700EBD85D /* ASAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASAppDelegate.h; sourceTree = ""; }; 77 | 3AAC013C18FE027700EBD85D /* ASAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASAppDelegate.m; sourceTree = ""; }; 78 | 3AAC013F18FE027700EBD85D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 79 | 3AAC014118FE027700EBD85D /* ASViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASViewController.h; sourceTree = ""; }; 80 | 3AAC014218FE027700EBD85D /* ASViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASViewController.m; sourceTree = ""; }; 81 | 3AAC014418FE027700EBD85D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 82 | 3AAC014A18FE027700EBD85D /* ASWeekSelectorViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ASWeekSelectorViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 83 | 3AAC014B18FE027700EBD85D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 84 | 3AAC015318FE027700EBD85D /* ASWeekSelectorViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ASWeekSelectorViewTests-Info.plist"; sourceTree = ""; }; 85 | 3AAC015518FE027700EBD85D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 86 | 3AAC015718FE027700EBD85D /* ASWeekSelectorViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASWeekSelectorViewTests.m; sourceTree = ""; }; 87 | 3AAC016218FE04C800EBD85D /* ASWeekSelectorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASWeekSelectorView.h; path = ../Classes/ASWeekSelectorView.h; sourceTree = ""; }; 88 | 3AAC016318FE04C800EBD85D /* ASWeekSelectorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASWeekSelectorView.m; path = ../Classes/ASWeekSelectorView.m; sourceTree = ""; }; 89 | 3AAC016518FE0A0400EBD85D /* ASSingleWeekView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASSingleWeekView.h; path = ../Classes/ASSingleWeekView.h; sourceTree = ""; }; 90 | 3AAC016618FE0A0400EBD85D /* ASSingleWeekView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ASSingleWeekView.m; path = ../Classes/ASSingleWeekView.m; sourceTree = ""; }; 91 | 3AF0FE681D363ADD00859505 /* ASWeekSelectorView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ASWeekSelectorView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 92 | 3AF0FE6C1D363ADD00859505 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ASWeekSelectorView/Info.plist; sourceTree = ""; }; 93 | /* End PBXFileReference section */ 94 | 95 | /* Begin PBXFrameworksBuildPhase section */ 96 | 3AAC012618FE027600EBD85D /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | 3AF0FE6F1D363ADD00859505 /* ASWeekSelectorView.framework in Frameworks */, 101 | 3AAC012F18FE027700EBD85D /* CoreGraphics.framework in Frameworks */, 102 | 3AAC013118FE027700EBD85D /* UIKit.framework in Frameworks */, 103 | 3AAC012D18FE027600EBD85D /* Foundation.framework in Frameworks */, 104 | ); 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | 3AAC014718FE027700EBD85D /* Frameworks */ = { 108 | isa = PBXFrameworksBuildPhase; 109 | buildActionMask = 2147483647; 110 | files = ( 111 | 3AAC014C18FE027700EBD85D /* XCTest.framework in Frameworks */, 112 | 3AAC014E18FE027700EBD85D /* UIKit.framework in Frameworks */, 113 | 3AAC014D18FE027700EBD85D /* Foundation.framework in Frameworks */, 114 | ); 115 | runOnlyForDeploymentPostprocessing = 0; 116 | }; 117 | 3AF0FE641D363ADD00859505 /* Frameworks */ = { 118 | isa = PBXFrameworksBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | ); 122 | runOnlyForDeploymentPostprocessing = 0; 123 | }; 124 | /* End PBXFrameworksBuildPhase section */ 125 | 126 | /* Begin PBXGroup section */ 127 | 3AAC012018FE027600EBD85D = { 128 | isa = PBXGroup; 129 | children = ( 130 | 3AAC016118FE044000EBD85D /* ASWeekSelectorView */, 131 | 3AAC013218FE027700EBD85D /* Example */, 132 | 3AAC015118FE027700EBD85D /* ASWeekSelectorViewTests */, 133 | 3AAC012B18FE027600EBD85D /* Frameworks */, 134 | 3AAC012A18FE027600EBD85D /* Products */, 135 | ); 136 | sourceTree = ""; 137 | }; 138 | 3AAC012A18FE027600EBD85D /* Products */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 3AAC012918FE027600EBD85D /* ASWeekSelectorViewExample.app */, 142 | 3AAC014A18FE027700EBD85D /* ASWeekSelectorViewTests.xctest */, 143 | 3AF0FE681D363ADD00859505 /* ASWeekSelectorView.framework */, 144 | ); 145 | name = Products; 146 | sourceTree = ""; 147 | }; 148 | 3AAC012B18FE027600EBD85D /* Frameworks */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 3AAC012C18FE027600EBD85D /* Foundation.framework */, 152 | 3AAC012E18FE027700EBD85D /* CoreGraphics.framework */, 153 | 3AAC013018FE027700EBD85D /* UIKit.framework */, 154 | 3AAC014B18FE027700EBD85D /* XCTest.framework */, 155 | ); 156 | name = Frameworks; 157 | sourceTree = ""; 158 | }; 159 | 3AAC013218FE027700EBD85D /* Example */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 3AAC013B18FE027700EBD85D /* ASAppDelegate.h */, 163 | 3AAC013C18FE027700EBD85D /* ASAppDelegate.m */, 164 | 3AAC013E18FE027700EBD85D /* Main.storyboard */, 165 | 3AAC014118FE027700EBD85D /* ASViewController.h */, 166 | 3AAC014218FE027700EBD85D /* ASViewController.m */, 167 | 3AAC014418FE027700EBD85D /* Images.xcassets */, 168 | 3AAC013318FE027700EBD85D /* Supporting Files */, 169 | ); 170 | name = Example; 171 | path = ASWeekSelectorView; 172 | sourceTree = ""; 173 | }; 174 | 3AAC013318FE027700EBD85D /* Supporting Files */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 3AAC013418FE027700EBD85D /* ASWeekSelectorView-Info.plist */, 178 | 3AAC013518FE027700EBD85D /* InfoPlist.strings */, 179 | 3AAC013818FE027700EBD85D /* main.m */, 180 | 3AAC013A18FE027700EBD85D /* ASWeekSelectorView-Prefix.pch */, 181 | ); 182 | name = "Supporting Files"; 183 | sourceTree = ""; 184 | }; 185 | 3AAC015118FE027700EBD85D /* ASWeekSelectorViewTests */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 3AAC015718FE027700EBD85D /* ASWeekSelectorViewTests.m */, 189 | 3AAC015218FE027700EBD85D /* Supporting Files */, 190 | ); 191 | path = ASWeekSelectorViewTests; 192 | sourceTree = ""; 193 | }; 194 | 3AAC015218FE027700EBD85D /* Supporting Files */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 3AAC015318FE027700EBD85D /* ASWeekSelectorViewTests-Info.plist */, 198 | 3AAC015418FE027700EBD85D /* InfoPlist.strings */, 199 | ); 200 | name = "Supporting Files"; 201 | sourceTree = ""; 202 | }; 203 | 3AAC016118FE044000EBD85D /* ASWeekSelectorView */ = { 204 | isa = PBXGroup; 205 | children = ( 206 | 3AAC016518FE0A0400EBD85D /* ASSingleWeekView.h */, 207 | 3AAC016618FE0A0400EBD85D /* ASSingleWeekView.m */, 208 | 3A278F7019062FB9009DDB4D /* ASDaySelectionView.h */, 209 | 3A278F7119062FB9009DDB4D /* ASDaySelectionView.m */, 210 | 3AAC016218FE04C800EBD85D /* ASWeekSelectorView.h */, 211 | 3AAC016318FE04C800EBD85D /* ASWeekSelectorView.m */, 212 | 3AF0FE6C1D363ADD00859505 /* Info.plist */, 213 | ); 214 | name = ASWeekSelectorView; 215 | sourceTree = ""; 216 | }; 217 | /* End PBXGroup section */ 218 | 219 | /* Begin PBXHeadersBuildPhase section */ 220 | 3AF0FE651D363ADD00859505 /* Headers */ = { 221 | isa = PBXHeadersBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 3AF0FE751D363C0300859505 /* ASWeekSelectorView.h in Headers */, 225 | 3AF0FE771D363C0E00859505 /* ASSingleWeekView.h in Headers */, 226 | 3AF0FE761D363C0800859505 /* ASDaySelectionView.h in Headers */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | /* End PBXHeadersBuildPhase section */ 231 | 232 | /* Begin PBXNativeTarget section */ 233 | 3AAC012818FE027600EBD85D /* ASWeekSelectorViewExample */ = { 234 | isa = PBXNativeTarget; 235 | buildConfigurationList = 3AAC015B18FE027700EBD85D /* Build configuration list for PBXNativeTarget "ASWeekSelectorViewExample" */; 236 | buildPhases = ( 237 | 3AAC012518FE027600EBD85D /* Sources */, 238 | 3AAC012618FE027600EBD85D /* Frameworks */, 239 | 3AAC012718FE027600EBD85D /* Resources */, 240 | 3AF0FE741D363ADD00859505 /* Embed Frameworks */, 241 | ); 242 | buildRules = ( 243 | ); 244 | dependencies = ( 245 | 3AF0FE6E1D363ADD00859505 /* PBXTargetDependency */, 246 | ); 247 | name = ASWeekSelectorViewExample; 248 | productName = ASWeekSelectorView; 249 | productReference = 3AAC012918FE027600EBD85D /* ASWeekSelectorViewExample.app */; 250 | productType = "com.apple.product-type.application"; 251 | }; 252 | 3AAC014918FE027700EBD85D /* ASWeekSelectorViewTests */ = { 253 | isa = PBXNativeTarget; 254 | buildConfigurationList = 3AAC015E18FE027700EBD85D /* Build configuration list for PBXNativeTarget "ASWeekSelectorViewTests" */; 255 | buildPhases = ( 256 | 3AAC014618FE027700EBD85D /* Sources */, 257 | 3AAC014718FE027700EBD85D /* Frameworks */, 258 | 3AAC014818FE027700EBD85D /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | 3AAC015018FE027700EBD85D /* PBXTargetDependency */, 264 | ); 265 | name = ASWeekSelectorViewTests; 266 | productName = ASWeekSelectorViewTests; 267 | productReference = 3AAC014A18FE027700EBD85D /* ASWeekSelectorViewTests.xctest */; 268 | productType = "com.apple.product-type.bundle.unit-test"; 269 | }; 270 | 3AF0FE671D363ADD00859505 /* ASWeekSelectorView */ = { 271 | isa = PBXNativeTarget; 272 | buildConfigurationList = 3AF0FE711D363ADD00859505 /* Build configuration list for PBXNativeTarget "ASWeekSelectorView" */; 273 | buildPhases = ( 274 | 3AF0FE631D363ADD00859505 /* Sources */, 275 | 3AF0FE641D363ADD00859505 /* Frameworks */, 276 | 3AF0FE651D363ADD00859505 /* Headers */, 277 | 3AF0FE661D363ADD00859505 /* Resources */, 278 | ); 279 | buildRules = ( 280 | ); 281 | dependencies = ( 282 | ); 283 | name = ASWeekSelectorView; 284 | productName = ASWeekSelectorView; 285 | productReference = 3AF0FE681D363ADD00859505 /* ASWeekSelectorView.framework */; 286 | productType = "com.apple.product-type.framework"; 287 | }; 288 | /* End PBXNativeTarget section */ 289 | 290 | /* Begin PBXProject section */ 291 | 3AAC012118FE027600EBD85D /* Project object */ = { 292 | isa = PBXProject; 293 | attributes = { 294 | CLASSPREFIX = AS; 295 | LastUpgradeCheck = 1100; 296 | ORGANIZATIONNAME = "Adrian Schoenig"; 297 | TargetAttributes = { 298 | 3AAC012818FE027600EBD85D = { 299 | DevelopmentTeam = 7N3B54ALZK; 300 | }; 301 | 3AAC014918FE027700EBD85D = { 302 | DevelopmentTeam = 7N3B54ALZK; 303 | TestTargetID = 3AAC012818FE027600EBD85D; 304 | }; 305 | 3AF0FE671D363ADD00859505 = { 306 | CreatedOnToolsVersion = 7.3.1; 307 | }; 308 | }; 309 | }; 310 | buildConfigurationList = 3AAC012418FE027600EBD85D /* Build configuration list for PBXProject "ASWeekSelectorView" */; 311 | compatibilityVersion = "Xcode 3.2"; 312 | developmentRegion = English; 313 | hasScannedForEncodings = 0; 314 | knownRegions = ( 315 | English, 316 | en, 317 | Base, 318 | ); 319 | mainGroup = 3AAC012018FE027600EBD85D; 320 | productRefGroup = 3AAC012A18FE027600EBD85D /* Products */; 321 | projectDirPath = ""; 322 | projectRoot = ""; 323 | targets = ( 324 | 3AAC012818FE027600EBD85D /* ASWeekSelectorViewExample */, 325 | 3AAC014918FE027700EBD85D /* ASWeekSelectorViewTests */, 326 | 3AF0FE671D363ADD00859505 /* ASWeekSelectorView */, 327 | ); 328 | }; 329 | /* End PBXProject section */ 330 | 331 | /* Begin PBXResourcesBuildPhase section */ 332 | 3AAC012718FE027600EBD85D /* Resources */ = { 333 | isa = PBXResourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | 3AAC014518FE027700EBD85D /* Images.xcassets in Resources */, 337 | 3AAC013718FE027700EBD85D /* InfoPlist.strings in Resources */, 338 | 3AAC014018FE027700EBD85D /* Main.storyboard in Resources */, 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | 3AAC014818FE027700EBD85D /* Resources */ = { 343 | isa = PBXResourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | 3AAC015618FE027700EBD85D /* InfoPlist.strings in Resources */, 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | 3AF0FE661D363ADD00859505 /* Resources */ = { 351 | isa = PBXResourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | /* End PBXResourcesBuildPhase section */ 358 | 359 | /* Begin PBXSourcesBuildPhase section */ 360 | 3AAC012518FE027600EBD85D /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 3AAC013D18FE027700EBD85D /* ASAppDelegate.m in Sources */, 365 | 3AAC014318FE027700EBD85D /* ASViewController.m in Sources */, 366 | 3AAC013918FE027700EBD85D /* main.m in Sources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | 3AAC014618FE027700EBD85D /* Sources */ = { 371 | isa = PBXSourcesBuildPhase; 372 | buildActionMask = 2147483647; 373 | files = ( 374 | 3AAC015818FE027700EBD85D /* ASWeekSelectorViewTests.m in Sources */, 375 | ); 376 | runOnlyForDeploymentPostprocessing = 0; 377 | }; 378 | 3AF0FE631D363ADD00859505 /* Sources */ = { 379 | isa = PBXSourcesBuildPhase; 380 | buildActionMask = 2147483647; 381 | files = ( 382 | 3AF0FE791D363C1300859505 /* ASDaySelectionView.m in Sources */, 383 | 3AF0FE781D363C1300859505 /* ASSingleWeekView.m in Sources */, 384 | 3AF0FE7A1D363C1300859505 /* ASWeekSelectorView.m in Sources */, 385 | ); 386 | runOnlyForDeploymentPostprocessing = 0; 387 | }; 388 | /* End PBXSourcesBuildPhase section */ 389 | 390 | /* Begin PBXTargetDependency section */ 391 | 3AAC015018FE027700EBD85D /* PBXTargetDependency */ = { 392 | isa = PBXTargetDependency; 393 | target = 3AAC012818FE027600EBD85D /* ASWeekSelectorViewExample */; 394 | targetProxy = 3AAC014F18FE027700EBD85D /* PBXContainerItemProxy */; 395 | }; 396 | 3AF0FE6E1D363ADD00859505 /* PBXTargetDependency */ = { 397 | isa = PBXTargetDependency; 398 | target = 3AF0FE671D363ADD00859505 /* ASWeekSelectorView */; 399 | targetProxy = 3AF0FE6D1D363ADD00859505 /* PBXContainerItemProxy */; 400 | }; 401 | /* End PBXTargetDependency section */ 402 | 403 | /* Begin PBXVariantGroup section */ 404 | 3AAC013518FE027700EBD85D /* InfoPlist.strings */ = { 405 | isa = PBXVariantGroup; 406 | children = ( 407 | 3AAC013618FE027700EBD85D /* en */, 408 | ); 409 | name = InfoPlist.strings; 410 | sourceTree = ""; 411 | }; 412 | 3AAC013E18FE027700EBD85D /* Main.storyboard */ = { 413 | isa = PBXVariantGroup; 414 | children = ( 415 | 3AAC013F18FE027700EBD85D /* Base */, 416 | ); 417 | name = Main.storyboard; 418 | sourceTree = ""; 419 | }; 420 | 3AAC015418FE027700EBD85D /* InfoPlist.strings */ = { 421 | isa = PBXVariantGroup; 422 | children = ( 423 | 3AAC015518FE027700EBD85D /* en */, 424 | ); 425 | name = InfoPlist.strings; 426 | sourceTree = ""; 427 | }; 428 | /* End PBXVariantGroup section */ 429 | 430 | /* Begin XCBuildConfiguration section */ 431 | 3AAC015918FE027700EBD85D /* Debug */ = { 432 | isa = XCBuildConfiguration; 433 | buildSettings = { 434 | ALWAYS_SEARCH_USER_PATHS = NO; 435 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 436 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 437 | CLANG_CXX_LIBRARY = "libc++"; 438 | CLANG_ENABLE_MODULES = YES; 439 | CLANG_ENABLE_OBJC_ARC = YES; 440 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 441 | CLANG_WARN_BOOL_CONVERSION = YES; 442 | CLANG_WARN_COMMA = YES; 443 | CLANG_WARN_CONSTANT_CONVERSION = YES; 444 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 445 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 446 | CLANG_WARN_EMPTY_BODY = YES; 447 | CLANG_WARN_ENUM_CONVERSION = YES; 448 | CLANG_WARN_INFINITE_RECURSION = YES; 449 | CLANG_WARN_INT_CONVERSION = YES; 450 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 451 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 452 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 453 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 454 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 455 | CLANG_WARN_STRICT_PROTOTYPES = YES; 456 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 457 | CLANG_WARN_UNREACHABLE_CODE = YES; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | COPY_PHASE_STRIP = NO; 461 | ENABLE_STRICT_OBJC_MSGSEND = YES; 462 | ENABLE_TESTABILITY = YES; 463 | GCC_C_LANGUAGE_STANDARD = gnu99; 464 | GCC_DYNAMIC_NO_PIC = NO; 465 | GCC_NO_COMMON_BLOCKS = YES; 466 | GCC_OPTIMIZATION_LEVEL = 0; 467 | GCC_PREPROCESSOR_DEFINITIONS = ( 468 | "DEBUG=1", 469 | "$(inherited)", 470 | ); 471 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 472 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 473 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 474 | GCC_WARN_UNDECLARED_SELECTOR = YES; 475 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 476 | GCC_WARN_UNUSED_FUNCTION = YES; 477 | GCC_WARN_UNUSED_VARIABLE = YES; 478 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 479 | ONLY_ACTIVE_ARCH = YES; 480 | SDKROOT = iphoneos; 481 | }; 482 | name = Debug; 483 | }; 484 | 3AAC015A18FE027700EBD85D /* Release */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ALWAYS_SEARCH_USER_PATHS = NO; 488 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 489 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 490 | CLANG_CXX_LIBRARY = "libc++"; 491 | CLANG_ENABLE_MODULES = YES; 492 | CLANG_ENABLE_OBJC_ARC = YES; 493 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 494 | CLANG_WARN_BOOL_CONVERSION = YES; 495 | CLANG_WARN_COMMA = YES; 496 | CLANG_WARN_CONSTANT_CONVERSION = YES; 497 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 498 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 499 | CLANG_WARN_EMPTY_BODY = YES; 500 | CLANG_WARN_ENUM_CONVERSION = YES; 501 | CLANG_WARN_INFINITE_RECURSION = YES; 502 | CLANG_WARN_INT_CONVERSION = YES; 503 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 504 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 505 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 506 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 507 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 508 | CLANG_WARN_STRICT_PROTOTYPES = YES; 509 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 510 | CLANG_WARN_UNREACHABLE_CODE = YES; 511 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 512 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 513 | COPY_PHASE_STRIP = YES; 514 | ENABLE_NS_ASSERTIONS = NO; 515 | ENABLE_STRICT_OBJC_MSGSEND = YES; 516 | GCC_C_LANGUAGE_STANDARD = gnu99; 517 | GCC_NO_COMMON_BLOCKS = YES; 518 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 519 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 520 | GCC_WARN_UNDECLARED_SELECTOR = YES; 521 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 522 | GCC_WARN_UNUSED_FUNCTION = YES; 523 | GCC_WARN_UNUSED_VARIABLE = YES; 524 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 525 | SDKROOT = iphoneos; 526 | VALIDATE_PRODUCT = YES; 527 | }; 528 | name = Release; 529 | }; 530 | 3AAC015C18FE027700EBD85D /* Debug */ = { 531 | isa = XCBuildConfiguration; 532 | buildSettings = { 533 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 534 | DEVELOPMENT_TEAM = 7N3B54ALZK; 535 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 536 | GCC_PREFIX_HEADER = "ASWeekSelectorView/ASWeekSelectorView-Prefix.pch"; 537 | INFOPLIST_FILE = "ASWeekSelectorView/ASWeekSelectorView-Info.plist"; 538 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 539 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 540 | PRODUCT_BUNDLE_IDENTIFIER = "net.byadrian.${PRODUCT_NAME:rfc1034identifier}"; 541 | PRODUCT_NAME = "$(TARGET_NAME)"; 542 | WRAPPER_EXTENSION = app; 543 | }; 544 | name = Debug; 545 | }; 546 | 3AAC015D18FE027700EBD85D /* Release */ = { 547 | isa = XCBuildConfiguration; 548 | buildSettings = { 549 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 550 | DEVELOPMENT_TEAM = 7N3B54ALZK; 551 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 552 | GCC_PREFIX_HEADER = "ASWeekSelectorView/ASWeekSelectorView-Prefix.pch"; 553 | INFOPLIST_FILE = "ASWeekSelectorView/ASWeekSelectorView-Info.plist"; 554 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 555 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 556 | PRODUCT_BUNDLE_IDENTIFIER = "net.byadrian.${PRODUCT_NAME:rfc1034identifier}"; 557 | PRODUCT_NAME = "$(TARGET_NAME)"; 558 | WRAPPER_EXTENSION = app; 559 | }; 560 | name = Release; 561 | }; 562 | 3AAC015F18FE027700EBD85D /* Debug */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ASWeekSelectorView.app/ASWeekSelectorView"; 566 | DEVELOPMENT_TEAM = 7N3B54ALZK; 567 | FRAMEWORK_SEARCH_PATHS = ( 568 | "$(SDKROOT)/Developer/Library/Frameworks", 569 | "$(inherited)", 570 | "$(DEVELOPER_FRAMEWORKS_DIR)", 571 | ); 572 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 573 | GCC_PREFIX_HEADER = "ASWeekSelectorView/ASWeekSelectorView-Prefix.pch"; 574 | GCC_PREPROCESSOR_DEFINITIONS = ( 575 | "DEBUG=1", 576 | "$(inherited)", 577 | ); 578 | INFOPLIST_FILE = "ASWeekSelectorViewTests/ASWeekSelectorViewTests-Info.plist"; 579 | PRODUCT_BUNDLE_IDENTIFIER = "net.byadrian.${PRODUCT_NAME:rfc1034identifier}"; 580 | PRODUCT_NAME = "$(TARGET_NAME)"; 581 | TEST_HOST = "$(BUNDLE_LOADER)"; 582 | WRAPPER_EXTENSION = xctest; 583 | }; 584 | name = Debug; 585 | }; 586 | 3AAC016018FE027700EBD85D /* Release */ = { 587 | isa = XCBuildConfiguration; 588 | buildSettings = { 589 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ASWeekSelectorView.app/ASWeekSelectorView"; 590 | DEVELOPMENT_TEAM = 7N3B54ALZK; 591 | FRAMEWORK_SEARCH_PATHS = ( 592 | "$(SDKROOT)/Developer/Library/Frameworks", 593 | "$(inherited)", 594 | "$(DEVELOPER_FRAMEWORKS_DIR)", 595 | ); 596 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 597 | GCC_PREFIX_HEADER = "ASWeekSelectorView/ASWeekSelectorView-Prefix.pch"; 598 | INFOPLIST_FILE = "ASWeekSelectorViewTests/ASWeekSelectorViewTests-Info.plist"; 599 | PRODUCT_BUNDLE_IDENTIFIER = "net.byadrian.${PRODUCT_NAME:rfc1034identifier}"; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | TEST_HOST = "$(BUNDLE_LOADER)"; 602 | WRAPPER_EXTENSION = xctest; 603 | }; 604 | name = Release; 605 | }; 606 | 3AF0FE721D363ADD00859505 /* Debug */ = { 607 | isa = XCBuildConfiguration; 608 | buildSettings = { 609 | CLANG_ANALYZER_NONNULL = YES; 610 | CLANG_WARN_UNREACHABLE_CODE = YES; 611 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 612 | CURRENT_PROJECT_VERSION = 1; 613 | DEBUG_INFORMATION_FORMAT = dwarf; 614 | DEFINES_MODULE = YES; 615 | DYLIB_COMPATIBILITY_VERSION = 1; 616 | DYLIB_CURRENT_VERSION = 1; 617 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 618 | ENABLE_STRICT_OBJC_MSGSEND = YES; 619 | GCC_NO_COMMON_BLOCKS = YES; 620 | INFOPLIST_FILE = ASWeekSelectorView/Info.plist; 621 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 622 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 623 | MTL_ENABLE_DEBUG_INFO = YES; 624 | PRODUCT_BUNDLE_IDENTIFIER = com.buzzhives.ASWeekSelectorView; 625 | PRODUCT_NAME = "$(TARGET_NAME)"; 626 | SKIP_INSTALL = YES; 627 | TARGETED_DEVICE_FAMILY = "1,2"; 628 | VERSIONING_SYSTEM = "apple-generic"; 629 | VERSION_INFO_PREFIX = ""; 630 | }; 631 | name = Debug; 632 | }; 633 | 3AF0FE731D363ADD00859505 /* Release */ = { 634 | isa = XCBuildConfiguration; 635 | buildSettings = { 636 | CLANG_ANALYZER_NONNULL = YES; 637 | CLANG_WARN_UNREACHABLE_CODE = YES; 638 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 639 | COPY_PHASE_STRIP = NO; 640 | CURRENT_PROJECT_VERSION = 1; 641 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 642 | DEFINES_MODULE = YES; 643 | DYLIB_COMPATIBILITY_VERSION = 1; 644 | DYLIB_CURRENT_VERSION = 1; 645 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 646 | ENABLE_STRICT_OBJC_MSGSEND = YES; 647 | GCC_NO_COMMON_BLOCKS = YES; 648 | INFOPLIST_FILE = ASWeekSelectorView/Info.plist; 649 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 650 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 651 | MTL_ENABLE_DEBUG_INFO = NO; 652 | PRODUCT_BUNDLE_IDENTIFIER = com.buzzhives.ASWeekSelectorView; 653 | PRODUCT_NAME = "$(TARGET_NAME)"; 654 | SKIP_INSTALL = YES; 655 | TARGETED_DEVICE_FAMILY = "1,2"; 656 | VERSIONING_SYSTEM = "apple-generic"; 657 | VERSION_INFO_PREFIX = ""; 658 | }; 659 | name = Release; 660 | }; 661 | /* End XCBuildConfiguration section */ 662 | 663 | /* Begin XCConfigurationList section */ 664 | 3AAC012418FE027600EBD85D /* Build configuration list for PBXProject "ASWeekSelectorView" */ = { 665 | isa = XCConfigurationList; 666 | buildConfigurations = ( 667 | 3AAC015918FE027700EBD85D /* Debug */, 668 | 3AAC015A18FE027700EBD85D /* Release */, 669 | ); 670 | defaultConfigurationIsVisible = 0; 671 | defaultConfigurationName = Release; 672 | }; 673 | 3AAC015B18FE027700EBD85D /* Build configuration list for PBXNativeTarget "ASWeekSelectorViewExample" */ = { 674 | isa = XCConfigurationList; 675 | buildConfigurations = ( 676 | 3AAC015C18FE027700EBD85D /* Debug */, 677 | 3AAC015D18FE027700EBD85D /* Release */, 678 | ); 679 | defaultConfigurationIsVisible = 0; 680 | defaultConfigurationName = Release; 681 | }; 682 | 3AAC015E18FE027700EBD85D /* Build configuration list for PBXNativeTarget "ASWeekSelectorViewTests" */ = { 683 | isa = XCConfigurationList; 684 | buildConfigurations = ( 685 | 3AAC015F18FE027700EBD85D /* Debug */, 686 | 3AAC016018FE027700EBD85D /* Release */, 687 | ); 688 | defaultConfigurationIsVisible = 0; 689 | defaultConfigurationName = Release; 690 | }; 691 | 3AF0FE711D363ADD00859505 /* Build configuration list for PBXNativeTarget "ASWeekSelectorView" */ = { 692 | isa = XCConfigurationList; 693 | buildConfigurations = ( 694 | 3AF0FE721D363ADD00859505 /* Debug */, 695 | 3AF0FE731D363ADD00859505 /* Release */, 696 | ); 697 | defaultConfigurationIsVisible = 0; 698 | defaultConfigurationName = Release; 699 | }; 700 | /* End XCConfigurationList section */ 701 | }; 702 | rootObject = 3AAC012118FE027600EBD85D /* Project object */; 703 | } 704 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView.xcodeproj/xcshareddata/xcschemes/ASWeekSelectorView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASAppDelegate.h 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ASAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASAppDelegate.m 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import "ASAppDelegate.h" 10 | 11 | @implementation ASAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // 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. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // 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. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASViewController.h 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ASWeekSelectorView.h" 12 | 13 | @interface ASViewController : UIViewController 14 | 15 | @property (weak, nonatomic) IBOutlet ASWeekSelectorView *weekSelector; 16 | @property (weak, nonatomic) IBOutlet UILabel *label; 17 | 18 | - (IBAction)todayButtonPressed:(id)sender; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASViewController.m: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ASViewController.m 4 | // ASWeekSelectorView 5 | // 6 | // Created by Adrian Schoenig on 16/04/2014. 7 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 8 | // 9 | 10 | #import "ASViewController.h" 11 | 12 | @interface ASViewController () 13 | 14 | @end 15 | 16 | @implementation ASViewController 17 | 18 | - (IBAction)todayButtonPressed:(id)sender 19 | { 20 | NSDate *now = [NSDate date]; 21 | [self.weekSelector setSelectedDate:now animated:YES]; 22 | [self updateLabelForDate:now]; 23 | } 24 | 25 | - (void)updateLabelForDate:(NSDate *)date 26 | { 27 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 28 | dateFormatter.timeStyle = NSDateFormatterNoStyle; 29 | dateFormatter.dateStyle = NSDateFormatterFullStyle; 30 | 31 | self.label.text = [dateFormatter stringFromDate:date]; 32 | } 33 | 34 | #pragma mark - UIViewController 35 | 36 | - (void)viewDidLoad 37 | { 38 | [super viewDidLoad]; 39 | 40 | NSDate *now = [NSDate date]; 41 | [self updateLabelForDate:now]; 42 | 43 | self.weekSelector.firstWeekday = 2; // monday 44 | self.weekSelector.letterTextColor = UIColor.labelColor; 45 | self.weekSelector.numberTextColor = UIColor.labelColor; 46 | self.weekSelector.lineColor = UIColor.separatorColor; 47 | self.weekSelector.delegate = self; 48 | self.weekSelector.selectedDate = now; 49 | } 50 | 51 | - (void)viewWillLayoutSubviews 52 | { 53 | [super viewWillLayoutSubviews]; 54 | 55 | CGRect frame = self.weekSelector.frame; 56 | frame.size.width = CGRectGetWidth(self.view.frame); 57 | self.weekSelector.frame = frame; 58 | } 59 | 60 | #pragma mark - ASWeekSelectorViewDelegate 61 | 62 | - (void)weekSelector:(ASWeekSelectorView *)weekSelector willSelectDate:(NSDate *)date 63 | { 64 | [self updateLabelForDate:date]; 65 | } 66 | 67 | - (UIColor *)weekSelector:(ASWeekSelectorView *)weekSelector numberColorForDate:(NSDate *)date 68 | { 69 | NSCalendar *gregorian = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 70 | NSInteger weekday = [gregorian component:NSCalendarUnitWeekday fromDate:date]; 71 | if (weekday == 1 || weekday == 7) { // Sat or Sun 72 | return UIColor.secondaryLabelColor; 73 | } else { 74 | return nil; 75 | } 76 | } 77 | 78 | - (UIColor *)weekSelector:(ASWeekSelectorView *)weekSelector circleColorForDate:(NSDate *)date 79 | { 80 | NSCalendar *gregorian = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 81 | NSInteger weekday = [gregorian component:NSCalendarUnitWeekday fromDate:date]; 82 | if (weekday == 2) { // Mo 83 | return [UIColor systemGreenColor]; 84 | } else { 85 | return nil; 86 | } 87 | } 88 | 89 | - (BOOL)weekSelector:(ASWeekSelectorView *)weekSelector showIndicatorForDate:(NSDate *)date 90 | { 91 | NSCalendar *gregorian = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 92 | NSInteger weekday = [gregorian component:NSCalendarUnitDay fromDate:date]; 93 | return weekday % 2 == 1; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASWeekSelectorView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Main 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/ASWeekSelectorView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/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 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/ASWeekSelectorView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ASAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ASAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Adrian Schoenig 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of the FreeBSD Project. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ASWeekSelectorView", 8 | defaultLocalization: "en", 9 | platforms: [ 10 | .iOS(.v13) 11 | ], 12 | products: [ 13 | .library( 14 | name: "ASWeekSelectorView", 15 | targets: ["ASWeekSelectorView"] 16 | ), 17 | ], 18 | targets: [ 19 | .target( 20 | name: "ASWeekSelectorView" 21 | ), 22 | ] 23 | ) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `ASWeekSelectorView` 2 | 3 | [![CocoaPod badge w/ platform](http://cocoapod-badges.herokuapp.com/p/ASWeekSelectorView/badge.png)](http://cocoadocs.org/docsets/ASWeekSelectorView) 4 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/nighthawk/ASWeekSelectorView?display_name=tag&label=spm) 5 | [![CocoaPod badge w/ version](http://cocoapod-badges.herokuapp.com/v/ASWeekSelectorView/badge.png)](http://cocoadocs.org/docsets/ASWeekSelectorView) 6 | ![GitHub all releases](https://img.shields.io/github/downloads/nighthawk/ASWeekSelectorView/total) 7 | 8 | A mini week view to select a day. You can swipe through weeks and tap on a day to select them, somewhat similar to the iOS calendar app (since iOS 7). 9 | 10 | It's using the methodology described in Apple's excellent WWDC 2011 session 104 "Advanced ScrollView Techniques". 11 | 12 | ![Week selector](https://github.com/nighthawk/ASWeekSelectorView/raw/main/weekpicker.gif) 13 | 14 | # Setup 15 | 16 | 1) Add to your project. 17 | 18 | Using Swift Package Manager: 19 | 20 | ```swift 21 | .package(url: "https://github.com/nighthawk/ASWeekSelectorView.git", from: "1.0.0") 22 | ``` 23 | 24 | Using Cocoapods: 25 | 26 | ```ruby 27 | pod 'ASWeekSelectorView', '~> 1.0' 28 | ``` 29 | 30 | 2) Add an instance of `ASWeekSelectorView` to your view hierarchy, configure it, provide a delegate and implement the delegate smethod. (Note that you won't need to use `ASDaySelectionView` and `ASSingleWeekView` yourself - they are internal helper class.) 31 | 32 | 3) When using Auto Layout, adjust the frame in `viewWillLayoutSubviews`: 33 | 34 | ```swift 35 | override func viewWillLayoutSubviews() { 36 | super.viewWillLayoutSubviews() 37 | weekSelector.frame.size.width = self.view.frame.width 38 | } 39 | ``` 40 | 41 | ```objective-c 42 | - (void)viewWillLayoutSubviews 43 | { 44 | [super viewWillLayoutSubviews]; 45 | 46 | CGRect frame = self.weekSelector.frame; 47 | frame.size.width = CGRectGetWidth(self.view.frame); 48 | self.weekSelector.frame = frame; 49 | } 50 | ``` 51 | 52 | 53 | # Example 54 | 55 | See the included example project for a very basic implementation. 56 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/ASDaySelectionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASDaySelectionView.h 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 22/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ASDaySelectionView : UIView 12 | 13 | @property (nonatomic, assign) CGPoint circleCenter; 14 | @property (nonatomic, strong, nullable) UIColor *circleColor; 15 | @property (nonatomic, assign) BOOL fillCircle; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/ASDaySelectionView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASDaySelectionView.m 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 22/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import "ASDaySelectionView.h" 10 | 11 | @implementation ASDaySelectionView 12 | 13 | #pragma mark - UIView 14 | 15 | - (void)drawRect:(CGRect)rect 16 | { 17 | CGContextRef context = UIGraphicsGetCurrentContext(); 18 | 19 | // Draw circle. 20 | CGRect circleRect = [self circleRect]; 21 | if (self.fillCircle) { 22 | CGContextSetFillColorWithColor(context, self.circleColor.CGColor); 23 | CGContextFillEllipseInRect(context, circleRect); 24 | } else { 25 | CGContextSetStrokeColorWithColor(context, self.circleColor.CGColor); 26 | CGContextStrokeEllipseInRect(context, circleRect); 27 | } 28 | 29 | } 30 | 31 | #pragma mark - Private helpers 32 | 33 | - (CGRect)circleRect 34 | { 35 | CGFloat diameterFromWidth = CGRectGetWidth(self.frame) * .66; 36 | CGFloat diameterFromHeight = CGRectGetHeight(self.frame) * .5; 37 | 38 | CGFloat diameter = MIN(diameterFromWidth, diameterFromHeight); 39 | CGFloat xOffset = self.circleCenter.x - diameter / 2; 40 | CGFloat yOffset = self.circleCenter.y - diameter / 2; 41 | return CGRectMake(xOffset, yOffset, diameter, diameter); 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/ASSingleWeekView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASSingleWeekView.h 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @protocol ASSingleWeekViewDelegate; 14 | 15 | @interface ASSingleWeekView : UIView 16 | 17 | @property (nonatomic, weak, nullable) id delegate; 18 | 19 | /** 20 | The first date to be shown. 21 | */ 22 | @property (nonatomic, strong, null_resettable) NSDate *startDate; 23 | 24 | @end 25 | 26 | @protocol ASSingleWeekViewDelegate 27 | 28 | - (void)singleWeekView:(ASSingleWeekView *)singleWeekView didSelectDate:(NSDate *)date atFrame:(CGRect)frame; 29 | 30 | - (UIView *)singleWeekView:(ASSingleWeekView *)singleWeekView viewForDate:(NSDate *)date withFrame:(CGRect)frame; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/ASSingleWeekView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASSingleWeekView.m 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 16/04/2014. 6 | // Copyright (c) 2014 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import "ASSingleWeekView.h" 10 | 11 | @interface ASSingleWeekView () 12 | 13 | @property (nonatomic, strong) NSCalendar *gregorian; 14 | 15 | @end 16 | 17 | @implementation ASSingleWeekView 18 | 19 | #pragma mark - Public methods 20 | 21 | - (void)setStartDate:(NSDate *)startDate 22 | { 23 | _startDate = startDate; 24 | 25 | [self rebuildView]; 26 | } 27 | 28 | - (id)initWithFrame:(CGRect)frame 29 | { 30 | self = [super initWithFrame:frame]; 31 | if (self) { 32 | self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 33 | 34 | UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapper:)]; 35 | [self addGestureRecognizer:tapper]; 36 | } 37 | return self; 38 | } 39 | 40 | #pragma mark - User interaction 41 | 42 | - (void)handleTapper:(UITapGestureRecognizer *)tapper 43 | { 44 | CGPoint location = [tapper locationInView:self]; 45 | UIView *subview = [self hitTest:location withEvent:nil]; 46 | NSUInteger dayOffset = subview.tag; 47 | 48 | NSDate *date = [self dateByAddingDays:dayOffset toDate:self.startDate]; 49 | [self.delegate singleWeekView:self didSelectDate:date atFrame:subview.frame]; 50 | } 51 | 52 | #pragma mark - Private helpers 53 | 54 | - (NSDate *)dateByAddingDays:(NSInteger)days toDate:(NSDate *)date 55 | { 56 | if (days == 0) { 57 | return date; 58 | } 59 | 60 | NSDateComponents *components = [[NSDateComponents alloc] init]; 61 | [components setDay:days]; 62 | return [self.gregorian dateByAddingComponents:components toDate:date options:0]; 63 | } 64 | 65 | - (void)rebuildView 66 | { 67 | for (NSInteger index = self.subviews.count - 1; index >= 0; index--) { 68 | UIView *subview = self.subviews[index]; 69 | [subview removeFromSuperview]; 70 | } 71 | CGFloat totalWidth = CGRectGetWidth(self.frame); 72 | CGFloat widthPerItem = totalWidth / 7; 73 | CGFloat itemHeight = CGRectGetHeight(self.frame); 74 | for (NSUInteger dayIndex = 0; dayIndex < 7; dayIndex++) { 75 | NSDate *date = [self dateByAddingDays:dayIndex toDate:self.startDate]; 76 | CGRect frame; 77 | if (self.effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight) { 78 | frame = CGRectMake(dayIndex * widthPerItem, 0, widthPerItem, itemHeight); 79 | } else { 80 | frame = CGRectMake(totalWidth - dayIndex * widthPerItem - widthPerItem, 0, widthPerItem, itemHeight); 81 | } 82 | 83 | 84 | UIView *view = [self.delegate singleWeekView:self 85 | viewForDate:date 86 | withFrame:frame]; 87 | view.tag = dayIndex; 88 | [self addSubview:view]; 89 | } 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/ASWeekSelectorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASWeekSelectorView.m 3 | // TripGo 4 | // 5 | // Created by Adrian Schoenig on 15/04/2014. 6 | // 7 | // 8 | 9 | #if SWIFT_PACKAGE 10 | #import 11 | #else 12 | #import "ASWeekSelectorView.h" 13 | #endif 14 | 15 | #import 16 | 17 | #import "ASSingleWeekView.h" 18 | #import "ASDaySelectionView.h" 19 | 20 | #define WEEKS 3 21 | 22 | 23 | @interface ASContainerView : UIView 24 | @property (nonatomic, assign, getter = isAccessibilityElement) BOOL accessibilityElement; 25 | @end 26 | @implementation ASContainerView 27 | @end 28 | 29 | @interface ASWeekSelectorView () 30 | 31 | @property (nonatomic, weak) UIScrollView *scrollView; 32 | @property (nonatomic, strong) NSMutableArray *singleWeekViews; 33 | @property (nonatomic, weak) ASDaySelectionView *selectionView; 34 | @property (nonatomic, strong) ASDaySelectionView *todayView; 35 | 36 | // for animating the selection view 37 | @property (nonatomic, assign) CGFloat preDragSelectionX; 38 | @property (nonatomic, assign) CGFloat preDragOffsetX; 39 | @property (nonatomic, assign) BOOL isAnimating; 40 | @property (nonatomic, assign) BOOL isSettingFrame; 41 | 42 | @property (nonatomic, strong) NSDateFormatter *dayNameDateFormatter; 43 | @property (nonatomic, strong) NSDateFormatter *dayNumberDateFormatter; 44 | @property (nonatomic, strong) NSDateFormatter *accessibilityDateFormatter; 45 | @property (nonatomic, strong) NSCalendar *gregorian; 46 | @property (nonatomic, strong) NSDate *lastToday; // to check when we need to update our 'today' time stamp 47 | 48 | // formatting 49 | @property (nonatomic, strong) UIColor *selectorLetterTextColor; 50 | 51 | @end 52 | 53 | @implementation ASWeekSelectorView 54 | 55 | #pragma mark - Public methods 56 | 57 | - (void)setFirstWeekday:(NSUInteger)firstWeekday 58 | { 59 | _firstWeekday = firstWeekday; 60 | 61 | [self rebuildWeeks]; 62 | } 63 | 64 | - (void)setSelectedDate:(NSDate *)selectedDate 65 | { 66 | [self setSelectedDate:selectedDate animated:NO]; 67 | } 68 | 69 | - (void)setSelectedDate:(NSDate *)selectedDate animated:(BOOL)animated 70 | { 71 | if (!self.lastToday || ![self date:self.lastToday matchesDateComponentsOfDate:[NSDate date]]) { 72 | [self rebuildWeeks]; 73 | } 74 | 75 | if (! [self date:selectedDate matchesDateComponentsOfDate:_selectedDate]) { 76 | UIColor *numberTextColor = [self numberTextColorForDate:_selectedDate]; 77 | [self colorLabelForDate:_selectedDate withTextColor:numberTextColor]; 78 | _selectedDate = selectedDate; 79 | self.isAnimating = animated; 80 | 81 | [UIView animateWithDuration:animated ? 0.25f : 0 82 | animations: 83 | ^{ 84 | [self rebuildWeeks]; 85 | } 86 | completion: 87 | ^(BOOL finished) { 88 | self.isAnimating = NO; 89 | if (finished) { 90 | [self colorLabelForDate:selectedDate withTextColor:self.selectorLetterTextColor]; 91 | } 92 | }]; 93 | } 94 | } 95 | 96 | - (void)setLocale:(NSLocale *)locale 97 | { 98 | _locale = locale; 99 | [self updateDateFormatters]; 100 | } 101 | 102 | - (void)refresh 103 | { 104 | [self rebuildWeeks]; 105 | } 106 | 107 | #pragma mark - UIView 108 | 109 | - (id)initWithFrame:(CGRect)frame 110 | { 111 | self = [super initWithFrame:frame]; 112 | if (self) { 113 | [self didInit:YES]; 114 | } 115 | return self; 116 | } 117 | 118 | - (id)initWithCoder:(NSCoder *)aDecoder 119 | { 120 | self = [super initWithCoder:aDecoder]; 121 | if (self) { 122 | [self didInit:YES]; 123 | } 124 | return self; 125 | } 126 | 127 | - (void)setFrame:(CGRect)frame 128 | { 129 | self.isSettingFrame = YES; 130 | BOOL didChange = !CGRectEqualToRect(frame, self.frame); 131 | 132 | [super setFrame:frame]; 133 | 134 | if (didChange) { 135 | _selectionView = nil; 136 | _todayView = nil; 137 | for (UIView *view in [self subviews]) { 138 | [view removeFromSuperview]; 139 | } 140 | [self didInit:NO]; 141 | } 142 | self.isSettingFrame = NO; 143 | } 144 | 145 | - (void)setTintColor:(UIColor *)tintColor 146 | { 147 | [super setTintColor:tintColor]; 148 | 149 | self.selectionView.circleColor = self.tintColor; 150 | self.todayView.circleColor = self.tintColor; 151 | } 152 | 153 | - (void)setLetterFont:(UIFont *)letterFont 154 | { 155 | _letterFont = letterFont; 156 | [self rebuildWeeks]; 157 | } 158 | 159 | #pragma mark - UIScrollViewDelegate 160 | 161 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 162 | { 163 | if (self.preDragOffsetX == MAXFLOAT) { 164 | self.preDragOffsetX = scrollView.contentOffset.x; 165 | self.preDragSelectionX = CGRectGetMinX(self.selectionView.frame); 166 | } 167 | } 168 | 169 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 170 | { 171 | if (self.singleWeekViews.count <= 0 || self.isSettingFrame) { 172 | return; // not ready yet 173 | } 174 | 175 | CGPoint offset = scrollView.contentOffset; 176 | BOOL updatedOffset = NO; 177 | 178 | // place the selection views 179 | if (self.preDragOffsetX < MAXFLOAT) { 180 | CGFloat selectionX = self.preDragSelectionX - (offset.x - self.preDragOffsetX); 181 | 182 | CGRect selectionViewFrame = self.selectionView.frame; 183 | selectionViewFrame.origin.x = selectionX; 184 | self.selectionView.frame = selectionViewFrame; 185 | } 186 | 187 | // prevent horizontal scrolling 188 | if (fabs(offset.y) > 0.01) { 189 | offset.y = 0; 190 | updatedOffset = YES; 191 | } 192 | 193 | CGFloat width = CGRectGetWidth(scrollView.frame); 194 | if (offset.x >= width * 2 || offset.x <= 0) { 195 | // swap things around 196 | ASSingleWeekView *week0 = self.singleWeekViews[0]; 197 | ASSingleWeekView *week1 = self.singleWeekViews[1]; 198 | ASSingleWeekView *week2 = self.singleWeekViews[2]; 199 | CGRect leftFrame = week0.frame; 200 | CGRect middleFrame = week1.frame; 201 | CGRect rightFrame = week2.frame; 202 | NSInteger multiplier = self.effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight ? 1 : -1; 203 | 204 | if (offset.x <= 0) { 205 | // 0 and 1 move right 206 | week0.frame = middleFrame; 207 | week1.frame = rightFrame; 208 | self.singleWeekViews[1] = week0; 209 | self.singleWeekViews[2] = week1; 210 | 211 | // 2 get's updated to -1 212 | week2.startDate = [self dateByAddingDays:-7*multiplier toDate:week0.startDate]; 213 | week2.frame = leftFrame; 214 | self.singleWeekViews[0] = week2; 215 | 216 | if ([self.delegate respondsToSelector:@selector(weekSelectorDidSwipe:)]) { 217 | [self.delegate weekSelectorDidSwipe:self]; 218 | } 219 | NSDate *date = [self dateByAddingDays:-7*multiplier toDate:self.selectedDate]; 220 | [self userWillSelectDate:date]; 221 | [self userDidSelectDate:date]; 222 | 223 | } else { 224 | // 1 and 2 move to the left 225 | week1.frame = leftFrame; 226 | week2.frame = middleFrame; 227 | self.singleWeekViews[0] = week1; 228 | self.singleWeekViews[1] = week2; 229 | 230 | // 0 get's updated to 3 231 | week0.startDate = [self dateByAddingDays:7*multiplier toDate:week2.startDate]; 232 | week0.frame = rightFrame; 233 | self.singleWeekViews[2] = week0; 234 | 235 | if ([self.delegate respondsToSelector:@selector(weekSelectorDidSwipe:)]) { 236 | [self.delegate weekSelectorDidSwipe:self]; 237 | } 238 | NSDate *date = [self dateByAddingDays:7*multiplier toDate:self.selectedDate]; 239 | [self userWillSelectDate:date]; 240 | [self userDidSelectDate:date]; 241 | } 242 | 243 | // reset offset 244 | offset.x = width; 245 | updatedOffset = YES; 246 | } 247 | 248 | if (updatedOffset) { 249 | scrollView.contentOffset = offset; 250 | } 251 | } 252 | 253 | - (NSString *)accessibilityScrollStatusForScrollView:(UIScrollView *)scrollView 254 | { 255 | NSString *format = NSLocalizedStringFromTable(@"Week of %@", @"ASWeekSelectorView", @"Accessibility description when paging through weeks. Supplied %@ is string for the start date."); 256 | NSDate *startDate = [self.singleWeekViews[1] startDate]; 257 | return [NSString stringWithFormat:format, [self.accessibilityDateFormatter stringFromDate:startDate]]; 258 | } 259 | 260 | 261 | #pragma mark - ASSingleWeekViewDelegate 262 | 263 | - (UIView *)singleWeekView:(ASSingleWeekView *)singleWeekView viewForDate:(NSDate *)date withFrame:(CGRect)frame 264 | { 265 | BOOL isSelection = [self date:date matchesDateComponentsOfDate:self.selectedDate]; 266 | if (isSelection) { 267 | self.selectionView.frame = frame; 268 | } 269 | 270 | NSDate *today = [NSDate date]; 271 | BOOL isToday = [self date:date matchesDateComponentsOfDate:today]; 272 | if (isToday) { 273 | self.todayView.frame = frame; 274 | [singleWeekView insertSubview:self.todayView atIndex:0]; 275 | self.lastToday = today; 276 | } 277 | 278 | ASContainerView *wrapper = [[ASContainerView alloc] initWithFrame:frame]; 279 | CGFloat width = CGRectGetWidth(frame); 280 | 281 | CGFloat nameHeight = 20; 282 | CGFloat topPadding = 8; 283 | CGRect nameFrame = CGRectMake(0, topPadding, width, nameHeight - topPadding); 284 | UILabel *letterLabel = [[UILabel alloc] initWithFrame:nameFrame]; 285 | letterLabel.textAlignment = NSTextAlignmentCenter; 286 | letterLabel.font = self.letterFont; 287 | letterLabel.textColor = self.letterTextColor; 288 | letterLabel.text = [[self.dayNameDateFormatter stringFromDate:date] uppercaseString]; 289 | [wrapper addSubview:letterLabel]; 290 | 291 | NSString *dayNumberText = [self.dayNumberDateFormatter stringFromDate:date]; 292 | CGRect numberFrame = CGRectMake(0, nameHeight, width, CGRectGetHeight(frame) - nameHeight); 293 | UILabel *numberLabel = [[UILabel alloc] initWithFrame:numberFrame]; 294 | numberLabel.textAlignment = NSTextAlignmentCenter; 295 | numberLabel.font = [UIFont systemFontOfSize:18]; 296 | if (isSelection && ! self.isAnimating) { 297 | numberLabel.textColor = self.selectorLetterTextColor; 298 | } else { 299 | numberLabel.textColor = [self numberTextColorForDate:date]; 300 | } 301 | numberLabel.text = dayNumberText; 302 | numberLabel.tag = 100 + [dayNumberText integerValue]; 303 | [wrapper addSubview:numberLabel]; 304 | 305 | if ([self.delegate respondsToSelector:@selector(weekSelector:circleColorForDate:)]) { 306 | UIColor *color = [self.delegate weekSelector:self circleColorForDate:date]; 307 | if (color) { 308 | ASDaySelectionView *view = [self eventDayView]; 309 | view.circleColor = color; 310 | [wrapper insertSubview:view atIndex:0]; 311 | } 312 | } 313 | 314 | if ([self.delegate respondsToSelector:@selector(weekSelector:showIndicatorForDate:)]) { 315 | if ([self.delegate weekSelector:self showIndicatorForDate:date]) { 316 | CGFloat radius = 3; 317 | CGRect indicatorFrame = CGRectMake((width - radius) / 2, CGRectGetMaxY(numberFrame) - 7 - radius, radius, radius); 318 | UIView *view = [[UIView alloc] initWithFrame:indicatorFrame]; 319 | view.backgroundColor = numberLabel.textColor; 320 | view.layer.cornerRadius = radius / 2; 321 | view.tag = 200 + [dayNumberText integerValue]; 322 | [wrapper addSubview:view]; 323 | } 324 | } 325 | 326 | wrapper.accessibilityElement = YES; 327 | wrapper.accessibilityLabel = [self.accessibilityDateFormatter stringFromDate:date]; 328 | wrapper.accessibilityTraits = isSelection ? (UIAccessibilityTraitButton | UIAccessibilityTraitSelected) : UIAccessibilityTraitButton; 329 | return wrapper; 330 | } 331 | 332 | - (void)singleWeekView:(ASSingleWeekView *)singleWeekView didSelectDate:(NSDate *)date atFrame:(CGRect)frame 333 | { 334 | [self userWillSelectDate:date]; 335 | 336 | UIColor *numberTextColor = [self numberTextColorForDate:_selectedDate]; 337 | [self colorLabelForDate:_selectedDate withTextColor:numberTextColor]; 338 | 339 | [UIView animateWithDuration:0.25f 340 | animations: 341 | ^{ 342 | self.selectionView.frame = frame; 343 | } 344 | completion: 345 | ^(BOOL finished) { 346 | if (finished) { 347 | [self userDidSelectDate:date]; 348 | } 349 | }]; 350 | } 351 | 352 | #pragma mark - Private helpers 353 | 354 | - (void)didInit:(BOOL)setDefaults 355 | { 356 | self.clipsToBounds = YES; 357 | 358 | if (setDefaults) { 359 | // default styles 360 | _letterFont = [UIFont systemFontOfSize:9]; 361 | _letterTextColor = [UIColor colorWithWhite:204.f/255 alpha:1]; 362 | _numberTextColor = [UIColor colorWithWhite:77.f/255 alpha:1]; 363 | _selectorLetterTextColor = self.backgroundColor; 364 | _preDragOffsetX = MAXFLOAT; 365 | _preDragSelectionX = MAXFLOAT; 366 | _locale = [NSLocale autoupdatingCurrentLocale]; 367 | 368 | // this is using variables directly to not trigger setter methods 369 | _selectedDate = [NSDate date]; 370 | _singleWeekViews = [NSMutableArray arrayWithCapacity:WEEKS]; 371 | _firstWeekday = 1; // sunday 372 | _gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 373 | } 374 | CGFloat width = CGRectGetWidth(self.frame); 375 | CGFloat height = CGRectGetHeight(self.frame); 376 | CGRect scrollViewFrame = CGRectMake(0, 0, width, height - 1); 377 | UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame]; 378 | scrollView.contentSize = CGSizeMake(WEEKS * width, height); 379 | scrollView.contentOffset = CGPointMake(width, 0); 380 | scrollView.pagingEnabled = YES; 381 | scrollView.delegate = self; 382 | scrollView.showsVerticalScrollIndicator = NO; 383 | scrollView.showsHorizontalScrollIndicator = NO; 384 | scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth; 385 | [self addSubview:scrollView]; 386 | self.scrollView = scrollView; 387 | 388 | [self updateDateFormatters]; 389 | } 390 | 391 | - (void)updateDateFormatters 392 | { 393 | self.dayNumberDateFormatter = [[NSDateFormatter alloc] init]; 394 | self.dayNumberDateFormatter.locale = self.locale; 395 | self.dayNumberDateFormatter.dateFormat = @"d"; 396 | self.dayNameDateFormatter = [[NSDateFormatter alloc] init]; 397 | self.dayNameDateFormatter.locale = self.locale; 398 | self.dayNameDateFormatter.dateFormat = [NSDateFormatter dateFormatFromTemplate:@"E" 399 | options:0 400 | locale:self.locale]; 401 | 402 | self.accessibilityDateFormatter = [[NSDateFormatter alloc] init]; 403 | self.accessibilityDateFormatter.locale = self.locale; 404 | self.accessibilityDateFormatter.dateStyle = NSDateFormatterFullStyle; 405 | self.accessibilityDateFormatter.timeStyle = NSDateFormatterNoStyle; 406 | [self rebuildWeeks]; 407 | } 408 | 409 | - (void)rebuildWeeks 410 | { 411 | if (! self.selectedDate) { 412 | return; 413 | } 414 | 415 | if (self.singleWeekViews.count > 0) { 416 | for (UIView *view in self.singleWeekViews) { 417 | [view removeFromSuperview]; 418 | } 419 | [self.singleWeekViews removeAllObjects]; 420 | } 421 | 422 | // determine where the start of the previews week was as that'll be our start date 423 | NSDateComponents *component = [self.gregorian components:NSCalendarUnitWeekday fromDate:self.selectedDate]; 424 | NSUInteger weekday = (NSUInteger) [component weekday]; 425 | NSInteger daysToSubtract; 426 | if (weekday == self.firstWeekday) { 427 | daysToSubtract = 0; 428 | } else if (weekday > self.firstWeekday) { 429 | daysToSubtract = weekday - self.firstWeekday; 430 | } else { 431 | daysToSubtract = (weekday + 7) - self.firstWeekday; 432 | } 433 | daysToSubtract += 7; 434 | 435 | NSDate *date = [self dateByAddingDays:- daysToSubtract toDate:self.selectedDate]; 436 | 437 | CGFloat width = CGRectGetWidth(self.frame); 438 | CGFloat height = CGRectGetHeight(self.frame); 439 | 440 | // now we can build the #WEEKS subvies 441 | for (NSUInteger index = 0; index < WEEKS; index++) { 442 | NSUInteger effectiveIndex = self.effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight ? index : WEEKS - index - 1; 443 | CGRect frame = CGRectMake(effectiveIndex * width, 0, width, height); 444 | ASSingleWeekView *singleView = [[ASSingleWeekView alloc] initWithFrame:frame]; 445 | singleView.delegate = self; 446 | singleView.startDate = date; // needs to be set AFTER delegate 447 | 448 | [self.scrollView addSubview:singleView]; 449 | [self.singleWeekViews addObject:singleView]; 450 | 451 | // next week 452 | date = [self dateByAddingDays:7 toDate:date]; 453 | } 454 | } 455 | 456 | - (NSDate *)dateByAddingDays:(NSInteger)days toDate:(NSDate *)date 457 | { 458 | NSDateComponents *diff = [[NSDateComponents alloc] init]; 459 | diff.day = days; 460 | return [self.gregorian dateByAddingComponents:diff toDate:date options:0]; 461 | } 462 | 463 | - (BOOL)date:(NSDate *)date matchesDateComponentsOfDate:(NSDate *)otherDate 464 | { 465 | if (date == otherDate) { 466 | return YES; 467 | } 468 | if (! date || ! otherDate) { 469 | return NO; 470 | } 471 | 472 | NSUInteger unitFlags = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear; 473 | 474 | NSDateComponents *components = [self.gregorian components:unitFlags fromDate:date]; 475 | NSDateComponents *otherComponents = [self.gregorian components:unitFlags fromDate:otherDate]; 476 | return [components isEqual:otherComponents]; 477 | } 478 | 479 | - (void)userWillSelectDate:(NSDate *)date 480 | { 481 | if ([self.delegate respondsToSelector:@selector(weekSelector:willSelectDate:)]) { 482 | [self.delegate weekSelector:self willSelectDate:date]; 483 | } 484 | } 485 | 486 | 487 | - (void)userDidSelectDate:(NSDate *)date 488 | { 489 | UIColor *numberTextColor = [self numberTextColorForDate:_selectedDate]; 490 | [self colorLabelForDate:_selectedDate withTextColor:numberTextColor]; 491 | _selectedDate = date; 492 | 493 | [self animateSelectionToPreDrag]; 494 | 495 | if ([self.delegate respondsToSelector:@selector(weekSelector:didSelectDate:)]) { 496 | [self.delegate weekSelector:self didSelectDate:date]; 497 | } 498 | } 499 | 500 | - (void)animateSelectionToPreDrag 501 | { 502 | if (self.preDragOffsetX < MAXFLOAT) { 503 | CGFloat selectionX = self.preDragSelectionX; 504 | 505 | CGRect selectionViewFrame = self.selectionView.frame; 506 | selectionViewFrame.origin.x = selectionX; 507 | 508 | [UIView animateWithDuration:0.25f 509 | animations: 510 | ^{ 511 | self.selectionView.frame = selectionViewFrame; 512 | } completion:^(BOOL finished) { 513 | if (finished) { 514 | [self colorLabelForDate:self.selectedDate withTextColor:self.selectorLetterTextColor]; 515 | } 516 | }]; 517 | 518 | self.preDragOffsetX = MAXFLOAT; 519 | } else { 520 | [self colorLabelForDate:_selectedDate withTextColor:self.selectorLetterTextColor]; 521 | } 522 | } 523 | 524 | - (UIColor *)numberTextColorForDate:(NSDate *)date { 525 | if (date && [self.delegate respondsToSelector:@selector(weekSelector:numberColorForDate:)]) { 526 | return [self.delegate weekSelector:self numberColorForDate:date] ?: self.numberTextColor; 527 | } else { 528 | return self.numberTextColor; 529 | } 530 | } 531 | 532 | - (void)colorLabelForDate:(NSDate *)date withTextColor:(UIColor *)textColor 533 | { 534 | NSString *dayNumberText = [self.dayNumberDateFormatter stringFromDate:date]; 535 | NSInteger labelTag = 100 + [dayNumberText integerValue]; 536 | NSInteger indicatorTag = 200 + [dayNumberText integerValue]; 537 | for (ASSingleWeekView *singleWeek in self.singleWeekViews) { 538 | UIView *view = [singleWeek viewWithTag:indicatorTag]; 539 | view.backgroundColor = textColor; 540 | 541 | view = [singleWeek viewWithTag:labelTag]; 542 | if ([view isKindOfClass:[UILabel class]]) { 543 | UILabel *label = (UILabel *)view; 544 | label.textColor = textColor; 545 | return; 546 | } 547 | } 548 | } 549 | 550 | #pragma mark - Lazy accessors 551 | 552 | - (ASDaySelectionView *)selectionView 553 | { 554 | if (! _selectionView) { 555 | CGFloat width = ceil(CGRectGetWidth(self.frame) / 7); 556 | CGFloat height = CGRectGetHeight(self.frame); 557 | 558 | ASDaySelectionView *view = [[ASDaySelectionView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 559 | view.backgroundColor = [UIColor clearColor]; 560 | view.fillCircle = YES; 561 | view.circleCenter = CGPointMake(width / 2, 20 + (height - 20) / 2); 562 | view.circleColor = self.tintColor; 563 | view.userInteractionEnabled = NO; 564 | [self insertSubview:view atIndex:0]; 565 | _selectionView = view; 566 | } 567 | return _selectionView; 568 | } 569 | 570 | - (ASDaySelectionView *)todayView 571 | { 572 | if (! _todayView) { 573 | CGFloat width = ceil(CGRectGetWidth(self.frame) / 7); 574 | CGFloat height = CGRectGetHeight(self.frame); 575 | 576 | ASDaySelectionView *view = [[ASDaySelectionView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 577 | view.backgroundColor = [UIColor clearColor]; 578 | view.fillCircle = NO; 579 | view.circleCenter = CGPointMake(width / 2, 20 + (height - 20) / 2); 580 | view.circleColor = self.tintColor; 581 | view.userInteractionEnabled = NO; 582 | _todayView = view; 583 | } 584 | return _todayView; 585 | } 586 | 587 | -(ASDaySelectionView *)eventDayView 588 | { 589 | CGFloat width = ceil(CGRectGetWidth(self.frame) / 7); 590 | CGFloat height = CGRectGetHeight(self.frame); 591 | ASDaySelectionView *view = [[ASDaySelectionView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; 592 | view.backgroundColor = [UIColor clearColor]; 593 | view.fillCircle = NO; 594 | view.circleCenter = CGPointMake(width / 2, 20 + (height - 20) / 2); 595 | view.circleColor = [UIColor redColor]; 596 | view.userInteractionEnabled = NO; 597 | return view; 598 | } 599 | @end 600 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/ar.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "الأسبوع %@"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/de.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "Woche von %@"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/en.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "Week of %@"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/es.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "Semana de %@"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/it.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "Settimana di %@"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/Resources/ja.lproj/ASWeekSelectorView.strings: -------------------------------------------------------------------------------- 1 | /* Accessibility description when paging through weeks. Supplied %@ is string for the start date. */ 2 | "Week of %@" = "%@ の週"; 3 | 4 | -------------------------------------------------------------------------------- /Sources/ASWeekSelectorView/include/ASWeekSelectorView/ASWeekSelectorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASWeekSelectorView.h 3 | // ASWeekSelectorView 4 | // 5 | // Created by Adrian Schoenig on 15/04/2014. 6 | // Copyright © 2016 Adrian Schoenig. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ASWeekSelectorView. 12 | FOUNDATION_EXPORT double ASWeekSelectorViewVersionNumber; 13 | 14 | //! Project version string for ASWeekSelectorView. 15 | FOUNDATION_EXPORT const unsigned char ASWeekSelectorViewVersionString[]; 16 | 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @protocol ASWeekSelectorViewDelegate; 21 | 22 | /** 23 | A mini week view to select a day. You can swipe through weeks and tap on days to select them, somewhat similar to the iOS 7 calendar app. 24 | 25 | It's using the methodology described in Apple's WWDC 2011 session 104 "Advanced ScrollView Techniques". 26 | */ 27 | @interface ASWeekSelectorView : UIView 28 | 29 | /** 30 | The delegate conforming to the `ASWeekSelectorViewDelegate` delegate. 31 | */ 32 | @property (nonatomic, weak, nullable) id delegate; 33 | 34 | /** 35 | Index of the first day of the week, same as used by `NSCalendar`. 36 | @default 1, i.e., Sunday 37 | */ 38 | @property (nonatomic, assign) NSUInteger firstWeekday; 39 | 40 | /** 41 | Text color of the big numbers 42 | */ 43 | @property (nonatomic, strong) UIColor *numberTextColor; 44 | 45 | /** 46 | Text color of the small letter labels 47 | */ 48 | @property (nonatomic, strong) UIColor *letterTextColor; 49 | 50 | /** 51 | Text color of the small letter labels 52 | */ 53 | @property (nonatomic, strong) UIFont *letterFont; 54 | 55 | /** 56 | Locale used for formatting dates 57 | @default `autoupdatingCurrentLocale` 58 | */ 59 | @property (nonatomic, strong) NSLocale *locale; 60 | 61 | /** 62 | The selected date which is highlighted in the view. When setting this property, the view will also jump to show that date. 63 | */ 64 | @property (nonatomic, strong) NSDate *selectedDate; 65 | 66 | /** 67 | @param selectedDate The date to be selected and shown. 68 | @param animated Selection should be animated. 69 | */ 70 | - (void)setSelectedDate:(NSDate *)selectedDate animated:(BOOL)animated; 71 | 72 | /** 73 | Triggers a refresh of the week view, which calls again the delegate methods 74 | for configuring colours and the indicators. Call this if your underlying 75 | data has changed and you need those valus refreshed. 76 | */ 77 | - (void)refresh; 78 | 79 | @end 80 | 81 | @protocol ASWeekSelectorViewDelegate 82 | 83 | @optional 84 | 85 | /** 86 | Called on the delegate whenever the user interacts with the view and selects a new date. Called immediately after selection commenced. 87 | 88 | @param weekSelector The week selector that the user interacted with. 89 | @param date The selected date. 90 | */ 91 | - (void)weekSelector:(ASWeekSelectorView *)weekSelector willSelectDate:(NSDate *)date; 92 | 93 | /** 94 | Called on the delegate whenever the user interacts with the view and selects a new date. Called after any animations are completed. 95 | 96 | @param weekSelector The week selector that the user interacted with. 97 | @param date The selected date. 98 | */ 99 | - (void)weekSelector:(ASWeekSelectorView *)weekSelector didSelectDate:(NSDate *)date; 100 | 101 | /** 102 | Called when the user did actively swipe to a new week. 103 | 104 | @note `weekSelector:selectedDate:` will also be called right after this. 105 | 106 | @param weekSelector The week selector that the user interacted with. 107 | */ 108 | - (void)weekSelectorDidSwipe:(ASWeekSelectorView *)weekSelector; 109 | 110 | /** 111 | Implement to draw a circle (stroke only) around the specified date. 112 | @param date Date for which to customise color (not called for selected date) 113 | @return Color of the highlighter circle, or `nil` if no circle 114 | */ 115 | - (nullable UIColor *)weekSelector:(ASWeekSelectorView *)weekSelector circleColorForDate:(NSDate *)date; 116 | 117 | /** 118 | Implement to change the color of the number for the specified date. 119 | @param date Date for which to customise color (not called for selected date) 120 | @return Color of number label, or `nil` to use default `numberTextColor` 121 | */ 122 | - (nullable UIColor *)weekSelector:(ASWeekSelectorView *)weekSelector numberColorForDate:(NSDate *)date; 123 | 124 | /** 125 | Implement to allow showing a dot below the number for the specified date. 126 | @param date Date for which to show a dot (or not) 127 | @return Whether an indicator dot should be shown 128 | */ 129 | - (BOOL)weekSelector:(ASWeekSelectorView *)weekSelector showIndicatorForDate:(NSDate *)date; 130 | 131 | @end 132 | 133 | NS_ASSUME_NONNULL_END 134 | -------------------------------------------------------------------------------- /weekpicker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nighthawk/ASWeekSelectorView/8986a5c52bd9fc9f72493395a6a06f2eea914f65/weekpicker.gif --------------------------------------------------------------------------------