├── .gitignore ├── .swift-version ├── .travis.yml ├── Cartfile ├── Carthage └── Build │ └── iOS │ └── JKInfinitePageView.framework │ ├── Headers │ └── JKInfinitePageView-Swift.h │ ├── Info.plist │ ├── JKInfinitePageView │ └── Modules │ ├── JKInfinitePageView.swiftmodule │ ├── arm.swiftdoc │ ├── arm.swiftmodule │ ├── arm64.swiftdoc │ ├── arm64.swiftmodule │ ├── i386.swiftdoc │ ├── i386.swiftmodule │ ├── x86_64.swiftdoc │ └── x86_64.swiftmodule │ └── module.modulemap ├── Example ├── Cartfile ├── JKCalendar-Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── JKCalendar-Example │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── JKCalendar_icon.png │ │ ├── Contents.json │ │ ├── ic_back.imageset │ │ │ ├── Contents.json │ │ │ ├── nb_btn_back.png │ │ │ ├── nb_btn_back@2x.png │ │ │ └── nb_btn_back@3x.png │ │ ├── ic_down.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_down.png │ │ │ ├── ic_down@2x.png │ │ │ └── ic_down@3x.png │ │ ├── ic_up.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_up.png │ │ │ ├── ic_up@2x.png │ │ │ └── ic_up@3x.png │ │ └── logo.imageset │ │ │ ├── Contents.json │ │ │ ├── logo.png │ │ │ ├── logo@2x.png │ │ │ └── logo@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ScrollViewController.swift │ ├── SelectorViewController.swift │ └── TableViewController.swift └── Podfile ├── JKCalendar.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── JKCalendar.xcscheme ├── LICENSE ├── README.md ├── Resources ├── banner.png ├── mark_type_continuous.png ├── mark_type_single.png ├── page_video.gif └── scroll_video.gif └── Sources ├── Info.plist ├── JKCalendar.h ├── JKCalendar.swift ├── JKCalendar.xib ├── JKCalendarMark.swift ├── JKCalendarScrollView.swift ├── JKCalendarTableView.swift ├── JKCalendarView.swift ├── common.swift └── icon.xcassets ├── Contents.json ├── ic_arrow_left.imageset ├── Contents.json ├── arrow_left.png ├── arrow_left@2x.png └── arrow_left@3x.png └── ic_arrow_right.imageset ├── Contents.json ├── arrow_right.png ├── arrow_right@2x.png └── arrow_right@3x.png /.gitignore: -------------------------------------------------------------------------------- 1 | *xcuserdata 2 | *podspec 3 | *ai 4 | *zip 5 | Pods/ 6 | 7 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.2 -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: swift 2 | osx_image: xcode9.2 3 | xcode_project: JKCalendar.xcodeproj 4 | xcode_scheme: JKCalendar 5 | xcode_sdk: iphonesimulator11.2 6 | env: 7 | global: 8 | - FRAMEWORK_NAME=JKCalendar 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 | deploy: 16 | provider: releases 17 | api_key: 18 | secure: tRJxyexjrTpSdnsxPqtUrq+gQDwQwsCrj5F6uFw/XgKlWu+ETj0RI4iBrOSDnrOq8eEIb6hJaA2vmzfMvPy1PWr3ABIP8z8I8jFGzMC2WUU0a1E+lkC+/nzPcYvFYvru6J/dg/xruGzPI08fRv6qDbBUV6YHf/uXee3Hs9NDyzykVE+VR+HX0uXlto06QtaJMBNTLdJzf7NgMQhDhTltySo35gc3AE2cPTNbLTbNCP8bYIUOUfSk2+GPKMB3xd/wvdAUKs7SRdIizQI/tNFGMuLFIrNBxHKZ1R5AOVKLOvnoVRTJsqrDlFNXjEPc8GlGlFKEAmIyrYEOXQ/enSK5mPmjF+8/bJ8wRf0er+tUc4TS9ntQrLn98L/V0KJANah3ayZDVFrhwyopkipaOIM6SbqsmmYIt9pZU2Uj3MBci9h1PSwmWb333vjO60wGZOlx1K8y6LMjvlEzB73Vi9iGrohpvw1drqOrFdts1Y5HnrqTAthVRPHuAxYfn5lfHP/QkcUhRvGOWSYDMBXTG24sKErTf4cJPyF5YE0kCu/iBbKAPSAT33ao3nngasrpW3Le0YOhK/SmO8iqaqhqkE6LnvXbOta63n7wKyDfhdW1BLgn60wqv7Zk9Mlhhx2lPXAwNIlTEiTMsxO3AqoWDrFpyiXFSupZDaeTN48WDrSjKeg= 19 | file: JKCalendar.framework.zip 20 | on: 21 | repo: JoeCiou/JKCalendar 22 | 23 | 24 | deploy: 25 | skip_cleanup: true 26 | on: 27 | repo: repo/repo 28 | tags: true -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "JoeCiou/JKInfinitePageView" ~> 1.1.0 -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Headers/JKInfinitePageView-Swift.h: -------------------------------------------------------------------------------- 1 | #if 0 2 | #elif defined(__arm64__) && __arm64__ 3 | // Generated by Apple Swift version 5.0 effective-4.2 (swiftlang-1001.0.69.5 clang-1001.0.46.3) 4 | #pragma clang diagnostic push 5 | #pragma clang diagnostic ignored "-Wgcc-compat" 6 | 7 | #if !defined(__has_include) 8 | # define __has_include(x) 0 9 | #endif 10 | #if !defined(__has_attribute) 11 | # define __has_attribute(x) 0 12 | #endif 13 | #if !defined(__has_feature) 14 | # define __has_feature(x) 0 15 | #endif 16 | #if !defined(__has_warning) 17 | # define __has_warning(x) 0 18 | #endif 19 | 20 | #if __has_include() 21 | # include 22 | #endif 23 | 24 | #pragma clang diagnostic ignored "-Wauto-import" 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #if !defined(SWIFT_TYPEDEFS) 31 | # define SWIFT_TYPEDEFS 1 32 | # if __has_include() 33 | # include 34 | # elif !defined(__cplusplus) 35 | typedef uint_least16_t char16_t; 36 | typedef uint_least32_t char32_t; 37 | # endif 38 | typedef float swift_float2 __attribute__((__ext_vector_type__(2))); 39 | typedef float swift_float3 __attribute__((__ext_vector_type__(3))); 40 | typedef float swift_float4 __attribute__((__ext_vector_type__(4))); 41 | typedef double swift_double2 __attribute__((__ext_vector_type__(2))); 42 | typedef double swift_double3 __attribute__((__ext_vector_type__(3))); 43 | typedef double swift_double4 __attribute__((__ext_vector_type__(4))); 44 | typedef int swift_int2 __attribute__((__ext_vector_type__(2))); 45 | typedef int swift_int3 __attribute__((__ext_vector_type__(3))); 46 | typedef int swift_int4 __attribute__((__ext_vector_type__(4))); 47 | typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); 48 | typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); 49 | typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); 50 | #endif 51 | 52 | #if !defined(SWIFT_PASTE) 53 | # define SWIFT_PASTE_HELPER(x, y) x##y 54 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) 55 | #endif 56 | #if !defined(SWIFT_METATYPE) 57 | # define SWIFT_METATYPE(X) Class 58 | #endif 59 | #if !defined(SWIFT_CLASS_PROPERTY) 60 | # if __has_feature(objc_class_property) 61 | # define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ 62 | # else 63 | # define SWIFT_CLASS_PROPERTY(...) 64 | # endif 65 | #endif 66 | 67 | #if __has_attribute(objc_runtime_name) 68 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) 69 | #else 70 | # define SWIFT_RUNTIME_NAME(X) 71 | #endif 72 | #if __has_attribute(swift_name) 73 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) 74 | #else 75 | # define SWIFT_COMPILE_NAME(X) 76 | #endif 77 | #if __has_attribute(objc_method_family) 78 | # define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) 79 | #else 80 | # define SWIFT_METHOD_FAMILY(X) 81 | #endif 82 | #if __has_attribute(noescape) 83 | # define SWIFT_NOESCAPE __attribute__((noescape)) 84 | #else 85 | # define SWIFT_NOESCAPE 86 | #endif 87 | #if __has_attribute(warn_unused_result) 88 | # define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 89 | #else 90 | # define SWIFT_WARN_UNUSED_RESULT 91 | #endif 92 | #if __has_attribute(noreturn) 93 | # define SWIFT_NORETURN __attribute__((noreturn)) 94 | #else 95 | # define SWIFT_NORETURN 96 | #endif 97 | #if !defined(SWIFT_CLASS_EXTRA) 98 | # define SWIFT_CLASS_EXTRA 99 | #endif 100 | #if !defined(SWIFT_PROTOCOL_EXTRA) 101 | # define SWIFT_PROTOCOL_EXTRA 102 | #endif 103 | #if !defined(SWIFT_ENUM_EXTRA) 104 | # define SWIFT_ENUM_EXTRA 105 | #endif 106 | #if !defined(SWIFT_CLASS) 107 | # if __has_attribute(objc_subclassing_restricted) 108 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA 109 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 110 | # else 111 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 112 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 113 | # endif 114 | #endif 115 | 116 | #if !defined(SWIFT_PROTOCOL) 117 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 118 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 119 | #endif 120 | 121 | #if !defined(SWIFT_EXTENSION) 122 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) 123 | #endif 124 | 125 | #if !defined(OBJC_DESIGNATED_INITIALIZER) 126 | # if __has_attribute(objc_designated_initializer) 127 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) 128 | # else 129 | # define OBJC_DESIGNATED_INITIALIZER 130 | # endif 131 | #endif 132 | #if !defined(SWIFT_ENUM_ATTR) 133 | # if defined(__has_attribute) && __has_attribute(enum_extensibility) 134 | # define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) 135 | # else 136 | # define SWIFT_ENUM_ATTR(_extensibility) 137 | # endif 138 | #endif 139 | #if !defined(SWIFT_ENUM) 140 | # define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type 141 | # if __has_feature(generalized_swift_name) 142 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type 143 | # else 144 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) 145 | # endif 146 | #endif 147 | #if !defined(SWIFT_UNAVAILABLE) 148 | # define SWIFT_UNAVAILABLE __attribute__((unavailable)) 149 | #endif 150 | #if !defined(SWIFT_UNAVAILABLE_MSG) 151 | # define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) 152 | #endif 153 | #if !defined(SWIFT_AVAILABILITY) 154 | # define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) 155 | #endif 156 | #if !defined(SWIFT_DEPRECATED) 157 | # define SWIFT_DEPRECATED __attribute__((deprecated)) 158 | #endif 159 | #if !defined(SWIFT_DEPRECATED_MSG) 160 | # define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) 161 | #endif 162 | #if __has_feature(attribute_diagnose_if_objc) 163 | # define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) 164 | #else 165 | # define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) 166 | #endif 167 | #if __has_feature(modules) 168 | #if __has_warning("-Watimport-in-framework-header") 169 | #pragma clang diagnostic ignored "-Watimport-in-framework-header" 170 | #endif 171 | @import CoreGraphics; 172 | @import Foundation; 173 | @import UIKit; 174 | #endif 175 | 176 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" 177 | #pragma clang diagnostic ignored "-Wduplicate-method-arg" 178 | #if __has_warning("-Wpragma-clang-attribute") 179 | # pragma clang diagnostic ignored "-Wpragma-clang-attribute" 180 | #endif 181 | #pragma clang diagnostic ignored "-Wunknown-pragmas" 182 | #pragma clang diagnostic ignored "-Wnullability" 183 | 184 | #if __has_attribute(external_source_symbol) 185 | # pragma push_macro("any") 186 | # undef any 187 | # pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="JKInfinitePageView",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) 188 | # pragma pop_macro("any") 189 | #endif 190 | 191 | @class UIColor; 192 | @class NSCoder; 193 | 194 | SWIFT_CLASS("_TtC18JKInfinitePageView18JKInfinitePageView") 195 | @interface JKInfinitePageView : UIView 196 | @property (nonatomic, strong) UIColor * _Nullable backgroundColor; 197 | - (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; 198 | - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; 199 | - (void)layoutSubviews; 200 | @end 201 | 202 | @class UIScrollView; 203 | 204 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 205 | - (void)scrollViewDidScroll:(UIScrollView * _Nonnull)scrollView; 206 | @end 207 | 208 | @class UICollectionView; 209 | @class UICollectionViewCell; 210 | 211 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 212 | - (void)collectionView:(UICollectionView * _Nonnull)collectionView willDisplayCell:(UICollectionViewCell * _Nonnull)cell forItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath; 213 | - (void)collectionView:(UICollectionView * _Nonnull)collectionView didEndDisplayingCell:(UICollectionViewCell * _Nonnull)cell forItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath; 214 | @end 215 | 216 | 217 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 218 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView * _Nonnull)collectionView SWIFT_WARN_UNUSED_RESULT; 219 | - (NSInteger)collectionView:(UICollectionView * _Nonnull)collectionView numberOfItemsInSection:(NSInteger)section SWIFT_WARN_UNUSED_RESULT; 220 | - (UICollectionViewCell * _Nonnull)collectionView:(UICollectionView * _Nonnull)collectionView cellForItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath SWIFT_WARN_UNUSED_RESULT; 221 | @end 222 | 223 | 224 | SWIFT_PROTOCOL("_TtP18JKInfinitePageView28JKInfinitePageViewDataSource_") 225 | @protocol JKInfinitePageViewDataSource 226 | @optional 227 | - (UIView * _Nonnull)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView viewBefore:(UIView * _Nonnull)view SWIFT_WARN_UNUSED_RESULT; 228 | - (UIView * _Nonnull)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView viewAfter:(UIView * _Nonnull)view SWIFT_WARN_UNUSED_RESULT; 229 | @end 230 | 231 | 232 | SWIFT_PROTOCOL("_TtP18JKInfinitePageView26JKInfinitePageViewDelegate_") 233 | @protocol JKInfinitePageViewDelegate 234 | @optional 235 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView didDisplay:(UIView * _Nonnull)view; 236 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView beforeWith:(UIView * _Nonnull)view progress:(double)progress; 237 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView afterWith:(UIView * _Nonnull)view progress:(double)progress; 238 | @end 239 | 240 | #if __has_attribute(external_source_symbol) 241 | # pragma clang attribute pop 242 | #endif 243 | #pragma clang diagnostic pop 244 | 245 | #elif defined(__ARM_ARCH_7A__) && __ARM_ARCH_7A__ 246 | // Generated by Apple Swift version 5.0 effective-4.2 (swiftlang-1001.0.69.5 clang-1001.0.46.3) 247 | #pragma clang diagnostic push 248 | #pragma clang diagnostic ignored "-Wgcc-compat" 249 | 250 | #if !defined(__has_include) 251 | # define __has_include(x) 0 252 | #endif 253 | #if !defined(__has_attribute) 254 | # define __has_attribute(x) 0 255 | #endif 256 | #if !defined(__has_feature) 257 | # define __has_feature(x) 0 258 | #endif 259 | #if !defined(__has_warning) 260 | # define __has_warning(x) 0 261 | #endif 262 | 263 | #if __has_include() 264 | # include 265 | #endif 266 | 267 | #pragma clang diagnostic ignored "-Wauto-import" 268 | #include 269 | #include 270 | #include 271 | #include 272 | 273 | #if !defined(SWIFT_TYPEDEFS) 274 | # define SWIFT_TYPEDEFS 1 275 | # if __has_include() 276 | # include 277 | # elif !defined(__cplusplus) 278 | typedef uint_least16_t char16_t; 279 | typedef uint_least32_t char32_t; 280 | # endif 281 | typedef float swift_float2 __attribute__((__ext_vector_type__(2))); 282 | typedef float swift_float3 __attribute__((__ext_vector_type__(3))); 283 | typedef float swift_float4 __attribute__((__ext_vector_type__(4))); 284 | typedef double swift_double2 __attribute__((__ext_vector_type__(2))); 285 | typedef double swift_double3 __attribute__((__ext_vector_type__(3))); 286 | typedef double swift_double4 __attribute__((__ext_vector_type__(4))); 287 | typedef int swift_int2 __attribute__((__ext_vector_type__(2))); 288 | typedef int swift_int3 __attribute__((__ext_vector_type__(3))); 289 | typedef int swift_int4 __attribute__((__ext_vector_type__(4))); 290 | typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); 291 | typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); 292 | typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); 293 | #endif 294 | 295 | #if !defined(SWIFT_PASTE) 296 | # define SWIFT_PASTE_HELPER(x, y) x##y 297 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) 298 | #endif 299 | #if !defined(SWIFT_METATYPE) 300 | # define SWIFT_METATYPE(X) Class 301 | #endif 302 | #if !defined(SWIFT_CLASS_PROPERTY) 303 | # if __has_feature(objc_class_property) 304 | # define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ 305 | # else 306 | # define SWIFT_CLASS_PROPERTY(...) 307 | # endif 308 | #endif 309 | 310 | #if __has_attribute(objc_runtime_name) 311 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) 312 | #else 313 | # define SWIFT_RUNTIME_NAME(X) 314 | #endif 315 | #if __has_attribute(swift_name) 316 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) 317 | #else 318 | # define SWIFT_COMPILE_NAME(X) 319 | #endif 320 | #if __has_attribute(objc_method_family) 321 | # define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) 322 | #else 323 | # define SWIFT_METHOD_FAMILY(X) 324 | #endif 325 | #if __has_attribute(noescape) 326 | # define SWIFT_NOESCAPE __attribute__((noescape)) 327 | #else 328 | # define SWIFT_NOESCAPE 329 | #endif 330 | #if __has_attribute(warn_unused_result) 331 | # define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 332 | #else 333 | # define SWIFT_WARN_UNUSED_RESULT 334 | #endif 335 | #if __has_attribute(noreturn) 336 | # define SWIFT_NORETURN __attribute__((noreturn)) 337 | #else 338 | # define SWIFT_NORETURN 339 | #endif 340 | #if !defined(SWIFT_CLASS_EXTRA) 341 | # define SWIFT_CLASS_EXTRA 342 | #endif 343 | #if !defined(SWIFT_PROTOCOL_EXTRA) 344 | # define SWIFT_PROTOCOL_EXTRA 345 | #endif 346 | #if !defined(SWIFT_ENUM_EXTRA) 347 | # define SWIFT_ENUM_EXTRA 348 | #endif 349 | #if !defined(SWIFT_CLASS) 350 | # if __has_attribute(objc_subclassing_restricted) 351 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA 352 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 353 | # else 354 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 355 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 356 | # endif 357 | #endif 358 | 359 | #if !defined(SWIFT_PROTOCOL) 360 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 361 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 362 | #endif 363 | 364 | #if !defined(SWIFT_EXTENSION) 365 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) 366 | #endif 367 | 368 | #if !defined(OBJC_DESIGNATED_INITIALIZER) 369 | # if __has_attribute(objc_designated_initializer) 370 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) 371 | # else 372 | # define OBJC_DESIGNATED_INITIALIZER 373 | # endif 374 | #endif 375 | #if !defined(SWIFT_ENUM_ATTR) 376 | # if defined(__has_attribute) && __has_attribute(enum_extensibility) 377 | # define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) 378 | # else 379 | # define SWIFT_ENUM_ATTR(_extensibility) 380 | # endif 381 | #endif 382 | #if !defined(SWIFT_ENUM) 383 | # define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type 384 | # if __has_feature(generalized_swift_name) 385 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type 386 | # else 387 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) 388 | # endif 389 | #endif 390 | #if !defined(SWIFT_UNAVAILABLE) 391 | # define SWIFT_UNAVAILABLE __attribute__((unavailable)) 392 | #endif 393 | #if !defined(SWIFT_UNAVAILABLE_MSG) 394 | # define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) 395 | #endif 396 | #if !defined(SWIFT_AVAILABILITY) 397 | # define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) 398 | #endif 399 | #if !defined(SWIFT_DEPRECATED) 400 | # define SWIFT_DEPRECATED __attribute__((deprecated)) 401 | #endif 402 | #if !defined(SWIFT_DEPRECATED_MSG) 403 | # define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) 404 | #endif 405 | #if __has_feature(attribute_diagnose_if_objc) 406 | # define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) 407 | #else 408 | # define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) 409 | #endif 410 | #if __has_feature(modules) 411 | #if __has_warning("-Watimport-in-framework-header") 412 | #pragma clang diagnostic ignored "-Watimport-in-framework-header" 413 | #endif 414 | @import CoreGraphics; 415 | @import Foundation; 416 | @import UIKit; 417 | #endif 418 | 419 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" 420 | #pragma clang diagnostic ignored "-Wduplicate-method-arg" 421 | #if __has_warning("-Wpragma-clang-attribute") 422 | # pragma clang diagnostic ignored "-Wpragma-clang-attribute" 423 | #endif 424 | #pragma clang diagnostic ignored "-Wunknown-pragmas" 425 | #pragma clang diagnostic ignored "-Wnullability" 426 | 427 | #if __has_attribute(external_source_symbol) 428 | # pragma push_macro("any") 429 | # undef any 430 | # pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="JKInfinitePageView",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) 431 | # pragma pop_macro("any") 432 | #endif 433 | 434 | @class UIColor; 435 | @class NSCoder; 436 | 437 | SWIFT_CLASS("_TtC18JKInfinitePageView18JKInfinitePageView") 438 | @interface JKInfinitePageView : UIView 439 | @property (nonatomic, strong) UIColor * _Nullable backgroundColor; 440 | - (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; 441 | - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; 442 | - (void)layoutSubviews; 443 | @end 444 | 445 | @class UIScrollView; 446 | 447 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 448 | - (void)scrollViewDidScroll:(UIScrollView * _Nonnull)scrollView; 449 | @end 450 | 451 | @class UICollectionView; 452 | @class UICollectionViewCell; 453 | 454 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 455 | - (void)collectionView:(UICollectionView * _Nonnull)collectionView willDisplayCell:(UICollectionViewCell * _Nonnull)cell forItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath; 456 | - (void)collectionView:(UICollectionView * _Nonnull)collectionView didEndDisplayingCell:(UICollectionViewCell * _Nonnull)cell forItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath; 457 | @end 458 | 459 | 460 | @interface JKInfinitePageView (SWIFT_EXTENSION(JKInfinitePageView)) 461 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView * _Nonnull)collectionView SWIFT_WARN_UNUSED_RESULT; 462 | - (NSInteger)collectionView:(UICollectionView * _Nonnull)collectionView numberOfItemsInSection:(NSInteger)section SWIFT_WARN_UNUSED_RESULT; 463 | - (UICollectionViewCell * _Nonnull)collectionView:(UICollectionView * _Nonnull)collectionView cellForItemAtIndexPath:(NSIndexPath * _Nonnull)indexPath SWIFT_WARN_UNUSED_RESULT; 464 | @end 465 | 466 | 467 | SWIFT_PROTOCOL("_TtP18JKInfinitePageView28JKInfinitePageViewDataSource_") 468 | @protocol JKInfinitePageViewDataSource 469 | @optional 470 | - (UIView * _Nonnull)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView viewBefore:(UIView * _Nonnull)view SWIFT_WARN_UNUSED_RESULT; 471 | - (UIView * _Nonnull)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView viewAfter:(UIView * _Nonnull)view SWIFT_WARN_UNUSED_RESULT; 472 | @end 473 | 474 | 475 | SWIFT_PROTOCOL("_TtP18JKInfinitePageView26JKInfinitePageViewDelegate_") 476 | @protocol JKInfinitePageViewDelegate 477 | @optional 478 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView didDisplay:(UIView * _Nonnull)view; 479 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView beforeWith:(UIView * _Nonnull)view progress:(double)progress; 480 | - (void)infinitePageView:(JKInfinitePageView * _Nonnull)infinitePageView afterWith:(UIView * _Nonnull)view progress:(double)progress; 481 | @end 482 | 483 | #if __has_attribute(external_source_symbol) 484 | # pragma clang attribute pop 485 | #endif 486 | #pragma clang diagnostic pop 487 | 488 | #endif 489 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Info.plist -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/JKInfinitePageView: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/JKInfinitePageView -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm64.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm64.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/arm64.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/i386.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/i386.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/i386.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/i386.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/x86_64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/x86_64.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/x86_64.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Carthage/Build/iOS/JKInfinitePageView.framework/Modules/JKInfinitePageView.swiftmodule/x86_64.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/JKInfinitePageView.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module JKInfinitePageView { 2 | header "JKInfinitePageView-Swift.h" 3 | requires objc 4 | } 5 | -------------------------------------------------------------------------------- /Example/Cartfile: -------------------------------------------------------------------------------- 1 | github "JoeCiou/JKCalendar" -------------------------------------------------------------------------------- /Example/JKCalendar-Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7C72FF231E72930100D12F76 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C72FF221E72930100D12F76 /* AppDelegate.swift */; }; 11 | 7C72FF251E72930100D12F76 /* ScrollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C72FF241E72930100D12F76 /* ScrollViewController.swift */; }; 12 | 7C72FF281E72930100D12F76 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7C72FF261E72930100D12F76 /* Main.storyboard */; }; 13 | 7C72FF2A1E72930100D12F76 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7C72FF291E72930100D12F76 /* Assets.xcassets */; }; 14 | 7C72FF2D1E72930100D12F76 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7C72FF2B1E72930100D12F76 /* LaunchScreen.storyboard */; }; 15 | 7C7300761F4C0803002D9861 /* SelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C7300751F4C0803002D9861 /* SelectorViewController.swift */; }; 16 | 7CA7DDDD1F6102030061011A /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CA7DDDC1F6102030061011A /* TableViewController.swift */; }; 17 | BB70E314764609619B1A1E45 /* Pods_JKCalendar_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74C8F7540A138A678E1AF9CB /* Pods_JKCalendar_Example.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | 7CF7FE6F1FFB865900200D3C /* Embed Frameworks */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = ""; 25 | dstSubfolderSpec = 10; 26 | files = ( 27 | ); 28 | name = "Embed Frameworks"; 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXCopyFilesBuildPhase section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 361D448F49212F5DB0AC92C4 /* Pods-JKCalendar-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JKCalendar-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JKCalendar-Example/Pods-JKCalendar-Example.debug.xcconfig"; sourceTree = ""; }; 35 | 74C8F7540A138A678E1AF9CB /* Pods_JKCalendar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JKCalendar_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 7C20ECF1E7C8F7CAFF1B8C5D /* Pods-JKCalendar-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JKCalendar-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-JKCalendar-Example/Pods-JKCalendar-Example.release.xcconfig"; sourceTree = ""; }; 37 | 7C72FF1F1E72930100D12F76 /* JKCalendar-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "JKCalendar-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 7C72FF221E72930100D12F76 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 39 | 7C72FF241E72930100D12F76 /* ScrollViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewController.swift; sourceTree = ""; }; 40 | 7C72FF271E72930100D12F76 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 7C72FF291E72930100D12F76 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 42 | 7C72FF2C1E72930100D12F76 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 43 | 7C72FF2E1E72930200D12F76 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | 7C7300751F4C0803002D9861 /* SelectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectorViewController.swift; sourceTree = ""; }; 45 | 7CA7DDDC1F6102030061011A /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 7C72FF1C1E72930100D12F76 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | BB70E314764609619B1A1E45 /* Pods_JKCalendar_Example.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 64A8DDF62768D88F55726AF8 /* Pods */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 361D448F49212F5DB0AC92C4 /* Pods-JKCalendar-Example.debug.xcconfig */, 64 | 7C20ECF1E7C8F7CAFF1B8C5D /* Pods-JKCalendar-Example.release.xcconfig */, 65 | ); 66 | name = Pods; 67 | sourceTree = ""; 68 | }; 69 | 7C72FF161E72930100D12F76 = { 70 | isa = PBXGroup; 71 | children = ( 72 | 7C72FF211E72930100D12F76 /* JKCalendar-Example */, 73 | 7C72FF201E72930100D12F76 /* Products */, 74 | 64A8DDF62768D88F55726AF8 /* Pods */, 75 | E65F3D52B3F3453A6ACA132C /* Frameworks */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | 7C72FF201E72930100D12F76 /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 7C72FF1F1E72930100D12F76 /* JKCalendar-Example.app */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 7C72FF211E72930100D12F76 /* JKCalendar-Example */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 7C72FF221E72930100D12F76 /* AppDelegate.swift */, 91 | 7C7300751F4C0803002D9861 /* SelectorViewController.swift */, 92 | 7C72FF241E72930100D12F76 /* ScrollViewController.swift */, 93 | 7CA7DDDC1F6102030061011A /* TableViewController.swift */, 94 | 7C72FF261E72930100D12F76 /* Main.storyboard */, 95 | 7C72FF291E72930100D12F76 /* Assets.xcassets */, 96 | 7C72FF2B1E72930100D12F76 /* LaunchScreen.storyboard */, 97 | 7C72FF2E1E72930200D12F76 /* Info.plist */, 98 | ); 99 | path = "JKCalendar-Example"; 100 | sourceTree = ""; 101 | }; 102 | E65F3D52B3F3453A6ACA132C /* Frameworks */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 74C8F7540A138A678E1AF9CB /* Pods_JKCalendar_Example.framework */, 106 | ); 107 | name = Frameworks; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | 7C72FF1E1E72930100D12F76 /* JKCalendar-Example */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = 7C72FF311E72930200D12F76 /* Build configuration list for PBXNativeTarget "JKCalendar-Example" */; 116 | buildPhases = ( 117 | 19D9E6AA37C40B1A00D6F001 /* [CP] Check Pods Manifest.lock */, 118 | 7C72FF1B1E72930100D12F76 /* Sources */, 119 | 7C72FF1C1E72930100D12F76 /* Frameworks */, 120 | 7C72FF1D1E72930100D12F76 /* Resources */, 121 | 7CF7FE6F1FFB865900200D3C /* Embed Frameworks */, 122 | 133A683166D81DA96F85D19C /* [CP] Embed Pods Frameworks */, 123 | ); 124 | buildRules = ( 125 | ); 126 | dependencies = ( 127 | ); 128 | name = "JKCalendar-Example"; 129 | productName = "JKCalendar-Sample"; 130 | productReference = 7C72FF1F1E72930100D12F76 /* JKCalendar-Example.app */; 131 | productType = "com.apple.product-type.application"; 132 | }; 133 | /* End PBXNativeTarget section */ 134 | 135 | /* Begin PBXProject section */ 136 | 7C72FF171E72930100D12F76 /* Project object */ = { 137 | isa = PBXProject; 138 | attributes = { 139 | LastSwiftUpdateCheck = 0820; 140 | LastUpgradeCheck = 0900; 141 | ORGANIZATIONNAME = Joe; 142 | TargetAttributes = { 143 | 7C72FF1E1E72930100D12F76 = { 144 | CreatedOnToolsVersion = 8.2.1; 145 | DevelopmentTeam = KE5A24937J; 146 | LastSwiftMigration = 1000; 147 | ProvisioningStyle = Automatic; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 7C72FF1A1E72930100D12F76 /* Build configuration list for PBXProject "JKCalendar-Example" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = English; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 7C72FF161E72930100D12F76; 160 | productRefGroup = 7C72FF201E72930100D12F76 /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 7C72FF1E1E72930100D12F76 /* JKCalendar-Example */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 7C72FF1D1E72930100D12F76 /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 7C72FF2D1E72930100D12F76 /* LaunchScreen.storyboard in Resources */, 175 | 7C72FF2A1E72930100D12F76 /* Assets.xcassets in Resources */, 176 | 7C72FF281E72930100D12F76 /* Main.storyboard in Resources */, 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | }; 180 | /* End PBXResourcesBuildPhase section */ 181 | 182 | /* Begin PBXShellScriptBuildPhase section */ 183 | 133A683166D81DA96F85D19C /* [CP] Embed Pods Frameworks */ = { 184 | isa = PBXShellScriptBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | ); 188 | inputPaths = ( 189 | "${PODS_ROOT}/Target Support Files/Pods-JKCalendar-Example/Pods-JKCalendar-Example-frameworks.sh", 190 | "${BUILT_PRODUCTS_DIR}/JKCalendar/JKCalendar.framework", 191 | "${BUILT_PRODUCTS_DIR}/JKInfinitePageView/JKInfinitePageView.framework", 192 | ); 193 | name = "[CP] Embed Pods Frameworks"; 194 | outputPaths = ( 195 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JKCalendar.framework", 196 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JKInfinitePageView.framework", 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | shellPath = /bin/sh; 200 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JKCalendar-Example/Pods-JKCalendar-Example-frameworks.sh\"\n"; 201 | showEnvVarsInLog = 0; 202 | }; 203 | 19D9E6AA37C40B1A00D6F001 /* [CP] Check Pods Manifest.lock */ = { 204 | isa = PBXShellScriptBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | ); 208 | inputPaths = ( 209 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 210 | "${PODS_ROOT}/Manifest.lock", 211 | ); 212 | name = "[CP] Check Pods Manifest.lock"; 213 | outputPaths = ( 214 | "$(DERIVED_FILE_DIR)/Pods-JKCalendar-Example-checkManifestLockResult.txt", 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | 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"; 219 | showEnvVarsInLog = 0; 220 | }; 221 | /* End PBXShellScriptBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 7C72FF1B1E72930100D12F76 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 7C72FF251E72930100D12F76 /* ScrollViewController.swift in Sources */, 229 | 7C7300761F4C0803002D9861 /* SelectorViewController.swift in Sources */, 230 | 7C72FF231E72930100D12F76 /* AppDelegate.swift in Sources */, 231 | 7CA7DDDD1F6102030061011A /* TableViewController.swift in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | 7C72FF261E72930100D12F76 /* Main.storyboard */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | 7C72FF271E72930100D12F76 /* Base */, 242 | ); 243 | name = Main.storyboard; 244 | sourceTree = ""; 245 | }; 246 | 7C72FF2B1E72930100D12F76 /* LaunchScreen.storyboard */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | 7C72FF2C1E72930100D12F76 /* Base */, 250 | ); 251 | name = LaunchScreen.storyboard; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXVariantGroup section */ 255 | 256 | /* Begin XCBuildConfiguration section */ 257 | 7C72FF2F1E72930200D12F76 /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_COMMA = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 271 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INFINITE_RECURSION = YES; 275 | CLANG_WARN_INT_CONVERSION = YES; 276 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 279 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 280 | CLANG_WARN_STRICT_PROTOTYPES = YES; 281 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 282 | CLANG_WARN_UNREACHABLE_CODE = YES; 283 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 284 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 285 | COPY_PHASE_STRIP = NO; 286 | DEBUG_INFORMATION_FORMAT = dwarf; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | ENABLE_TESTABILITY = YES; 289 | GCC_C_LANGUAGE_STANDARD = gnu99; 290 | GCC_DYNAMIC_NO_PIC = NO; 291 | GCC_NO_COMMON_BLOCKS = YES; 292 | GCC_OPTIMIZATION_LEVEL = 0; 293 | GCC_PREPROCESSOR_DEFINITIONS = ( 294 | "DEBUG=1", 295 | "$(inherited)", 296 | ); 297 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 298 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 299 | GCC_WARN_UNDECLARED_SELECTOR = YES; 300 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 301 | GCC_WARN_UNUSED_FUNCTION = YES; 302 | GCC_WARN_UNUSED_VARIABLE = YES; 303 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 304 | MTL_ENABLE_DEBUG_INFO = YES; 305 | ONLY_ACTIVE_ARCH = YES; 306 | SDKROOT = iphoneos; 307 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 308 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 309 | }; 310 | name = Debug; 311 | }; 312 | 7C72FF301E72930200D12F76 /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ANALYZER_NONNULL = YES; 317 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 318 | CLANG_CXX_LIBRARY = "libc++"; 319 | CLANG_ENABLE_MODULES = YES; 320 | CLANG_ENABLE_OBJC_ARC = YES; 321 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 322 | CLANG_WARN_BOOL_CONVERSION = YES; 323 | CLANG_WARN_COMMA = YES; 324 | CLANG_WARN_CONSTANT_CONVERSION = YES; 325 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 326 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INFINITE_RECURSION = YES; 330 | CLANG_WARN_INT_CONVERSION = YES; 331 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 333 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 334 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 335 | CLANG_WARN_STRICT_PROTOTYPES = YES; 336 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 337 | CLANG_WARN_UNREACHABLE_CODE = YES; 338 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 339 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 340 | COPY_PHASE_STRIP = NO; 341 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 342 | ENABLE_NS_ASSERTIONS = NO; 343 | ENABLE_STRICT_OBJC_MSGSEND = YES; 344 | GCC_C_LANGUAGE_STANDARD = gnu99; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 347 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 348 | GCC_WARN_UNDECLARED_SELECTOR = YES; 349 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 350 | GCC_WARN_UNUSED_FUNCTION = YES; 351 | GCC_WARN_UNUSED_VARIABLE = YES; 352 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 353 | MTL_ENABLE_DEBUG_INFO = NO; 354 | SDKROOT = iphoneos; 355 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 356 | VALIDATE_PRODUCT = YES; 357 | }; 358 | name = Release; 359 | }; 360 | 7C72FF321E72930200D12F76 /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | baseConfigurationReference = 361D448F49212F5DB0AC92C4 /* Pods-JKCalendar-Example.debug.xcconfig */; 363 | buildSettings = { 364 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 365 | DEVELOPMENT_TEAM = KE5A24937J; 366 | FRAMEWORK_SEARCH_PATHS = ( 367 | "$(inherited)", 368 | "$(PROJECT_DIR)", 369 | "$(PROJECT_DIR)/Carthage/Build/iOS", 370 | ); 371 | INFOPLIST_FILE = "$(SRCROOT)/JKCalendar-Example/Info.plist"; 372 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 373 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 374 | PRODUCT_BUNDLE_IDENTIFIER = "com.joe.JKCalendar-Sample"; 375 | PRODUCT_NAME = "$(TARGET_NAME)"; 376 | SWIFT_VERSION = 4.2; 377 | }; 378 | name = Debug; 379 | }; 380 | 7C72FF331E72930200D12F76 /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | baseConfigurationReference = 7C20ECF1E7C8F7CAFF1B8C5D /* Pods-JKCalendar-Example.release.xcconfig */; 383 | buildSettings = { 384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 385 | DEVELOPMENT_TEAM = KE5A24937J; 386 | FRAMEWORK_SEARCH_PATHS = ( 387 | "$(inherited)", 388 | "$(PROJECT_DIR)", 389 | "$(PROJECT_DIR)/Carthage/Build/iOS", 390 | ); 391 | INFOPLIST_FILE = "$(SRCROOT)/JKCalendar-Example/Info.plist"; 392 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 394 | PRODUCT_BUNDLE_IDENTIFIER = "com.joe.JKCalendar-Sample"; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | SWIFT_VERSION = 4.2; 397 | }; 398 | name = Release; 399 | }; 400 | /* End XCBuildConfiguration section */ 401 | 402 | /* Begin XCConfigurationList section */ 403 | 7C72FF1A1E72930100D12F76 /* Build configuration list for PBXProject "JKCalendar-Example" */ = { 404 | isa = XCConfigurationList; 405 | buildConfigurations = ( 406 | 7C72FF2F1E72930200D12F76 /* Debug */, 407 | 7C72FF301E72930200D12F76 /* Release */, 408 | ); 409 | defaultConfigurationIsVisible = 0; 410 | defaultConfigurationName = Release; 411 | }; 412 | 7C72FF311E72930200D12F76 /* Build configuration list for PBXNativeTarget "JKCalendar-Example" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | 7C72FF321E72930200D12F76 /* Debug */, 416 | 7C72FF331E72930200D12F76 /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | /* End XCConfigurationList section */ 422 | }; 423 | rootObject = 7C72FF171E72930100D12F76 /* Project object */; 424 | } 425 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | 27 | @UIApplicationMain 28 | class AppDelegate: UIResponder, UIApplicationDelegate { 29 | 30 | var window: UIWindow? 31 | 32 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 33 | // Override point for customization after application launch. 34 | return true 35 | } 36 | 37 | func applicationWillResignActive(_ application: UIApplication) { 38 | // 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. 39 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 40 | } 41 | 42 | func applicationDidEnterBackground(_ application: UIApplication) { 43 | // 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. 44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 45 | } 46 | 47 | func applicationWillEnterForeground(_ application: UIApplication) { 48 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 49 | } 50 | 51 | func applicationDidBecomeActive(_ application: UIApplication) { 52 | // 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. 53 | } 54 | 55 | func applicationWillTerminate(_ application: UIApplication) { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "JKCalendar_icon.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/JKCalendar_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/AppIcon.appiconset/JKCalendar_icon.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "nb_btn_back.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "nb_btn_back@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "nb_btn_back@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_back.imageset/nb_btn_back@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_down.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_down@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_down@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_down.imageset/ic_down@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_up.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_up@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_up@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/ic_up.imageset/ic_up@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo@2x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Example/JKCalendar-Example/Assets.xcassets/logo.imageset/logo@3x.png -------------------------------------------------------------------------------- /Example/JKCalendar-Example/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 | 27 | 28 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | JKCalendar 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 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/ScrollViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollViewController.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | import JKCalendar 27 | 28 | class ScrollViewController: UIViewController { 29 | 30 | let markColor = UIColor(red: 40/255, green: 178/255, blue: 253/255, alpha: 1) 31 | var selectDay: JKDay = JKDay(date: Date()) 32 | 33 | @IBOutlet weak var statusButtonItem: UIBarButtonItem! 34 | @IBOutlet weak var calendarScrollView: JKCalendarScrollView! 35 | 36 | @IBOutlet weak var dateLabel: UILabel! 37 | @IBOutlet weak var textview: UITextView! 38 | @IBOutlet weak var timeLabel: UILabel! 39 | 40 | override func viewDidLoad() { 41 | super.viewDidLoad() 42 | 43 | calendarScrollView.calendar.delegate = self 44 | calendarScrollView.calendar.dataSource = self 45 | 46 | calendarScrollView.calendar.textColor = UIColor(red: 60/255, 47 | green: 60/255, 48 | blue: 60/255, 49 | alpha: 1) 50 | calendarScrollView.calendar.backgroundColor = UIColor.white 51 | 52 | calendarScrollView.calendar.focusWeek = selectDay.weekOfMonth - 1 53 | calendarScrollView.calendar.isInitializationCollapsed = true 54 | 55 | setupTextView() 56 | } 57 | 58 | func setupTextView(){ 59 | let selectDate = JKCalendar.calendar.date(from: DateComponents(year: selectDay.year, 60 | month: selectDay.month, 61 | day: selectDay.day))! 62 | let formatter = DateFormatter() 63 | 64 | formatter.dateStyle = .medium 65 | formatter.timeStyle = .none 66 | dateLabel.text = formatter.string(from: selectDate) 67 | 68 | formatter.dateStyle = .none 69 | formatter.timeStyle = .medium 70 | timeLabel.text = formatter.string(from: selectDate) 71 | 72 | textview.textContainerInset = UIEdgeInsets.zero 73 | textview.textContainer.lineFragmentPadding = 0 74 | } 75 | 76 | override func didReceiveMemoryWarning() { 77 | super.didReceiveMemoryWarning() 78 | // Dispose of any resources that can be recreated. 79 | } 80 | 81 | 82 | @IBAction func handleStatusButtonClick(_ sender: Any) { 83 | if calendarScrollView.calendar.status == .collapse{ 84 | calendarScrollView.calendar.expand(animated: true) 85 | }else if calendarScrollView.calendar.status == .expand{ 86 | calendarScrollView.calendar.collapse(animated: true) 87 | } 88 | } 89 | 90 | @IBAction func handleBackButtonClick(_ sender: Any) { 91 | let _ = navigationController?.popViewController(animated: true) 92 | } 93 | 94 | } 95 | 96 | extension ScrollViewController: JKCalendarDelegate{ 97 | 98 | func calendar(_ calendar: JKCalendar, didTouch day: JKDay){ 99 | selectDay = day 100 | calendar.focusWeek = day < calendar.month ? 0: day > calendar.month ? calendar.month.weeksCount - 1: day.weekOfMonth - 1 101 | calendar.reloadData() 102 | 103 | let testDay = JKDay(date: Date()) 104 | print(min(day, testDay).day) 105 | } 106 | 107 | func calendar(_ calendar: JKCalendar, didChanged status: JKCalendarViewStatus) { 108 | statusButtonItem.image = UIImage(named: status == .collapse ? "ic_down": "ic_up") 109 | } 110 | 111 | func heightOfFooterView(in claendar: JKCalendar) -> CGFloat{ 112 | return 10 113 | } 114 | 115 | func viewOfFooter(in calendar: JKCalendar) -> UIView?{ 116 | let view = UIView() 117 | let line = UIView(frame: CGRect(x: 8, y: 9, width: calendar.frame.width - 16, height: 1)) 118 | line.backgroundColor = UIColor.lightGray 119 | view.addSubview(line) 120 | return view 121 | } 122 | } 123 | 124 | extension ScrollViewController: JKCalendarDataSource{ 125 | 126 | func calendar(_ calendar: JKCalendar, marksWith month: JKMonth) -> [JKCalendarMark]? { 127 | 128 | let firstMarkDay: JKDay = JKDay(year: 2018, month: 1, day: 9)! 129 | let secondMarkDay: JKDay = JKDay(year: 2018, month: 1, day: 20)! 130 | 131 | var marks: [JKCalendarMark] = [] 132 | if selectDay == month{ 133 | marks.append(JKCalendarMark(type: .circle, 134 | day: selectDay, 135 | color: markColor)) 136 | } 137 | if firstMarkDay == month{ 138 | marks.append(JKCalendarMark(type: .underline, 139 | day: firstMarkDay, 140 | color: markColor)) 141 | } 142 | if secondMarkDay == month{ 143 | marks.append(JKCalendarMark(type: .hollowCircle, 144 | day: secondMarkDay, 145 | color: markColor)) 146 | } 147 | return marks 148 | } 149 | 150 | func calendar(_ calendar: JKCalendar, continuousMarksWith month: JKMonth) -> [JKCalendarContinuousMark]?{ 151 | let startDay: JKDay = JKDay(year: 2018, month: 1, day: 17)! 152 | let endDay: JKDay = JKDay(year: 2018, month: 1, day: 18)! 153 | 154 | return [JKCalendarContinuousMark(type: .dot, 155 | start: startDay, 156 | end: endDay, 157 | color: markColor)] 158 | } 159 | 160 | } 161 | 162 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/SelectorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SelectorViewController.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | import JKCalendar 27 | 28 | class SelectorViewController: UIViewController { 29 | 30 | let markColor = UIColor(red: 40/255, green: 178/255, blue: 253/255, alpha: 1) 31 | var selectDays: [JKDay]?{ 32 | didSet{ 33 | if let days = selectDays, 34 | days.count > 0{ 35 | let formatter = DateFormatter() 36 | formatter.dateStyle = .medium 37 | formatter.timeStyle = .none 38 | 39 | let firstDay = days.first! 40 | let firstDate = JKCalendar.calendar.date(from: DateComponents(year: firstDay.year, 41 | month: firstDay.month, 42 | day: firstDay.day))! 43 | if days.count == 1{ 44 | dateLabel.text = formatter.string(from: firstDate) 45 | }else{ 46 | let lastDay = days.last! 47 | let lastDate = JKCalendar.calendar.date(from: DateComponents(year: lastDay.year, 48 | month: lastDay.month, 49 | day: lastDay.day))! 50 | dateLabel.text = formatter.string(from: firstDate) + "-" + formatter.string(from: lastDate) 51 | } 52 | } 53 | } 54 | } 55 | 56 | @IBOutlet weak var calendar: JKCalendar! 57 | @IBOutlet weak var dateLabel: UILabel! 58 | 59 | override func viewDidLoad() { 60 | super.viewDidLoad() 61 | 62 | calendar.delegate = self 63 | calendar.dataSource = self 64 | 65 | calendar.textColor = UIColor(white: 0.25, alpha: 1) 66 | calendar.backgroundColor = UIColor.white 67 | 68 | calendar.isNearbyMonthNameDisplayed = false 69 | calendar.isScrollEnabled = false 70 | } 71 | 72 | override func didReceiveMemoryWarning() { 73 | super.didReceiveMemoryWarning() 74 | // Dispose of any resources that can be recreated. 75 | } 76 | 77 | @IBAction func handleBackButtonClick(_ sender: Any) { 78 | let _ = navigationController?.popViewController(animated: true) 79 | } 80 | 81 | } 82 | 83 | extension SelectorViewController: JKCalendarDelegate{ 84 | 85 | func calendar(_ calendar: JKCalendar, didTouch day: JKDay) { 86 | selectDays = [day] 87 | calendar.reloadData() 88 | } 89 | 90 | func calendar(_ calendar: JKCalendar, didPan days: [JKDay]) { 91 | selectDays = days 92 | calendar.reloadData() 93 | } 94 | } 95 | 96 | extension SelectorViewController: JKCalendarDataSource{ 97 | 98 | func calendar(_ calendar: JKCalendar, continuousMarksWith month: JKMonth) -> [JKCalendarContinuousMark]?{ 99 | if let days = selectDays, 100 | let start = days.first, 101 | let end = days.last{ 102 | return [JKCalendarContinuousMark(type: .circle, start: start, end: end, color: markColor)] 103 | }else{ 104 | return nil 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /Example/JKCalendar-Example/TableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | import JKCalendar 27 | 28 | class TableViewCell: UITableViewCell{ 29 | @IBOutlet weak var timeLabel: UILabel! 30 | } 31 | 32 | class TableViewController: UIViewController { 33 | 34 | let markColor = UIColor(red: 40/255, green: 178/255, blue: 253/255, alpha: 1) 35 | var selectDay: JKDay = JKDay(date: Date()) 36 | 37 | @IBOutlet weak var calendarTableView: JKCalendarTableView! 38 | 39 | override func viewDidLoad() { 40 | super.viewDidLoad() 41 | 42 | calendarTableView.nativeDelegate = self 43 | calendarTableView.calendar.delegate = self 44 | calendarTableView.calendar.dataSource = self 45 | 46 | calendarTableView.calendar.focusWeek = selectDay.weekOfMonth - 1 47 | } 48 | 49 | override func didReceiveMemoryWarning() { 50 | super.didReceiveMemoryWarning() 51 | // Dispose of any resources that can be recreated. 52 | } 53 | 54 | @IBAction func handleBackButtonClick(_ sender: Any) { 55 | let _ = navigationController?.popViewController(animated: true) 56 | } 57 | 58 | } 59 | 60 | extension TableViewController: JKCalendarDelegate{ 61 | 62 | func calendar(_ calendar: JKCalendar, didTouch day: JKDay){ 63 | selectDay = day 64 | calendar.focusWeek = day < calendar.month ? 0: day > calendar.month ? calendar.month.weeksCount - 1: day.weekOfMonth - 1 65 | calendar.reloadData() 66 | } 67 | 68 | func heightOfFooterView(in claendar: JKCalendar) -> CGFloat{ 69 | return 10 70 | } 71 | 72 | func viewOfFooter(in calendar: JKCalendar) -> UIView?{ 73 | let view = UIView() 74 | let line = UIView(frame: CGRect(x: 8, y: 9, width: calendar.frame.width - 16, height: 1)) 75 | line.backgroundColor = UIColor.lightGray 76 | view.addSubview(line) 77 | return view 78 | } 79 | } 80 | 81 | extension TableViewController: JKCalendarDataSource{ 82 | 83 | func calendar(_ calendar: JKCalendar, marksWith month: JKMonth) -> [JKCalendarMark]? { 84 | 85 | let firstMarkDay: JKDay = JKDay(year: 2018, month: 1, day: 9)! 86 | let secondMarkDay: JKDay = JKDay(year: 2018, month: 1, day: 20)! 87 | 88 | var marks: [JKCalendarMark] = [] 89 | if selectDay == month{ 90 | marks.append(JKCalendarMark(type: .circle, 91 | day: selectDay, 92 | color: markColor)) 93 | } 94 | if firstMarkDay == month{ 95 | marks.append(JKCalendarMark(type: .underline, 96 | day: firstMarkDay, 97 | color: markColor)) 98 | } 99 | if secondMarkDay == month{ 100 | marks.append(JKCalendarMark(type: .hollowCircle, 101 | day: secondMarkDay, 102 | color: markColor)) 103 | } 104 | return marks 105 | } 106 | 107 | func calendar(_ calendar: JKCalendar, continuousMarksWith month: JKMonth) -> [JKCalendarContinuousMark]?{ 108 | let startDay: JKDay = JKDay(year: 2018, month: 1, day: 17)! 109 | let endDay: JKDay = JKDay(year: 2018, month: 1, day: 18)! 110 | 111 | return [JKCalendarContinuousMark(type: .dot, 112 | start: startDay, 113 | end: endDay, 114 | color: markColor)] 115 | } 116 | 117 | } 118 | 119 | extension TableViewController: UITableViewDelegate, UITableViewDataSource{ 120 | 121 | func numberOfSections(in tableView: UITableView) -> Int { 122 | return 1 123 | } 124 | 125 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 126 | return 48 127 | } 128 | 129 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 130 | let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell 131 | 132 | if indexPath.row % 2 == 0 && indexPath.row != 0 && indexPath.row != 47{ 133 | let hour = indexPath.row / 2 134 | cell.timeLabel.text = (hour < 10 ? "0": "") + String(hour) + ":00" 135 | }else{ 136 | cell.timeLabel.text = "" 137 | } 138 | 139 | return cell 140 | } 141 | 142 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 143 | print(indexPath.row) 144 | } 145 | 146 | } 147 | 148 | 149 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'JKCalendar-Example' do 5 | use_frameworks! 6 | pod 'JKCalendar' 7 | end 8 | -------------------------------------------------------------------------------- /JKCalendar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7CBDAE4B1FF49B30007D6D22 /* common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE3F1FF49B30007D6D22 /* common.swift */; }; 11 | 7CBDAE4D1FF49B30007D6D22 /* icon.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CBDAE421FF49B30007D6D22 /* icon.xcassets */; }; 12 | 7CBDAE501FF49B30007D6D22 /* JKCalendar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE451FF49B30007D6D22 /* JKCalendar.swift */; }; 13 | 7CBDAE511FF49B30007D6D22 /* JKCalendarMark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE461FF49B30007D6D22 /* JKCalendarMark.swift */; }; 14 | 7CBDAE521FF49B30007D6D22 /* JKCalendarScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE471FF49B30007D6D22 /* JKCalendarScrollView.swift */; }; 15 | 7CBDAE531FF49B30007D6D22 /* JKCalendarTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE481FF49B30007D6D22 /* JKCalendarTableView.swift */; }; 16 | 7CBDAE541FF49B30007D6D22 /* JKCalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CBDAE491FF49B30007D6D22 /* JKCalendarView.swift */; }; 17 | 7CBDAE571FF49CBB007D6D22 /* JKCalendar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7CBDAE561FF49CBB007D6D22 /* JKCalendar.xib */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 7C5141081F34203600263E8A /* JKCalendar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JKCalendar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 7CBDAE3F1FF49B30007D6D22 /* common.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = common.swift; sourceTree = ""; }; 23 | 7CBDAE421FF49B30007D6D22 /* icon.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = icon.xcassets; sourceTree = ""; }; 24 | 7CBDAE431FF49B30007D6D22 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | 7CBDAE441FF49B30007D6D22 /* JKCalendar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JKCalendar.h; sourceTree = ""; }; 26 | 7CBDAE451FF49B30007D6D22 /* JKCalendar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JKCalendar.swift; sourceTree = ""; }; 27 | 7CBDAE461FF49B30007D6D22 /* JKCalendarMark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JKCalendarMark.swift; sourceTree = ""; }; 28 | 7CBDAE471FF49B30007D6D22 /* JKCalendarScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JKCalendarScrollView.swift; sourceTree = ""; }; 29 | 7CBDAE481FF49B30007D6D22 /* JKCalendarTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JKCalendarTableView.swift; sourceTree = ""; }; 30 | 7CBDAE491FF49B30007D6D22 /* JKCalendarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JKCalendarView.swift; sourceTree = ""; }; 31 | 7CBDAE561FF49CBB007D6D22 /* JKCalendar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JKCalendar.xib; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 7C5141041F34203600263E8A /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 7C5140FE1F34203600263E8A = { 46 | isa = PBXGroup; 47 | children = ( 48 | 7CBDAE3E1FF49B30007D6D22 /* Sources */, 49 | 7C5141091F34203600263E8A /* Products */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | 7C5141091F34203600263E8A /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 7C5141081F34203600263E8A /* JKCalendar.framework */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | 7CBDAE3E1FF49B30007D6D22 /* Sources */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 7CBDAE3F1FF49B30007D6D22 /* common.swift */, 65 | 7CBDAE451FF49B30007D6D22 /* JKCalendar.swift */, 66 | 7CBDAE461FF49B30007D6D22 /* JKCalendarMark.swift */, 67 | 7CBDAE471FF49B30007D6D22 /* JKCalendarScrollView.swift */, 68 | 7CBDAE481FF49B30007D6D22 /* JKCalendarTableView.swift */, 69 | 7CBDAE491FF49B30007D6D22 /* JKCalendarView.swift */, 70 | 7CBDAE441FF49B30007D6D22 /* JKCalendar.h */, 71 | 7CBDAE561FF49CBB007D6D22 /* JKCalendar.xib */, 72 | 7CBDAE421FF49B30007D6D22 /* icon.xcassets */, 73 | 7CBDAE431FF49B30007D6D22 /* Info.plist */, 74 | ); 75 | path = Sources; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXHeadersBuildPhase section */ 81 | 7C5141051F34203600263E8A /* Headers */ = { 82 | isa = PBXHeadersBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXHeadersBuildPhase section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | 7C5141071F34203600263E8A /* JKCalendar */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = 7C5141101F34203600263E8A /* Build configuration list for PBXNativeTarget "JKCalendar" */; 94 | buildPhases = ( 95 | 7C5141031F34203600263E8A /* Sources */, 96 | 7C5141041F34203600263E8A /* Frameworks */, 97 | 7C5141051F34203600263E8A /* Headers */, 98 | 7C5141061F34203600263E8A /* Resources */, 99 | ); 100 | buildRules = ( 101 | ); 102 | dependencies = ( 103 | ); 104 | name = JKCalendar; 105 | productName = JKCalendar; 106 | productReference = 7C5141081F34203600263E8A /* JKCalendar.framework */; 107 | productType = "com.apple.product-type.framework"; 108 | }; 109 | /* End PBXNativeTarget section */ 110 | 111 | /* Begin PBXProject section */ 112 | 7C5140FF1F34203600263E8A /* Project object */ = { 113 | isa = PBXProject; 114 | attributes = { 115 | LastUpgradeCheck = 1000; 116 | ORGANIZATIONNAME = Joe; 117 | TargetAttributes = { 118 | 7C5141071F34203600263E8A = { 119 | CreatedOnToolsVersion = 8.3.3; 120 | DevelopmentTeam = AZ5GBDWZ9H; 121 | LastSwiftMigration = 0900; 122 | ProvisioningStyle = Automatic; 123 | }; 124 | }; 125 | }; 126 | buildConfigurationList = 7C5141021F34203600263E8A /* Build configuration list for PBXProject "JKCalendar" */; 127 | compatibilityVersion = "Xcode 3.2"; 128 | developmentRegion = English; 129 | hasScannedForEncodings = 0; 130 | knownRegions = ( 131 | English, 132 | en, 133 | de, 134 | ); 135 | mainGroup = 7C5140FE1F34203600263E8A; 136 | productRefGroup = 7C5141091F34203600263E8A /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | 7C5141071F34203600263E8A /* JKCalendar */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXResourcesBuildPhase section */ 146 | 7C5141061F34203600263E8A /* Resources */ = { 147 | isa = PBXResourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 7CBDAE4D1FF49B30007D6D22 /* icon.xcassets in Resources */, 151 | 7CBDAE571FF49CBB007D6D22 /* JKCalendar.xib in Resources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXResourcesBuildPhase section */ 156 | 157 | /* Begin PBXSourcesBuildPhase section */ 158 | 7C5141031F34203600263E8A /* Sources */ = { 159 | isa = PBXSourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 7CBDAE4B1FF49B30007D6D22 /* common.swift in Sources */, 163 | 7CBDAE541FF49B30007D6D22 /* JKCalendarView.swift in Sources */, 164 | 7CBDAE501FF49B30007D6D22 /* JKCalendar.swift in Sources */, 165 | 7CBDAE511FF49B30007D6D22 /* JKCalendarMark.swift in Sources */, 166 | 7CBDAE521FF49B30007D6D22 /* JKCalendarScrollView.swift in Sources */, 167 | 7CBDAE531FF49B30007D6D22 /* JKCalendarTableView.swift in Sources */, 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | }; 171 | /* End PBXSourcesBuildPhase section */ 172 | 173 | /* Begin XCBuildConfiguration section */ 174 | 7C51410E1F34203600263E8A /* Debug */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 179 | CLANG_ANALYZER_NONNULL = YES; 180 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 181 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 182 | CLANG_CXX_LIBRARY = "libc++"; 183 | CLANG_ENABLE_MODULES = YES; 184 | CLANG_ENABLE_OBJC_ARC = YES; 185 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_COMMA = YES; 188 | CLANG_WARN_CONSTANT_CONVERSION = YES; 189 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 190 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 191 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 192 | CLANG_WARN_EMPTY_BODY = YES; 193 | CLANG_WARN_ENUM_CONVERSION = YES; 194 | CLANG_WARN_INFINITE_RECURSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 197 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 198 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 199 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 200 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 201 | CLANG_WARN_STRICT_PROTOTYPES = YES; 202 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 203 | CLANG_WARN_UNREACHABLE_CODE = YES; 204 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 205 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 206 | COPY_PHASE_STRIP = NO; 207 | CURRENT_PROJECT_VERSION = 1; 208 | DEBUG_INFORMATION_FORMAT = dwarf; 209 | ENABLE_STRICT_OBJC_MSGSEND = YES; 210 | ENABLE_TESTABILITY = YES; 211 | GCC_C_LANGUAGE_STANDARD = gnu99; 212 | GCC_DYNAMIC_NO_PIC = NO; 213 | GCC_NO_COMMON_BLOCKS = YES; 214 | GCC_OPTIMIZATION_LEVEL = 0; 215 | GCC_PREPROCESSOR_DEFINITIONS = ( 216 | "DEBUG=1", 217 | "$(inherited)", 218 | ); 219 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 220 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 221 | GCC_WARN_UNDECLARED_SELECTOR = YES; 222 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 223 | GCC_WARN_UNUSED_FUNCTION = YES; 224 | GCC_WARN_UNUSED_VARIABLE = YES; 225 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 226 | MTL_ENABLE_DEBUG_INFO = YES; 227 | ONLY_ACTIVE_ARCH = YES; 228 | SDKROOT = iphoneos; 229 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 230 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 231 | TARGETED_DEVICE_FAMILY = "1,2"; 232 | VERSIONING_SYSTEM = "apple-generic"; 233 | VERSION_INFO_PREFIX = ""; 234 | }; 235 | name = Debug; 236 | }; 237 | 7C51410F1F34203600263E8A /* Release */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 242 | CLANG_ANALYZER_NONNULL = YES; 243 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_COMMA = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 253 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 254 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 255 | CLANG_WARN_EMPTY_BODY = YES; 256 | CLANG_WARN_ENUM_CONVERSION = YES; 257 | CLANG_WARN_INFINITE_RECURSION = YES; 258 | CLANG_WARN_INT_CONVERSION = YES; 259 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 261 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 262 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 263 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 264 | CLANG_WARN_STRICT_PROTOTYPES = YES; 265 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 266 | CLANG_WARN_UNREACHABLE_CODE = YES; 267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 269 | COPY_PHASE_STRIP = NO; 270 | CURRENT_PROJECT_VERSION = 1; 271 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 272 | ENABLE_NS_ASSERTIONS = NO; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | GCC_C_LANGUAGE_STANDARD = gnu99; 275 | GCC_NO_COMMON_BLOCKS = YES; 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 278 | GCC_WARN_UNDECLARED_SELECTOR = YES; 279 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 280 | GCC_WARN_UNUSED_FUNCTION = YES; 281 | GCC_WARN_UNUSED_VARIABLE = YES; 282 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 283 | MTL_ENABLE_DEBUG_INFO = NO; 284 | SDKROOT = iphoneos; 285 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 286 | TARGETED_DEVICE_FAMILY = "1,2"; 287 | VALIDATE_PRODUCT = YES; 288 | VERSIONING_SYSTEM = "apple-generic"; 289 | VERSION_INFO_PREFIX = ""; 290 | }; 291 | name = Release; 292 | }; 293 | 7C5141111F34203600263E8A /* Debug */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | CLANG_ENABLE_MODULES = YES; 297 | CODE_SIGN_IDENTITY = ""; 298 | DEFINES_MODULE = YES; 299 | DEVELOPMENT_TEAM = AZ5GBDWZ9H; 300 | DYLIB_COMPATIBILITY_VERSION = 1; 301 | DYLIB_CURRENT_VERSION = 1; 302 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 303 | FRAMEWORK_SEARCH_PATHS = ( 304 | "$(inherited)", 305 | "$(PROJECT_DIR)/Carthage/Build/iOS", 306 | ); 307 | HEADER_SEARCH_PATHS = "$(SRCROOT)/Pods"; 308 | INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; 309 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 310 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 311 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 312 | PRODUCT_BUNDLE_IDENTIFIER = com.joe.JKCalendar; 313 | PRODUCT_NAME = "$(TARGET_NAME)"; 314 | SKIP_INSTALL = YES; 315 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 316 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 317 | SWIFT_VERSION = 4.2; 318 | }; 319 | name = Debug; 320 | }; 321 | 7C5141121F34203600263E8A /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | CLANG_ENABLE_MODULES = YES; 325 | CODE_SIGN_IDENTITY = ""; 326 | DEFINES_MODULE = YES; 327 | DEVELOPMENT_TEAM = AZ5GBDWZ9H; 328 | DYLIB_COMPATIBILITY_VERSION = 1; 329 | DYLIB_CURRENT_VERSION = 1; 330 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 331 | FRAMEWORK_SEARCH_PATHS = ( 332 | "$(inherited)", 333 | "$(PROJECT_DIR)/Carthage/Build/iOS", 334 | ); 335 | HEADER_SEARCH_PATHS = "$(SRCROOT)/Pods"; 336 | INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; 337 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 338 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 339 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.joe.JKCalendar; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SKIP_INSTALL = YES; 343 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 344 | SWIFT_VERSION = 4.2; 345 | }; 346 | name = Release; 347 | }; 348 | /* End XCBuildConfiguration section */ 349 | 350 | /* Begin XCConfigurationList section */ 351 | 7C5141021F34203600263E8A /* Build configuration list for PBXProject "JKCalendar" */ = { 352 | isa = XCConfigurationList; 353 | buildConfigurations = ( 354 | 7C51410E1F34203600263E8A /* Debug */, 355 | 7C51410F1F34203600263E8A /* Release */, 356 | ); 357 | defaultConfigurationIsVisible = 0; 358 | defaultConfigurationName = Release; 359 | }; 360 | 7C5141101F34203600263E8A /* Build configuration list for PBXNativeTarget "JKCalendar" */ = { 361 | isa = XCConfigurationList; 362 | buildConfigurations = ( 363 | 7C5141111F34203600263E8A /* Debug */, 364 | 7C5141121F34203600263E8A /* Release */, 365 | ); 366 | defaultConfigurationIsVisible = 0; 367 | defaultConfigurationName = Release; 368 | }; 369 | /* End XCConfigurationList section */ 370 | }; 371 | rootObject = 7C5140FF1F34203600263E8A /* Project object */; 372 | } 373 | -------------------------------------------------------------------------------- /JKCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JKCalendar.xcodeproj/xcshareddata/xcschemes/JKCalendar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Joe Ciou 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | # JKCalendar 4 | ![](https://travis-ci.org/JoeCiou/JKCalendar.svg?branch=master) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Version](https://img.shields.io/cocoapods/v/JKCalendar.svg)](http://cocoadocs.org/docsets/JKCalendar) 7 | [![Platform](https://img.shields.io/cocoapods/p/JKCalendar.svg)](http://cocoadocs.org/docsets/JKCalendar) 8 | [![Swift 3.x](https://img.shields.io/badge/Swift-3.x-orange.svg?style=flat)](https://swift.org/) 9 | [![Swift 4.0](https://img.shields.io/badge/Swift-4.0-orange.svg?style=flat)](https://swift.org/) 10 | ## Screenshot 11 | 12 | 13 | ## Requirements 14 | - iOS 9.0+ 15 | - Xcode 8+ 16 | 17 | ## Installation 18 | #### CocoaPods 19 | To install add the following line to your `Podfile`: 20 | ```ruby 21 | pod 'JKCalendar' 22 | ``` 23 | 24 | #### Carthage 25 | To install add the following line to your `Cartfile`: 26 | ```ruby 27 | github "JoeCiou/JKCalendar" 28 | ``` 29 | 30 | ## Usage 31 | 32 | Firstley, import `JKCalendar` 33 | ```swift 34 | import JKCalendar 35 | ``` 36 | 37 | ### Initialization 38 | Then, there are to two ways you can create JKCalendar: 39 | - By storyboard, change class of any `UIView` to JKCalendar 40 | 41 | _**Note:** Set Module to `JKCalendar`._ 42 | 43 | - By code, using initializer. 44 | ```swift 45 | let calendar = JKCalendar(frame: frame) 46 | ``` 47 | 48 | ### Mark 49 | ```swift 50 | public enum JKCalendarMarkType{ 51 | case circle 52 | case hollowCircle 53 | case underline 54 | case dot 55 | } 56 | ``` 57 | For single mark: 58 | 59 | For continuous mark: 60 | 61 | 62 | #### Examples 63 | Firstley, Setup data source: 64 | ```swift 65 | calendar.dataSource = self 66 | ``` 67 | For single mark: 68 | ```swift 69 | func calendar(_ calendar: JKCalendar, marksWith month: JKMonth) -> [JKCalendarMark]? { 70 | let today = JKDay(date: Date()) 71 | if today == month{ 72 | return [JKCalendarMark(type: .underline, day: today, color: UIColor.red)] 73 | }else{ 74 | return nil 75 | } 76 | } 77 | ``` 78 | For continuous mark: 79 | ```swift 80 | func calendar(_ calendar: JKCalendar, continuousMarksWith month: JKMonth) -> [JKCalendarContinuousMark]?{ 81 | let markStartDay = JKDay(year: 2017, month: 9, day: 3)! 82 | let markEndDay = JKDay(year: 2017, month: 9, day: 12)! 83 | if markStartDay == month || markEndDay == month{ 84 | return [JKCalendarContinuousMark(type: .circle, start: markStartDay, end: markEndDay, color: UIColor.red)] 85 | }else{ 86 | return nil 87 | } 88 | } 89 | ``` 90 | 91 | ## License 92 | The MIT License (MIT) 93 | 94 | copyright (c) 2017 Joe Ciou 95 | 96 | 97 | -------------------------------------------------------------------------------- /Resources/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Resources/banner.png -------------------------------------------------------------------------------- /Resources/mark_type_continuous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Resources/mark_type_continuous.png -------------------------------------------------------------------------------- /Resources/mark_type_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Resources/mark_type_single.png -------------------------------------------------------------------------------- /Resources/page_video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Resources/page_video.gif -------------------------------------------------------------------------------- /Resources/scroll_video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Resources/scroll_video.gif -------------------------------------------------------------------------------- /Sources/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.1.4 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/JKCalendar.h: -------------------------------------------------------------------------------- 1 | // 2 | // JKCalendar.h 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | #import 26 | 27 | FOUNDATION_EXPORT double JKCalendarVersionNumber; 28 | FOUNDATION_EXPORT const unsigned char JKCalendarVersionString[]; 29 | -------------------------------------------------------------------------------- /Sources/JKCalendar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JKCalendar.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | import JKInfinitePageView 27 | 28 | public class JKCalendar: UIView { 29 | 30 | /** 31 | A gregorian calendar 32 | */ 33 | static public let calendar = Calendar(identifier: .gregorian) 34 | 35 | /** 36 | The object that acts as the delegate of the calendar view. 37 | 38 | The delegate must adopt the JKCalendarDelegate protocol. The calendar view maintains a weak reference to the delegate object. 39 | */ 40 | public weak var delegate: JKCalendarDelegate? 41 | 42 | /** 43 | The object that provides the marks data for the calendar view. 44 | 45 | The data source must adopt the JKCalendarDataSource protocol. The calendar view maintains a weak reference to the data source object. 46 | */ 47 | public weak var dataSource: JKCalendarDataSource? 48 | 49 | /** 50 | The status of the calendar view. 51 | */ 52 | public var status: JKCalendarViewStatus { 53 | if collapsedValue == collapsedMaximum { 54 | return .collapse 55 | } else if collapsedValue == 0 { 56 | return .expand 57 | } else { 58 | return .between 59 | } 60 | } 61 | 62 | /** 63 | The color of the day text. Default value for this property is a black color. 64 | */ 65 | public var textColor: UIColor = UIColor.black { 66 | didSet { 67 | reloadData() 68 | } 69 | } 70 | 71 | /** 72 | A Boolean value that determines whether scrolling is enabled. The default is true. 73 | */ 74 | public var isScrollEnabled: Bool = true { 75 | didSet { 76 | calendarPageView.isScrollEnabled = isScrollEnabled 77 | if let calendarView = calendarPageView.currentView as? JKCalendarView { 78 | calendarView.panRecognizer.isEnabled = !isScrollEnabled 79 | } 80 | } 81 | } 82 | 83 | /** 84 | This Boolean determines whether the calendar status is collapsed at initialization. The default is false. 85 | */ 86 | public var isInitializationCollapsed: Bool = false 87 | 88 | /** 89 | This Boolean determines whether the top view is displayed. The default is true. 90 | */ 91 | public var isTopViewDisplayed: Bool = true { 92 | didSet{ 93 | topView.isHidden = !isTopViewDisplayed 94 | weekViewTopConstraint.constant = isTopViewDisplayed ? 44: 0 95 | } 96 | } 97 | 98 | /** 99 | This Boolean determines whether nearby month button is displayed. The default is true. 100 | */ 101 | public var isNearbyMonthButtonDisplayed: Bool = true { 102 | didSet { 103 | previousButton.isHidden = !isNearbyMonthButtonDisplayed 104 | nextButton.isHidden = !isNearbyMonthButtonDisplayed 105 | } 106 | } 107 | 108 | /** 109 | A Boolean value that determines whether nearby month name is displayed. The default is true. 110 | */ 111 | public var isNearbyMonthNameDisplayed: Bool = true { 112 | didSet { 113 | previousButton.setTitle(isNearbyMonthNameDisplayed ? month.previous.name : nil, for: .normal) 114 | nextButton.setTitle(isNearbyMonthNameDisplayed ? month.next.name : nil, for: .normal) 115 | } 116 | } 117 | 118 | /** 119 | The calendar view is background color. The default value is nil, which results in a transparent background color. 120 | */ 121 | public override var backgroundColor: UIColor? { 122 | set { 123 | topView?.backgroundColor = newValue 124 | weekView?.backgroundColor = newValue 125 | calendarPageView?.backgroundColor = newValue 126 | calendarPageView?.currentView?.backgroundColor = newValue 127 | footerView?.backgroundColor = newValue 128 | } 129 | 130 | get { 131 | return calendarPageView?.backgroundColor 132 | } 133 | } 134 | 135 | /** 136 | The month object of the calendar view. The default is the current month. 137 | */ 138 | public var month: JKMonth { 139 | set { 140 | if let calendarView = calendarPageView.currentView as? JKCalendarView { 141 | calendarView.month = newValue 142 | } 143 | _month = newValue 144 | } 145 | 146 | get { 147 | return _month 148 | } 149 | } 150 | 151 | /** 152 | The property is the display week index of the calendar view in the folded state. 153 | */ 154 | public var focusWeek: Int{ 155 | set { 156 | if let calendarView = calendarPageView.currentView as? JKCalendarView { 157 | calendarView.focusWeek = newValue 158 | } 159 | } 160 | get { 161 | if let calendarView = calendarPageView.currentView as? JKCalendarView { 162 | return calendarView.focusWeek 163 | } else { 164 | return 0 165 | } 166 | } 167 | } 168 | 169 | var _month: JKMonth = JKMonth()! { 170 | didSet { 171 | let weekCount = month.weeksCount 172 | collapsedMaximum = pageViewHeightConstraint.constant * CGFloat(weekCount - 1) / CGFloat(weekCount) 173 | setupLabels() 174 | delegate?.calendar?(self, didChangedMonth: _month) 175 | } 176 | } 177 | 178 | var collapsedValue: CGFloat = 0 { 179 | didSet{ 180 | if let calendarView = calendarPageView.currentView as? JKCalendarView, 181 | calendarView.collapsedValue != collapsedValue { 182 | calendarView.collapsedValue = collapsedValue 183 | contentViewBottomConstraint.constant = collapsedValue 184 | 185 | previousButton.setTitleColor(previousButton.titleColor(for: .normal)!.withAlphaComponent(1 - collapsedValue / collapsedMaximum), for: .normal) 186 | nextButton.setTitleColor(nextButton.titleColor(for: .normal)!.withAlphaComponent(1 - collapsedValue / collapsedMaximum), for: .normal) 187 | 188 | if collapsedValue == 0 && oldValue != collapsedValue { 189 | delegate?.calendar?(self, didChangedStatus: .expand) 190 | calendarPageView.isScrollEnabled = true 191 | } else if collapsedValue == collapsedMaximum && oldValue != collapsedValue { 192 | delegate?.calendar?(self, didChangedStatus: .collapse) 193 | calendarPageView.isScrollEnabled = true 194 | } else if (collapsedValue != 0 && oldValue == 0) || (collapsedValue != collapsedMaximum && oldValue == collapsedMaximum) { 195 | delegate?.calendar?(self, didChangedStatus: .between) 196 | calendarPageView.isScrollEnabled = false 197 | } 198 | } 199 | } 200 | } 201 | 202 | var collapsedMaximum: CGFloat = 0 203 | 204 | fileprivate var contentViewBottomConstraint: NSLayoutConstraint! 205 | 206 | private var first = true 207 | 208 | weak var interactionObject: UIScrollView? 209 | 210 | @IBOutlet weak var topView: UIView! 211 | @IBOutlet weak var weekView: UIView! 212 | @IBOutlet weak var calendarPageView: JKInfinitePageView! 213 | @IBOutlet weak var footerView: UIView! 214 | 215 | @IBOutlet weak var monthLabel: UILabel! 216 | @IBOutlet weak var yearLabel: UILabel! 217 | @IBOutlet weak var previousButton: UIButton! 218 | @IBOutlet weak var nextButton: UIButton! 219 | @IBOutlet weak var leftContentView: UIView! 220 | @IBOutlet weak var rightContentView: UIView! 221 | 222 | @IBOutlet weak var pageViewHeightConstraint: NSLayoutConstraint! 223 | @IBOutlet weak var weekViewTopConstraint: NSLayoutConstraint! 224 | @IBOutlet weak var footerViewHeightConstraint: NSLayoutConstraint! 225 | 226 | public override init(frame: CGRect) { 227 | super.init(frame: frame) 228 | setupContentViewUI() 229 | setupCalendarView() 230 | } 231 | 232 | public required init?(coder aDecoder: NSCoder) { 233 | super.init(coder: aDecoder) 234 | setupContentViewUI() 235 | setupCalendarView() 236 | } 237 | 238 | public override func layoutSubviews() { 239 | super.layoutSubviews() 240 | 241 | let footerHeight = delegate?.heightOfFooterView?(in: self) ?? 0 242 | footerViewHeightConstraint.constant = footerHeight 243 | 244 | if let view = delegate?.viewOfFooter?(in: self), 245 | footerView.subviews.count == 0 { 246 | footerView.addSubview(view) 247 | view.translatesAutoresizingMaskIntoConstraints = false 248 | 249 | let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: .directionLeadingToTrailing, metrics: nil, views: ["view": view]) 250 | let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: .directionLeadingToTrailing, metrics: nil, views: ["view": view]) 251 | addConstraints(horizontalConstraints) 252 | addConstraints(verticalConstraints) 253 | } 254 | 255 | let pageViewHeight = frame.height - weekViewTopConstraint.constant - weekView.frame.height - footerHeight 256 | pageViewHeightConstraint.constant = pageViewHeight > 0 ? pageViewHeight: 0 257 | 258 | let weekCount = month.weeksCount 259 | let maximum = pageViewHeightConstraint.constant * CGFloat(weekCount - 1) / CGFloat(weekCount) 260 | if first { 261 | collapsedMaximum = maximum 262 | if isInitializationCollapsed { 263 | if let object = interactionObject { 264 | object.setContentOffset(CGPoint(x: 0, y: collapsedMaximum - bounds.height), animated: false) 265 | } else { 266 | collapsedValue = maximum 267 | } 268 | } 269 | first = false 270 | }else{ 271 | // handle changed of collapsed maximum 272 | if maximum != collapsedMaximum && collapsedValue == collapsedMaximum { 273 | if let object = interactionObject{ 274 | object.setContentOffset(CGPoint(x: 0, y: collapsedMaximum - bounds.height), animated: false) 275 | } else { 276 | collapsedValue = maximum 277 | } 278 | } 279 | collapsedMaximum = maximum 280 | } 281 | 282 | if let view = calendarPageView.currentView as? JKCalendarView { 283 | view.setNeedsDisplay() 284 | } 285 | } 286 | 287 | func setupContentViewUI() { 288 | let bundle = Bundle(for: type(of: self)) 289 | let nib = UINib(nibName: "JKCalendar", bundle: bundle) 290 | 291 | let contentView = nib.instantiate(withOwner: self, options: nil)[0] as! UIView 292 | contentView.translatesAutoresizingMaskIntoConstraints = false 293 | contentView.backgroundColor = backgroundColor 294 | addSubview(contentView) 295 | 296 | let topConstraint = NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0) 297 | contentViewBottomConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 0) 298 | 299 | let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[contentView]|", options: .directionLeadingToTrailing, metrics: nil, views: ["contentView": contentView]) 300 | 301 | addConstraint(topConstraint) 302 | addConstraint(contentViewBottomConstraint) 303 | addConstraints(horizontalConstraints) 304 | } 305 | 306 | func setupCalendarView() { 307 | calendarPageView.delegate = self 308 | calendarPageView.dataSource = self 309 | 310 | let calendarView = JKCalendarView(calendar: self, month: month) 311 | calendarView.backgroundColor = backgroundColor 312 | calendarView.panRecognizer.isEnabled = !isScrollEnabled 313 | calendarPageView.setView(calendarView) 314 | 315 | setupLabels() 316 | } 317 | 318 | func setupLabels() { 319 | monthLabel.text = month.name 320 | yearLabel.text = "\(month.year)" 321 | 322 | previousButton.setTitle(isNearbyMonthNameDisplayed ? month.previous.name : nil, for: .normal) 323 | nextButton.setTitle(isNearbyMonthNameDisplayed ? month.next.name : nil, for: .normal) 324 | } 325 | 326 | public func setLeftCustomView(_ view: UIView) { 327 | isNearbyMonthButtonDisplayed = false 328 | 329 | leftContentView.addSubview(view) 330 | view.translatesAutoresizingMaskIntoConstraints = false 331 | 332 | addConstraint(view.centerXAnchor.constraint(equalTo: leftContentView.centerXAnchor)) 333 | addConstraint(view.centerYAnchor.constraint(equalTo: leftContentView.centerYAnchor)) 334 | 335 | let widthConstraint = view.widthAnchor.constraint(equalTo: leftContentView.widthAnchor) 336 | widthConstraint.priority = UILayoutPriority.defaultHigh 337 | addConstraint(widthConstraint) 338 | 339 | let heightConstraint = view.heightAnchor.constraint(equalTo: leftContentView.heightAnchor) 340 | heightConstraint.priority = UILayoutPriority.defaultHigh 341 | addConstraint(heightConstraint) 342 | } 343 | 344 | public func setRightCustomView(_ view: UIView) { 345 | isNearbyMonthButtonDisplayed = false 346 | 347 | rightContentView.addSubview(view) 348 | view.translatesAutoresizingMaskIntoConstraints = false 349 | 350 | addConstraint(view.centerXAnchor.constraint(equalTo: rightContentView.centerXAnchor)) 351 | addConstraint(view.centerYAnchor.constraint(equalTo: rightContentView.centerYAnchor)) 352 | 353 | let widthConstraint = view.widthAnchor.constraint(equalTo: rightContentView.widthAnchor) 354 | widthConstraint.priority = UILayoutPriority.defaultHigh 355 | addConstraint(widthConstraint) 356 | 357 | let heightConstraint = view.heightAnchor.constraint(equalTo: rightContentView.heightAnchor) 358 | heightConstraint.priority = UILayoutPriority.defaultHigh 359 | addConstraint(heightConstraint) 360 | } 361 | 362 | /** 363 | Reloads all of the marks data for the calendar view. 364 | */ 365 | public func reloadData() { 366 | if let calendarView = calendarPageView.currentView as? JKCalendarView{ 367 | calendarView.resetWeeksInfo() 368 | calendarView.setNeedsDisplay() 369 | } 370 | } 371 | 372 | /** 373 | Collapsed up the calendar view. 374 | 375 | - Parameters: 376 | - animated: True to animate the transition at a constant velocity to the collapsed status, false to make the transition immediate. 377 | */ 378 | public func collapse(animated: Bool) { 379 | if let object = interactionObject{ 380 | object.setContentOffset(CGPoint(x: 0, y: collapsedMaximum - bounds.height), animated: animated) 381 | }else{ 382 | if animated{ 383 | continuouslyChangeCollapsedValue(destination: collapsedMaximum, duration: 0.2) 384 | } else { 385 | collapsedValue = collapsedMaximum 386 | } 387 | } 388 | } 389 | 390 | /** 391 | expanded up the calendar view. 392 | 393 | - Parameters: 394 | - animated: True to animate the transition at a constant velocity to the expanded status, false to make the transition immediate. 395 | */ 396 | public func expand(animated: Bool) { 397 | if let object = interactionObject{ 398 | object.setContentOffset(CGPoint(x: 0, y: -bounds.height), animated: animated) 399 | }else{ 400 | if animated { 401 | continuouslyChangeCollapsedValue(destination: 0, duration: 0.2) 402 | } else { 403 | collapsedValue = 0 404 | } 405 | } 406 | } 407 | 408 | func continuouslyChangeCollapsedValue(destination: CGFloat, duration: Double){ 409 | let timer = Timer(timeInterval: 0.02, 410 | target: self, 411 | selector: #selector(handleStatusChangeTimer(_:)), 412 | userInfo: ["source": collapsedValue, 413 | "destination": destination, 414 | "duration": duration, 415 | "startDate": Date()], 416 | repeats: true) 417 | RunLoop.current.add(timer, forMode: RunLoop.Mode.common) 418 | } 419 | 420 | @objc 421 | func handleStatusChangeTimer(_ timer: Timer){ 422 | if let userInfo = timer.userInfo as? [String: Any], 423 | let source = userInfo["source"] as? CGFloat, 424 | let destination = userInfo["destination"] as? CGFloat, 425 | let duration = userInfo["duration"] as? Double, 426 | let startDate = userInfo["startDate"] as? Date { 427 | 428 | let elapsing = Date().timeIntervalSince1970 - startDate.timeIntervalSince1970 429 | collapsedValue = source + (destination - source) * CGFloat(elapsing >= duration ? 1: elapsing / duration) 430 | 431 | if collapsedValue == destination{ 432 | timer.invalidate() 433 | } 434 | } else { 435 | timer.invalidate() 436 | } 437 | } 438 | 439 | /** 440 | Move the calendar view to the next month or week 441 | */ 442 | public func next() { 443 | calendarPageView.nextPage() 444 | } 445 | 446 | /** 447 | Move the calendar view to the previous month or week 448 | */ 449 | public func previous() { 450 | calendarPageView.previousPage() 451 | } 452 | 453 | public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 454 | let result = super.hitTest(point, with: event) 455 | if result == self { return nil } 456 | return result 457 | } 458 | 459 | @IBAction func handleNextButtonClick(_ sender: Any) { 460 | next() 461 | } 462 | 463 | @IBAction func handlePreviousButtonClick(_ sender: Any) { 464 | previous() 465 | } 466 | } 467 | 468 | extension JKCalendar: JKInfinitePageViewDelegate { 469 | public func infinitePageView(_ infinitePageView: JKInfinitePageView, afterWith view: UIView, progress: Double) { 470 | let calendarView = view as! JKCalendarView 471 | let currentCalendarView = infinitePageView.currentView! as! JKCalendarView 472 | 473 | if status == .collapse && calendarView.month == currentCalendarView.month{ 474 | return 475 | } 476 | 477 | let nextMonth = calendarView.month 478 | let acrossYear = nextMonth.previous.year != nextMonth.year 479 | let centerX = self.frame.width / 2 480 | 481 | if progress < 0.5{ 482 | _month = nextMonth.previous 483 | let newPositionX = centerX - monthLabel.frame.width * CGFloat(progress) 484 | let alpha = CGFloat(1 - progress * 2) 485 | 486 | monthLabel.alpha = alpha 487 | monthLabel.layer.position = CGPoint(x: newPositionX, y: monthLabel.center.y) 488 | 489 | if acrossYear{ 490 | yearLabel.alpha = alpha 491 | yearLabel.layer.position = CGPoint(x: newPositionX, y: yearLabel.center.y) 492 | }else{ 493 | yearLabel.alpha = 1 494 | yearLabel.layer.position = CGPoint(x: centerX, y: yearLabel.center.y) 495 | } 496 | }else{ 497 | _month = nextMonth 498 | let newPositionX = centerX + monthLabel.frame.width * CGFloat(1 - progress) 499 | let alpha = CGFloat((progress - 0.5) * 2) 500 | 501 | monthLabel.alpha = alpha 502 | monthLabel.layer.position = CGPoint(x: newPositionX, y: monthLabel.center.y) 503 | 504 | if acrossYear{ 505 | yearLabel.alpha = alpha 506 | yearLabel.layer.position = CGPoint(x: newPositionX, y: yearLabel.center.y) 507 | }else{ 508 | yearLabel.alpha = 1 509 | yearLabel.layer.position = CGPoint(x: centerX, y: yearLabel.center.y) 510 | } 511 | } 512 | } 513 | 514 | public func infinitePageView(_ infinitePageView: JKInfinitePageView, beforeWith view: UIView, progress: Double) { 515 | let calendarView = view as! JKCalendarView 516 | let currentCalendarView = infinitePageView.currentView! as! JKCalendarView 517 | 518 | if status == .collapse && calendarView.month == currentCalendarView.month{ 519 | return 520 | } 521 | 522 | let previousMonth = calendarView.month 523 | let acrossYear = previousMonth.next.year != previousMonth.year 524 | let centerX = self.frame.width / 2 525 | 526 | if progress < 0.5{ 527 | _month = previousMonth.next 528 | let newPositionX = centerX + monthLabel.frame.width * CGFloat(progress) 529 | let alpha = CGFloat(1 - progress * 2) 530 | 531 | monthLabel.alpha = alpha 532 | monthLabel.layer.position = CGPoint(x: newPositionX, y: monthLabel.center.y) 533 | 534 | if acrossYear{ 535 | yearLabel.alpha = alpha 536 | yearLabel.layer.position = CGPoint(x: newPositionX, y: yearLabel.center.y) 537 | }else{ 538 | yearLabel.alpha = 1 539 | yearLabel.layer.position = CGPoint(x: centerX, y: yearLabel.center.y) 540 | } 541 | }else{ 542 | _month = previousMonth 543 | let newPositionX = centerX - monthLabel.frame.width * CGFloat(1 - progress) 544 | let alpha = CGFloat((progress - 0.5) * 2) 545 | 546 | monthLabel.alpha = alpha 547 | monthLabel.layer.position = CGPoint(x: newPositionX, y: monthLabel.center.y) 548 | 549 | if acrossYear{ 550 | yearLabel.alpha = alpha 551 | yearLabel.layer.position = CGPoint(x: newPositionX, y: yearLabel.center.y) 552 | }else{ 553 | yearLabel.alpha = 1 554 | yearLabel.layer.position = CGPoint(x: centerX, y: yearLabel.center.y) 555 | } 556 | } 557 | } 558 | } 559 | 560 | extension JKCalendar: JKInfinitePageViewDataSource{ 561 | 562 | public func infinitePageView(_ infinitePageView: JKInfinitePageView, viewBefore view: UIView) -> UIView { 563 | let view = view as! JKCalendarView 564 | 565 | var calendarView: JKCalendarView! 566 | if status == .expand { 567 | calendarView = JKCalendarView(calendar: self, month: view.month.previous) 568 | calendarView.focusWeek = focusWeek >= calendarView.month.weeksCount ? calendarView.month.weeksCount - 1: focusWeek 569 | } else if focusWeek - 1 >= 0 { 570 | calendarView = JKCalendarView(calendar: self, month: view.month) 571 | calendarView.focusWeek = focusWeek - 1 572 | } else { 573 | calendarView = JKCalendarView(calendar: self, month: view.month.previous) 574 | calendarView.focusWeek = view.month.previous.weeksCount - 1 575 | } 576 | calendarView.backgroundColor = backgroundColor 577 | calendarView.collapsedValue = collapsedValue 578 | calendarView.panRecognizer.isEnabled = !isScrollEnabled 579 | 580 | return calendarView 581 | } 582 | 583 | public func infinitePageView(_ infinitePageView: JKInfinitePageView, viewAfter view: UIView) -> UIView { 584 | let view = view as! JKCalendarView 585 | 586 | var calendarView: JKCalendarView! 587 | if status == .expand { 588 | calendarView = JKCalendarView(calendar: self, month: view.month.next) 589 | calendarView.focusWeek = focusWeek >= calendarView.month.weeksCount ? calendarView.month.weeksCount - 1: focusWeek 590 | } else if focusWeek + 1 < view.month.weeksCount { 591 | calendarView = JKCalendarView(calendar: self, month: view.month) 592 | calendarView.focusWeek = focusWeek + 1 593 | } else { 594 | calendarView = JKCalendarView(calendar: self, month: view.month.next) 595 | calendarView.focusWeek = 0 596 | } 597 | 598 | calendarView.backgroundColor = backgroundColor 599 | calendarView.collapsedValue = collapsedValue 600 | calendarView.panRecognizer.isEnabled = !isScrollEnabled 601 | 602 | return calendarView 603 | } 604 | } 605 | 606 | @objc public protocol JKCalendarDelegate { 607 | 608 | @objc optional func calendar(_ calendar: JKCalendar, didTouch day: JKDay) 609 | 610 | @objc optional func calendar(_ calendar: JKCalendar, didPan days: [JKDay]) 611 | 612 | @objc optional func calendar(_ calendar: JKCalendar, didChangedStatus status: JKCalendarViewStatus) 613 | 614 | @objc optional func calendar(_ calendar: JKCalendar, didChangedMonth month: JKMonth) 615 | 616 | @objc optional func heightOfFooterView(in calendar: JKCalendar) -> CGFloat 617 | 618 | @objc optional func viewOfFooter(in calendar: JKCalendar) -> UIView? 619 | } 620 | 621 | @objc public protocol JKCalendarDataSource{ 622 | 623 | @objc optional func calendar(_ calendar: JKCalendar, marksWith month: JKMonth) -> [JKCalendarMark]? 624 | 625 | @objc optional func calendar(_ calendar: JKCalendar, continuousMarksWith month: JKMonth) -> [JKCalendarContinuousMark]? 626 | } 627 | 628 | -------------------------------------------------------------------------------- /Sources/JKCalendar.xib: -------------------------------------------------------------------------------- 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 | 44 | 50 | 56 | 62 | 68 | 74 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 156 | 173 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /Sources/JKCalendarMark.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JKCalendarMark.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | 27 | public enum JKCalendarMarkType { 28 | case circle 29 | case hollowCircle 30 | case underline 31 | case dot 32 | } 33 | 34 | public class JKCalendarMarkObject: NSObject { 35 | 36 | let type: JKCalendarMarkType 37 | let color: UIColor 38 | 39 | init(type: JKCalendarMarkType, color: UIColor) { 40 | self.type = type 41 | self.color = color 42 | super.init() 43 | } 44 | } 45 | 46 | public class JKCalendarMark: JKCalendarMarkObject { 47 | 48 | public let day: JKDay 49 | 50 | public init(type: JKCalendarMarkType, day: JKDay, color: UIColor) { 51 | self.day = day 52 | super.init(type: type, color: color) 53 | } 54 | } 55 | 56 | public class JKCalendarContinuousMark: JKCalendarMarkObject { 57 | public let start: JKDay 58 | public let end: JKDay 59 | public let days: [JKDay] 60 | 61 | public init(type: JKCalendarMarkType, start: JKDay, end: JKDay, color: UIColor) { 62 | self.start = start 63 | self.end = end 64 | self.days = start.days(until: end) 65 | super.init(type: type, color: color) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/JKCalendarScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JKCalendarScrollView.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | 27 | public class JKCalendarScrollView: UIScrollView { 28 | 29 | public let calendar: JKCalendar = JKCalendar(frame: CGRect.zero) 30 | public weak var nativeDelegate: UIScrollViewDelegate? 31 | 32 | public var startsCollapsed: Bool = false 33 | private var first = true 34 | private var rotating = false 35 | 36 | override public init(frame: CGRect) { 37 | super.init(frame: frame) 38 | setup() 39 | } 40 | 41 | required public init?(coder aDecoder: NSCoder) { 42 | super.init(coder: aDecoder) 43 | setup() 44 | } 45 | 46 | func setup() { 47 | super.delegate = self 48 | calendar.interactionObject = self 49 | 50 | NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: UIDevice.orientationDidChangeNotification, object: nil) 51 | } 52 | 53 | override open func layoutSubviews() { 54 | super.layoutSubviews() 55 | layoutSubviewsHandler() 56 | } 57 | 58 | func layoutSubviewsHandler() { 59 | if first || rotating{ 60 | var calendarSize: CGSize! 61 | let footerHeight = calendar.delegate?.heightOfFooterView?(in: calendar) ?? 0 62 | if frame.width > frame.height { 63 | let height = ((calendar.isTopViewDisplayed ? calendar.topView.frame.height: 0) + calendar.weekView.frame.height + frame.width * 0.35 + footerHeight).rounded() 64 | calendarSize = CGSize(width: frame.width, 65 | height: height) 66 | } else { 67 | let height = ((calendar.isTopViewDisplayed ? calendar.topView.frame.height: 0) + calendar.weekView.frame.height + frame.width * 0.65 + footerHeight).rounded() 68 | calendarSize = CGSize(width: frame.width, 69 | height: height) 70 | } 71 | 72 | calendar.frame = CGRect(x: 0, 73 | y: frame.origin.y, 74 | width: calendarSize.width, 75 | height: calendarSize.height) 76 | 77 | contentInset = UIEdgeInsets(top: calendarSize.height, 78 | left: 0, 79 | bottom: 0, 80 | right: 0) 81 | 82 | scrollIndicatorInsets = UIEdgeInsets(top: calendarSize.height, 83 | left: 0, 84 | bottom: 0, 85 | right: 0) 86 | 87 | contentOffset = CGPoint(x: 0, y: -calendarSize.height) 88 | rotating = false 89 | 90 | if first { 91 | superview?.insertSubview(calendar, aboveSubview: self) 92 | first = false 93 | } 94 | } 95 | } 96 | 97 | @objc 98 | func rotated() { 99 | if !first { 100 | rotating = true 101 | layoutSubviewsHandler() 102 | } 103 | } 104 | } 105 | 106 | extension JKCalendarScrollView: UIScrollViewDelegate { 107 | public func scrollViewDidScroll(_ scrollView: UIScrollView) { 108 | 109 | var value = calendar.frame.height + contentOffset.y 110 | if value > calendar.collapsedMaximum { 111 | value = calendar.collapsedMaximum 112 | } else if value < 0 { 113 | value = 0 114 | } 115 | 116 | calendar.collapsedValue = value 117 | 118 | nativeDelegate?.scrollViewDidScroll?(scrollView) 119 | } 120 | 121 | public func scrollViewDidZoom(_ scrollView: UIScrollView) { 122 | nativeDelegate?.scrollViewDidZoom?(scrollView) 123 | } 124 | 125 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 126 | nativeDelegate?.scrollViewWillBeginDragging?(scrollView) 127 | } 128 | 129 | public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { 130 | 131 | let value = (targetContentOffset.pointee.y + calendar.bounds.height) / calendar.collapsedMaximum 132 | 133 | if value < 1 { 134 | targetContentOffset.pointee.y = (value > 0.5 ? calendar.collapsedMaximum : 0) - calendar.bounds.height 135 | } 136 | 137 | nativeDelegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset) 138 | } 139 | 140 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 141 | nativeDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) 142 | } 143 | 144 | public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { 145 | nativeDelegate?.scrollViewWillBeginDecelerating?(scrollView) 146 | } 147 | 148 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 149 | nativeDelegate?.scrollViewDidEndDecelerating?(scrollView) 150 | } 151 | 152 | public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { 153 | nativeDelegate?.scrollViewDidEndScrollingAnimation?(scrollView) 154 | } 155 | 156 | public func viewForZooming(in scrollView: UIScrollView) -> UIView? { 157 | return nativeDelegate?.viewForZooming?(in: scrollView) 158 | } 159 | 160 | public func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { 161 | nativeDelegate?.scrollViewWillBeginZooming?(scrollView, with: view) 162 | } 163 | 164 | public func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { 165 | nativeDelegate?.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale) 166 | } 167 | 168 | public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { 169 | return nativeDelegate?.scrollViewShouldScrollToTop?(scrollView) != nil ? nativeDelegate!.scrollViewShouldScrollToTop!(scrollView): true 170 | } 171 | 172 | public func scrollViewDidScrollToTop(_ scrollView: UIScrollView) { 173 | nativeDelegate?.scrollViewDidScrollToTop?(scrollView) 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /Sources/JKCalendarTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JKCalendarTableView.swift 3 | // JKCalendar 4 | // 5 | // Created by Joe on 2017/9/7. 6 | // Copyright © 2017年 Joe. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class JKCalendarTableView: UITableView { 12 | 13 | public let calendar: JKCalendar = JKCalendar(frame: CGRect.zero) 14 | public weak var nativeDelegate: UITableViewDelegate? 15 | 16 | private var first = true 17 | private var rotating = false 18 | 19 | override public init(frame: CGRect, style: UITableView.Style) { 20 | super.init(frame: frame, style: style) 21 | setup() 22 | } 23 | 24 | required public init?(coder aDecoder: NSCoder) { 25 | super.init(coder: aDecoder) 26 | setup() 27 | } 28 | 29 | func setup(){ 30 | super.delegate = self 31 | calendar.backgroundColor = UIColor.white 32 | calendar.interactionObject = self 33 | 34 | NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: UIDevice.orientationDidChangeNotification, object: nil) 35 | } 36 | 37 | override open func layoutSubviews() { 38 | super.layoutSubviews() 39 | layoutSubviewsHandler() 40 | } 41 | 42 | func layoutSubviewsHandler(){ 43 | if first || rotating{ 44 | var calendarSize: CGSize! 45 | let footerHeight = calendar.delegate?.heightOfFooterView?(in: calendar) ?? 0 46 | if frame.width > frame.height { 47 | let height = ((calendar.isTopViewDisplayed ? calendar.topView.frame.height: 0) + calendar.weekView.frame.height + frame.width * 0.35 + footerHeight).rounded() 48 | calendarSize = CGSize(width: frame.width, 49 | height: height) 50 | } else { 51 | let height = ((calendar.isTopViewDisplayed ? calendar.topView.frame.height: 0) + calendar.weekView.frame.height + frame.width * 0.65 + footerHeight).rounded() 52 | calendarSize = CGSize(width: frame.width, 53 | height: height) 54 | } 55 | 56 | calendar.frame = CGRect(x: 0, 57 | y: frame.origin.y, 58 | width: calendarSize.width, 59 | height: calendarSize.height) 60 | 61 | contentInset = UIEdgeInsets(top: calendarSize.height, 62 | left: 0, 63 | bottom: 0, 64 | right: 0) 65 | 66 | scrollIndicatorInsets = UIEdgeInsets(top: calendarSize.height, 67 | left: 0, 68 | bottom: 0, 69 | right: 0) 70 | 71 | contentOffset = CGPoint(x: 0, y: -calendarSize.height) 72 | rotating = false 73 | 74 | if first{ 75 | superview?.insertSubview(calendar, aboveSubview: self) 76 | first = false 77 | } 78 | } 79 | } 80 | 81 | @objc 82 | func rotated(){ 83 | if !first{ 84 | rotating = true 85 | layoutSubviewsHandler() 86 | } 87 | } 88 | 89 | } 90 | 91 | extension JKCalendarTableView: UITableViewDelegate{ 92 | 93 | public func scrollViewDidScroll(_ scrollView: UIScrollView) { 94 | 95 | var value = calendar.frame.height + contentOffset.y 96 | if value > calendar.collapsedMaximum { 97 | value = calendar.collapsedMaximum 98 | }else if value < 0{ 99 | value = 0 100 | } 101 | 102 | calendar.collapsedValue = value 103 | 104 | nativeDelegate?.scrollViewDidScroll?(scrollView) 105 | } 106 | 107 | public func scrollViewDidZoom(_ scrollView: UIScrollView) { 108 | nativeDelegate?.scrollViewDidZoom?(scrollView) 109 | } 110 | 111 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 112 | nativeDelegate?.scrollViewWillBeginDragging?(scrollView) 113 | } 114 | 115 | public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { 116 | 117 | let value = (targetContentOffset.pointee.y + calendar.bounds.height) / calendar.collapsedMaximum 118 | 119 | if value < 1{ 120 | targetContentOffset.pointee.y = (value > 0.5 ? calendar.collapsedMaximum: 0) - calendar.bounds.height 121 | } 122 | 123 | nativeDelegate?.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset) 124 | } 125 | 126 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 127 | nativeDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) 128 | } 129 | 130 | public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { 131 | nativeDelegate?.scrollViewWillBeginDecelerating?(scrollView) 132 | } 133 | 134 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 135 | nativeDelegate?.scrollViewDidEndDecelerating?(scrollView) 136 | } 137 | 138 | public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { 139 | nativeDelegate?.scrollViewDidEndScrollingAnimation?(scrollView) 140 | } 141 | 142 | public func viewForZooming(in scrollView: UIScrollView) -> UIView? { 143 | return nativeDelegate?.viewForZooming?(in: scrollView) 144 | } 145 | 146 | public func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { 147 | nativeDelegate?.scrollViewWillBeginZooming?(scrollView, with: view) 148 | } 149 | 150 | public func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { 151 | nativeDelegate?.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale) 152 | } 153 | 154 | public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { 155 | return nativeDelegate?.scrollViewShouldScrollToTop?(scrollView) != nil ? nativeDelegate!.scrollViewShouldScrollToTop!(scrollView): true 156 | } 157 | 158 | public func scrollViewDidScrollToTop(_ scrollView: UIScrollView) { 159 | nativeDelegate?.scrollViewDidScrollToTop?(scrollView) 160 | } 161 | 162 | // MARK: Table View Delegate 163 | 164 | public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath){ 165 | nativeDelegate?.tableView?(tableView, willDisplay: cell, forRowAt: indexPath) 166 | } 167 | 168 | public func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){ 169 | nativeDelegate?.tableView?(tableView, willDisplayHeaderView: view, forSection: section) 170 | } 171 | 172 | 173 | public func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int){ 174 | nativeDelegate?.tableView?(tableView, willDisplayFooterView: view, forSection: section) 175 | } 176 | 177 | public func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath){ 178 | nativeDelegate?.tableView?(tableView, didEndDisplaying: cell, forRowAt: indexPath) 179 | } 180 | 181 | public func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int){ 182 | nativeDelegate?.tableView?(tableView, didEndDisplayingHeaderView: view, forSection: section) 183 | } 184 | 185 | public func tableView(_ tableView: UITableView, didEndDisplayingFooterView view: UIView, forSection section: Int){ 186 | nativeDelegate?.tableView?(tableView, didEndDisplayingFooterView: view, forSection: section) 187 | } 188 | 189 | public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{ 190 | return nativeDelegate?.tableView?(tableView, heightForRowAt: indexPath) ?? tableView.rowHeight 191 | } 192 | 193 | public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{ 194 | return nativeDelegate?.tableView?(tableView, heightForHeaderInSection: section) ?? tableView.sectionHeaderHeight 195 | } 196 | 197 | public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{ 198 | return nativeDelegate?.tableView?(tableView, heightForFooterInSection: section) ?? tableView.sectionFooterHeight 199 | } 200 | 201 | public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat{ 202 | return nativeDelegate?.tableView?(tableView, estimatedHeightForRowAt: indexPath) ?? tableView.estimatedRowHeight 203 | } 204 | 205 | public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat{ 206 | return nativeDelegate?.tableView?(tableView, estimatedHeightForHeaderInSection: section) ?? tableView.estimatedSectionHeaderHeight 207 | } 208 | 209 | public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat{ 210 | return nativeDelegate?.tableView?(tableView, estimatedHeightForFooterInSection: section) ?? tableView.estimatedSectionFooterHeight 211 | } 212 | 213 | public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{ 214 | return nativeDelegate?.tableView?(tableView, viewForHeaderInSection: section) ?? tableView.tableHeaderView 215 | } 216 | 217 | public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?{ 218 | return nativeDelegate?.tableView?(tableView, viewForFooterInSection: section) ?? tableView.tableFooterView 219 | } 220 | 221 | public func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath){ 222 | nativeDelegate?.tableView?(tableView, accessoryButtonTappedForRowWith: indexPath) 223 | } 224 | 225 | public func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool{ 226 | return nativeDelegate?.tableView?(tableView, shouldHighlightRowAt: indexPath) ?? true 227 | } 228 | 229 | public func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath){ 230 | nativeDelegate?.tableView?(tableView, didHighlightRowAt: indexPath) 231 | } 232 | 233 | public func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath){ 234 | nativeDelegate?.tableView?(tableView, didUnhighlightRowAt: indexPath) 235 | } 236 | 237 | public func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?{ 238 | return nativeDelegate?.tableView?(tableView, willSelectRowAt: indexPath) ?? indexPath 239 | } 240 | 241 | public func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath?{ 242 | return nativeDelegate?.tableView?(tableView, willDeselectRowAt: indexPath) ?? indexPath 243 | } 244 | 245 | public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){ 246 | nativeDelegate?.tableView?(tableView, didSelectRowAt: indexPath) 247 | } 248 | 249 | public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath){ 250 | nativeDelegate?.tableView?(tableView, didDeselectRowAt: indexPath) 251 | } 252 | 253 | public func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle{ 254 | return nativeDelegate?.tableView?(tableView, editingStyleForRowAt: indexPath) ?? (tableView.isEditing ? .delete: .none) 255 | } 256 | 257 | public func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String?{ 258 | return nativeDelegate?.tableView?(tableView, titleForDeleteConfirmationButtonForRowAt: indexPath) ?? nil 259 | } 260 | 261 | public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?{ 262 | return nativeDelegate?.tableView?(tableView, editActionsForRowAt: indexPath) ?? nil 263 | } 264 | 265 | public func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool{ 266 | return nativeDelegate?.tableView?(tableView, shouldIndentWhileEditingRowAt: indexPath) ?? true 267 | } 268 | 269 | public func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath){ 270 | nativeDelegate?.tableView?(tableView, willBeginEditingRowAt: indexPath) 271 | } 272 | 273 | public func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?){ 274 | nativeDelegate?.tableView?(tableView, didEndEditingRowAt: indexPath) 275 | } 276 | 277 | public func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath{ 278 | return nativeDelegate?.tableView?(tableView, targetIndexPathForMoveFromRowAt: sourceIndexPath, toProposedIndexPath: proposedDestinationIndexPath) ?? proposedDestinationIndexPath 279 | } 280 | 281 | public func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int{ 282 | return nativeDelegate?.tableView?(tableView, indentationLevelForRowAt: indexPath) ?? 0 283 | } 284 | 285 | public func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool{ 286 | return nativeDelegate?.tableView?(tableView, shouldShowMenuForRowAt: indexPath) ?? false 287 | } 288 | 289 | public func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool{ 290 | return nativeDelegate?.tableView?(tableView, canPerformAction: action, forRowAt: indexPath, withSender: sender) ?? false 291 | } 292 | 293 | public func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?){ 294 | nativeDelegate?.tableView?(tableView, performAction: action, forRowAt: indexPath, withSender: sender) 295 | } 296 | 297 | public func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool{ 298 | return nativeDelegate?.tableView?(tableView, canFocusRowAt: indexPath) ?? false 299 | } 300 | 301 | public func tableView(_ tableView: UITableView, shouldUpdateFocusIn context: UITableViewFocusUpdateContext) -> Bool{ 302 | return nativeDelegate?.tableView?(tableView, shouldUpdateFocusIn: context) ?? false 303 | } 304 | 305 | public func tableView(_ tableView: UITableView, didUpdateFocusIn context: UITableViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator){ 306 | nativeDelegate?.tableView?(tableView, didUpdateFocusIn: context, with: coordinator) 307 | } 308 | 309 | public func indexPathForPreferredFocusedView(in tableView: UITableView) -> IndexPath?{ 310 | return nativeDelegate?.indexPathForPreferredFocusedView?(in: tableView) ?? nil 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /Sources/common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // common.swift 3 | // 4 | // Copyright © 2017 Joe Ciou. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import UIKit 26 | 27 | public class JKYear: NSObject, Comparable { 28 | public let year: Int 29 | 30 | public init?(year: Int) { 31 | if year < 0{ 32 | return nil 33 | } 34 | self.year = year 35 | } 36 | 37 | override public func isEqual(_ object: Any?) -> Bool { 38 | if let object = object as? JKYear{ 39 | return object == self 40 | }else{ 41 | return false 42 | } 43 | } 44 | 45 | public static func == (lhs: JKYear, rhs: JKYear) -> Bool { 46 | return lhs.year == rhs.year 47 | } 48 | 49 | public static func != (lhs: JKYear, rhs: JKYear) -> Bool { 50 | return lhs.year != rhs.year 51 | } 52 | 53 | public static func < (lhs: JKYear, rhs: JKYear) -> Bool { 54 | return lhs.year < rhs.year 55 | } 56 | 57 | public static func <= (lhs: JKYear, rhs: JKYear) -> Bool { 58 | return lhs.year <= rhs.year 59 | } 60 | 61 | public static func > (lhs: JKYear, rhs: JKYear) -> Bool { 62 | return lhs.year > rhs.year 63 | } 64 | 65 | public static func >= (lhs: JKYear, rhs: JKYear) -> Bool { 66 | return lhs.year >= rhs.year 67 | } 68 | } 69 | 70 | public class JKMonth: JKYear { 71 | public let month: Int 72 | 73 | public init?(year: Int = Date().year, month: Int = Date().month) { 74 | if month < 0 || month > 12 { return nil } 75 | self.month = month 76 | super.init(year: year) 77 | } 78 | 79 | public var next: JKMonth { 80 | var year = self.year 81 | var month = self.month + 1 82 | if month > 12{ 83 | year += 1 84 | month = 1 85 | } 86 | return JKMonth(year: year, month: month)! 87 | } 88 | 89 | public var previous: JKMonth { 90 | var year = self.year 91 | var month = self.month - 1 92 | if month < 1 { 93 | year -= 1 94 | month = 12 95 | } 96 | return JKMonth(year: year, month: month)! 97 | } 98 | 99 | public var firstDay: JKDay{ 100 | return JKDay(year: year, month: month, day: 1)! 101 | } 102 | 103 | public var lastDay: JKDay{ 104 | let date = JKCalendar.calendar.date(byAdding: DateComponents(month: 1, day: -1), to: firstDay.date)! 105 | return JKDay(year: date.year, month: date.month, day: date.day)! 106 | } 107 | 108 | public var daysCount: Int { 109 | return lastDay.day 110 | } 111 | 112 | public var weeksCount: Int { 113 | return Int(ceil(Double(daysCount + firstDay.weekday - 1) / 7)) 114 | } 115 | 116 | public func weeks() -> [JKWeek] { 117 | var weeks: [JKWeek] = [] 118 | let weekday = firstDay.weekday - 1 119 | var offsetDay = firstDay.previous(weekday) 120 | while offsetDay <= self { 121 | weeks.append(offsetDay.week()) 122 | offsetDay = offsetDay.next(7) 123 | } 124 | return weeks 125 | } 126 | 127 | public var name: String { 128 | guard let date = JKCalendar.calendar.date(from: DateComponents(year: year, month: month)) else { 129 | return "" 130 | } 131 | 132 | let dateFormatter = DateFormatter() 133 | dateFormatter.dateFormat = "MMMM" 134 | 135 | return dateFormatter.string(from: date) 136 | } 137 | 138 | override public func isEqual(_ object: Any?) -> Bool { 139 | if let object = object as? JKMonth{ 140 | return object == self 141 | }else{ 142 | return false 143 | } 144 | } 145 | 146 | public static func == (lhs: JKMonth, rhs: JKMonth) -> Bool { 147 | return lhs.year == rhs.year && lhs.month == rhs.month 148 | } 149 | 150 | public static func != (lhs: JKMonth, rhs: JKMonth) -> Bool { 151 | return lhs.year != rhs.year || lhs.month != rhs.month 152 | } 153 | 154 | public static func < (lhs: JKMonth, rhs: JKMonth) -> Bool { 155 | return lhs.year < rhs.year || (lhs.year == rhs.year && lhs.month < rhs.month) 156 | } 157 | 158 | public static func <= (lhs: JKMonth, rhs: JKMonth) -> Bool { 159 | return lhs.year < rhs.year || (lhs.year == rhs.year && lhs.month <= rhs.month) 160 | } 161 | 162 | public static func > (lhs: JKMonth, rhs: JKMonth) -> Bool { 163 | return lhs.year > rhs.year || (lhs.year == rhs.year && lhs.month > rhs.month) 164 | } 165 | 166 | public static func >= (lhs: JKMonth, rhs: JKMonth) -> Bool { 167 | return lhs.year > rhs.year || (lhs.year == rhs.year && lhs.month >= rhs.month) 168 | } 169 | } 170 | 171 | public class JKDay: JKMonth { 172 | public let day: Int 173 | 174 | public init?(year: Int, month: Int, day: Int) { 175 | guard let _ = JKCalendar.calendar.date(from: DateComponents(year: year, 176 | month: month, 177 | day: day)) else { 178 | return nil 179 | } 180 | self.day = day 181 | super.init(year: year, month: month) 182 | } 183 | 184 | convenience public init(date: Date) { 185 | let year = date.year 186 | let month = date.month 187 | let day = date.day 188 | self.init(year: year, month: month, day: day)! 189 | } 190 | 191 | public var date: Date { 192 | return JKCalendar.calendar.date(from: DateComponents(year: year, 193 | month: month, 194 | day: day))! 195 | } 196 | 197 | public var weekday: Int { 198 | return date.week 199 | } 200 | 201 | public var weekOfMonth: Int { 202 | return date.weekOfMonth 203 | } 204 | 205 | public var weekOfYear: Int { 206 | return date.weekOfYear 207 | } 208 | 209 | public func week() -> JKWeek{ 210 | return JKWeek(sunday: self.previous(weekday - 1)) 211 | } 212 | 213 | public func next(_ count: Int = 1) -> JKDay{ 214 | let components = DateComponents(day: count) 215 | return JKDay(date: JKCalendar.calendar.date(byAdding: components, to: date)!) 216 | } 217 | 218 | public func previous(_ count: Int = 1) -> JKDay{ 219 | let components = DateComponents(day: -count) 220 | return JKDay(date: JKCalendar.calendar.date(byAdding: components, to: date)!) 221 | } 222 | 223 | public func days(until: JKDay) -> [JKDay] { 224 | let (start, end) = self < until ? (self, until): (until, self) 225 | 226 | var days: [JKDay] = [start] 227 | var offsetDay = start 228 | 229 | while offsetDay != end { 230 | offsetDay = offsetDay.next() 231 | days.append(offsetDay) 232 | } 233 | return days 234 | } 235 | 236 | override public func isEqual(_ object: Any?) -> Bool { 237 | if let object = object as? JKDay{ 238 | return object == self 239 | }else{ 240 | return false 241 | } 242 | } 243 | 244 | public static func == (lhs: JKDay, rhs: JKDay) -> Bool { 245 | return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day 246 | } 247 | 248 | public static func != (lhs: JKDay, rhs: JKDay) -> Bool { 249 | return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day 250 | } 251 | 252 | public static func < (lhs: JKDay, rhs: JKDay) -> Bool { 253 | return lhs.year < rhs.year || 254 | (lhs.year == rhs.year && (lhs.month < rhs.month || (lhs.month == rhs.month && lhs.day < rhs.day))) 255 | } 256 | 257 | public static func <= (lhs: JKDay, rhs: JKDay) -> Bool { 258 | return lhs.year < rhs.year || 259 | (lhs.year == rhs.year && (lhs.month < rhs.month || (lhs.month == rhs.month && lhs.day <= rhs.day))) 260 | } 261 | 262 | public static func > (lhs: JKDay, rhs: JKDay) -> Bool { 263 | return lhs.year > rhs.year || 264 | (lhs.year == rhs.year && (lhs.month > rhs.month || (lhs.month == rhs.month && lhs.day > rhs.day))) 265 | } 266 | 267 | public static func >= (lhs: JKDay, rhs: JKDay) -> Bool { 268 | return lhs.year > rhs.year || 269 | (lhs.year == rhs.year && (lhs.month > rhs.month || (lhs.month == rhs.month && lhs.day >= rhs.day))) 270 | } 271 | } 272 | 273 | public class JKWeek{ 274 | 275 | public let sunday: JKDay 276 | 277 | public var monday: JKDay{ 278 | return sunday.next(1) 279 | } 280 | 281 | public var tuesday: JKDay{ 282 | return sunday.next(2) 283 | } 284 | 285 | public var wednesday: JKDay{ 286 | return sunday.next(3) 287 | } 288 | 289 | public var thursday: JKDay{ 290 | return sunday.next(4) 291 | } 292 | 293 | public var friday: JKDay{ 294 | return sunday.next(5) 295 | } 296 | 297 | public var staturday: JKDay{ 298 | return sunday.next(6) 299 | } 300 | 301 | public init(sunday: JKDay) { 302 | self.sunday = sunday 303 | } 304 | 305 | public func contains(_ day: JKDay) -> Bool { 306 | return day >= sunday && day <= staturday 307 | } 308 | } 309 | 310 | public func == (lhs: JKWeek, rhs: JKWeek) -> Bool { 311 | return lhs.sunday == rhs.sunday 312 | } 313 | 314 | public func != (lhs: JKWeek, rhs: JKWeek) -> Bool { 315 | return lhs.sunday != rhs.sunday 316 | } 317 | 318 | @objc public enum JKCalendarViewStatus: Int { 319 | case collapse = 0 320 | case between 321 | case expand 322 | } 323 | 324 | public extension Date { 325 | var day: Int { 326 | return JKCalendar.calendar.component(.day, from: self) 327 | } 328 | 329 | var week: Int { 330 | return JKCalendar.calendar.component(.weekday, from: self) 331 | } 332 | 333 | var month: Int { 334 | return JKCalendar.calendar.component(.month, from: self) 335 | } 336 | 337 | var year: Int { 338 | return JKCalendar.calendar.component(.year, from: self) 339 | } 340 | 341 | var weekOfMonth: Int { 342 | return JKCalendar.calendar.component(.weekOfMonth, from: self) 343 | } 344 | 345 | var weekOfYear: Int { 346 | return JKCalendar.calendar.component(.weekOfYear, from: self) 347 | } 348 | } 349 | 350 | -------------------------------------------------------------------------------- /Sources/icon.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_left.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "arrow_left.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "arrow_left@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "arrow_left@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left.png -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left@2x.png -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_left.imageset/arrow_left@3x.png -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_right.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "arrow_right.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "arrow_right@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "arrow_right@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right.png -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right@2x.png -------------------------------------------------------------------------------- /Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoeCiou/JKCalendar/5a5870068bd5562b4800748ee0c1991406a80264/Sources/icon.xcassets/ic_arrow_right.imageset/arrow_right@3x.png --------------------------------------------------------------------------------