├── .DS_Store ├── .gitignore ├── Podfile ├── Podfile.lock ├── Pods ├── Manifest.lock ├── Pods.xcodeproj │ └── project.pbxproj ├── SkeletonView │ ├── LICENSE │ ├── README.md │ └── Sources │ │ ├── Collections │ │ ├── CollectionSkeletonProtocol.swift │ │ ├── CollectionViews │ │ │ ├── SkeletonCollectionViewProtocols.swift │ │ │ └── UICollectionView+CollectionSkeleton.swift │ │ ├── Generics │ │ │ ├── GenericCollectionView.swift │ │ │ └── SkeletonReusableCell.swift │ │ ├── SkeletonCollectionDataSource.swift │ │ ├── SkeletonCollectionDelegate.swift │ │ ├── TableViews │ │ │ ├── SkeletonTableViewProtocols.swift │ │ │ └── UITableView+CollectionSkeleton.swift │ │ └── UIView+CollectionSkeleton.swift │ │ ├── Extensions │ │ ├── CALayer+Extensions.swift │ │ ├── UIColor+Skeleton.swift │ │ ├── UIView+Frame.swift │ │ ├── UIView+IBInspectable.swift │ │ └── UIView+UIApplicationDelegate.swift │ │ ├── Helpers │ │ ├── AssociationPolicy.swift │ │ ├── ContainsMultilineText.swift │ │ ├── PrepareForSkeletonProtocol.swift │ │ └── RecursiveProtocol.swift │ │ ├── SkeletonAnimationBuilder.swift │ │ ├── SkeletonDefaultConfig.swift │ │ ├── SkeletonFlow.swift │ │ ├── SkeletonGradient.swift │ │ ├── SkeletonLayer.swift │ │ └── SkeletonView.swift └── Target Support Files │ ├── Pods-SkeletonDemo │ ├── Info.plist │ ├── Pods-SkeletonDemo-acknowledgements.markdown │ ├── Pods-SkeletonDemo-acknowledgements.plist │ ├── Pods-SkeletonDemo-dummy.m │ ├── Pods-SkeletonDemo-frameworks.sh │ ├── Pods-SkeletonDemo-resources.sh │ ├── Pods-SkeletonDemo-umbrella.h │ ├── Pods-SkeletonDemo.debug.xcconfig │ ├── Pods-SkeletonDemo.modulemap │ └── Pods-SkeletonDemo.release.xcconfig │ └── SkeletonView │ ├── Info.plist │ ├── SkeletonView-dummy.m │ ├── SkeletonView-prefix.pch │ ├── SkeletonView-umbrella.h │ ├── SkeletonView.modulemap │ └── SkeletonView.xcconfig ├── README.md ├── SkeletonDemo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SkeletonDemo.xcworkspace └── contents.xcworkspacedata ├── SkeletonDemo ├── .DS_Store ├── AppDelegate.swift ├── Assets.xcassets │ ├── .DS_Store │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── 经典.imageset │ │ ├── Contents.json │ │ └── 经典@2x.png │ └── 经典@2x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CustomCell.swift ├── CustomCell.xib ├── HeaderVeiw.swift ├── Info.plist └── ViewController.swift ├── SkeletonDemoTests ├── Info.plist └── SkeletonDemoTests.swift └── SkeletonDemoUITests ├── Info.plist └── SkeletonDemoUITests.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daomoer/SkeletonDemo/a5987fb574098dfa34fbda2a01cc9bbbdc5fd663/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios,'9.0' 2 | target 'SkeletonDemo' do 3 | use_frameworks! 4 | 5 | pod 'SkeletonView' 6 | 7 | end 8 | 9 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SkeletonView (1.2) 3 | 4 | DEPENDENCIES: 5 | - SkeletonView 6 | 7 | SPEC CHECKSUMS: 8 | SkeletonView: d68962d45d1af038f6a110d2274b183df8f82752 9 | 10 | PODFILE CHECKSUM: 8fb21c6a68fb523b53ddd4d7877d1977658fb200 11 | 12 | COCOAPODS: 1.3.1 13 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SkeletonView (1.2) 3 | 4 | DEPENDENCIES: 5 | - SkeletonView 6 | 7 | SPEC CHECKSUMS: 8 | SkeletonView: d68962d45d1af038f6a110d2274b183df8f82752 9 | 10 | PODFILE CHECKSUM: 8fb21c6a68fb523b53ddd4d7877d1977658fb200 11 | 12 | COCOAPODS: 1.3.1 13 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0821A0FB10F930234E449A0117E15743 /* UIView+CollectionSkeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64603B1271C07D8AE4013C3EEFCB4007 /* UIView+CollectionSkeleton.swift */; }; 11 | 0C18C6758EAAC7EEEF1C20EDACB14461 /* PrepareForSkeletonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 333CD41CC0856179162D085F8B750C33 /* PrepareForSkeletonProtocol.swift */; }; 12 | 14F76443F848C1AD1E6184C1A8088A10 /* SkeletonCollectionViewProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECA2C53C180E8928AC522EEBA0A48D4 /* SkeletonCollectionViewProtocols.swift */; }; 13 | 15345DEE41436B4D5141F41346226099 /* AssociationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE150461C08125A6618A11FCF3FB9A94 /* AssociationPolicy.swift */; }; 14 | 1F0853C12BA4D9089926951C39CDF18C /* SkeletonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50575677E3F1758E6ACC77137D0C17E3 /* SkeletonView.swift */; }; 15 | 244A98B0738EBE5C9A8B7E40185C9EBF /* RecursiveProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ACB65862D9656CFD584B999CE0839FE /* RecursiveProtocol.swift */; }; 16 | 272DD095161AF3929E2A195437B40E94 /* ContainsMultilineText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE4C97535B2795F64900E3F912CED03 /* ContainsMultilineText.swift */; }; 17 | 2FF492A8E341B1CCB46F1BE301612EFD /* UIView+Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = E79D5E00C1E6E323D483BF74095B7A31 /* UIView+Frame.swift */; }; 18 | 30CB37141129792700793A309B5B7422 /* SkeletonReusableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 839758AD9B240155F6EEEB3B26AD7DBA /* SkeletonReusableCell.swift */; }; 19 | 3601D473A28AD20928F03418AC4BD709 /* CALayer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B340E93748EC56135D612383C00E66CC /* CALayer+Extensions.swift */; }; 20 | 3894E3CC802288F1D5311C20A8F4959C /* Pods-SkeletonDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 937040CD27045E1E30B019D35769C8B6 /* Pods-SkeletonDemo-dummy.m */; }; 21 | 4223CBBE76307A50C35F238C1CBDA311 /* GenericCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA2FA288FBB7D93951D6DAB05557031 /* GenericCollectionView.swift */; }; 22 | 49575AC0C3C414A7037C3297FEBF72DB /* UIColor+Skeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35EA6FB9AE8E21EE5FC96EDFC68AA280 /* UIColor+Skeleton.swift */; }; 23 | 56D3465D40663F59F768FF7F765039AA /* UIView+UIApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AAD0C475F77447D023D1983D923F3D /* UIView+UIApplicationDelegate.swift */; }; 24 | 6275570CA76D38637B2064C9D99DFAC1 /* SkeletonDefaultConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45C869F88FCEB5FA4E1450332922B60 /* SkeletonDefaultConfig.swift */; }; 25 | 68C2EB093254CC78B4B2D99F733DF0AF /* UICollectionView+CollectionSkeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF98EC3E5F156E623B51B08DAC83B58 /* UICollectionView+CollectionSkeleton.swift */; }; 26 | 71B7B3E9C9583BA11890CBD0F2375C25 /* CollectionSkeletonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3B04C8869F9EAB483D96EFA33CA35D /* CollectionSkeletonProtocol.swift */; }; 27 | 90FF8305A893C7798C38092AD6B952B5 /* SkeletonFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1AD772F1DB00F89C2EE6B823F7B926 /* SkeletonFlow.swift */; }; 28 | 9974E7F97B2BB629E1CA004C32BB07B4 /* SkeletonGradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39BB2AC6E93B75D257F239AE7022532A /* SkeletonGradient.swift */; }; 29 | 9DDD423250D9F6F0F08A161B65C50450 /* SkeletonView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 40586D48A8875296B8403BC0A250325B /* SkeletonView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | A6A75815D8D020D14760844C8FBEC718 /* SkeletonAnimationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3514964E3511FC1E22C02BA5E62E2429 /* SkeletonAnimationBuilder.swift */; }; 31 | B386BE27F5CC5091271840487A93E9D3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; 32 | B4D08FD046931116469A337152FD7A99 /* UIView+IBInspectable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C589F2BA3611473D82BCC7BB6F663D9C /* UIView+IBInspectable.swift */; }; 33 | BA9465793D9DA8E250498FFC0B6F0C0C /* SkeletonCollectionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A65DE22DB8E5F1BE0579B657B2ED8EE /* SkeletonCollectionDataSource.swift */; }; 34 | C1B9E18733A99A61AE0C43EAFBBBBD07 /* UITableView+CollectionSkeleton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4B4902C5612D26A5CA7FA5FEFF851E /* UITableView+CollectionSkeleton.swift */; }; 35 | C1E98E7EE9D5B28511394F7D45BEAAE3 /* SkeletonCollectionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9800866DC4C133B74FBDBA38509F1399 /* SkeletonCollectionDelegate.swift */; }; 36 | C5F13488070D5DA922D69B3B99FC353B /* Pods-SkeletonDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = FAFDA4AEFCBF9AA0D9ABB0A6C3B186BE /* Pods-SkeletonDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | D26522E300514466D61D258CEF0B13BD /* SkeletonLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8909699751EFA39005A075027B564BE5 /* SkeletonLayer.swift */; }; 38 | DA0A264CCAD63F103BE7B8BFAE14DE4D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; 39 | DE324F92C19E4CF1522E3A4C85A884DD /* SkeletonTableViewProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C53E242DEBD86606F770DE445FAA2E3 /* SkeletonTableViewProtocols.swift */; }; 40 | E010BF69780C58A48457608E9A335FE8 /* SkeletonView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A7D3E0EDCF7BA742B9B98B8A9F23A51 /* SkeletonView-dummy.m */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXContainerItemProxy section */ 44 | FD22359C1DBCE1E2846113F7B63C99BD /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = 9175D2F10D001CD0918070A3F05E1FB3; 49 | remoteInfo = SkeletonView; 50 | }; 51 | /* End PBXContainerItemProxy section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 0037854F006E93DDF646520D260D464F /* SkeletonView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = SkeletonView.modulemap; sourceTree = ""; }; 55 | 0ECA2C53C180E8928AC522EEBA0A48D4 /* SkeletonCollectionViewProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonCollectionViewProtocols.swift; path = Sources/Collections/CollectionViews/SkeletonCollectionViewProtocols.swift; sourceTree = ""; }; 56 | 22FC26B78BE10F43566CF988C6A7AA26 /* SkeletonView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SkeletonView.framework; path = SkeletonView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 25C81AC1ED288EE55D924BA21E659249 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | 2D1AD772F1DB00F89C2EE6B823F7B926 /* SkeletonFlow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonFlow.swift; path = Sources/SkeletonFlow.swift; sourceTree = ""; }; 59 | 333CD41CC0856179162D085F8B750C33 /* PrepareForSkeletonProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PrepareForSkeletonProtocol.swift; path = Sources/Helpers/PrepareForSkeletonProtocol.swift; sourceTree = ""; }; 60 | 3514964E3511FC1E22C02BA5E62E2429 /* SkeletonAnimationBuilder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonAnimationBuilder.swift; path = Sources/SkeletonAnimationBuilder.swift; sourceTree = ""; }; 61 | 35EA6FB9AE8E21EE5FC96EDFC68AA280 /* UIColor+Skeleton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIColor+Skeleton.swift"; path = "Sources/Extensions/UIColor+Skeleton.swift"; sourceTree = ""; }; 62 | 39BB2AC6E93B75D257F239AE7022532A /* SkeletonGradient.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonGradient.swift; path = Sources/SkeletonGradient.swift; sourceTree = ""; }; 63 | 3A65DE22DB8E5F1BE0579B657B2ED8EE /* SkeletonCollectionDataSource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonCollectionDataSource.swift; path = Sources/Collections/SkeletonCollectionDataSource.swift; sourceTree = ""; }; 64 | 3BB0F01E70ACBBA1D06CDE6BFDD7547C /* Pods-SkeletonDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-SkeletonDemo.modulemap"; sourceTree = ""; }; 65 | 40586D48A8875296B8403BC0A250325B /* SkeletonView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SkeletonView-umbrella.h"; sourceTree = ""; }; 66 | 45BD865C3A84FA25B011707CB71EF264 /* Pods-SkeletonDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SkeletonDemo-acknowledgements.markdown"; sourceTree = ""; }; 67 | 4C53E242DEBD86606F770DE445FAA2E3 /* SkeletonTableViewProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonTableViewProtocols.swift; path = Sources/Collections/TableViews/SkeletonTableViewProtocols.swift; sourceTree = ""; }; 68 | 50575677E3F1758E6ACC77137D0C17E3 /* SkeletonView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonView.swift; path = Sources/SkeletonView.swift; sourceTree = ""; }; 69 | 50AAD0C475F77447D023D1983D923F3D /* UIView+UIApplicationDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+UIApplicationDelegate.swift"; path = "Sources/Extensions/UIView+UIApplicationDelegate.swift"; sourceTree = ""; }; 70 | 5DE4C97535B2795F64900E3F912CED03 /* ContainsMultilineText.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ContainsMultilineText.swift; path = Sources/Helpers/ContainsMultilineText.swift; sourceTree = ""; }; 71 | 64603B1271C07D8AE4013C3EEFCB4007 /* UIView+CollectionSkeleton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+CollectionSkeleton.swift"; path = "Sources/Collections/UIView+CollectionSkeleton.swift"; sourceTree = ""; }; 72 | 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 73 | 7FF98EC3E5F156E623B51B08DAC83B58 /* UICollectionView+CollectionSkeleton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UICollectionView+CollectionSkeleton.swift"; path = "Sources/Collections/CollectionViews/UICollectionView+CollectionSkeleton.swift"; sourceTree = ""; }; 74 | 839758AD9B240155F6EEEB3B26AD7DBA /* SkeletonReusableCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonReusableCell.swift; path = Sources/Collections/Generics/SkeletonReusableCell.swift; sourceTree = ""; }; 75 | 85DA67253D48FE830E38E71F57C40098 /* SkeletonView.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SkeletonView.xcconfig; sourceTree = ""; }; 76 | 8909699751EFA39005A075027B564BE5 /* SkeletonLayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonLayer.swift; path = Sources/SkeletonLayer.swift; sourceTree = ""; }; 77 | 8A7D3E0EDCF7BA742B9B98B8A9F23A51 /* SkeletonView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SkeletonView-dummy.m"; sourceTree = ""; }; 78 | 8ACB65862D9656CFD584B999CE0839FE /* RecursiveProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RecursiveProtocol.swift; path = Sources/Helpers/RecursiveProtocol.swift; sourceTree = ""; }; 79 | 8BFBA416115F14EE816C8B4CD0F731C5 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 80 | 937040CD27045E1E30B019D35769C8B6 /* Pods-SkeletonDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SkeletonDemo-dummy.m"; sourceTree = ""; }; 81 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 82 | 9800866DC4C133B74FBDBA38509F1399 /* SkeletonCollectionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonCollectionDelegate.swift; path = Sources/Collections/SkeletonCollectionDelegate.swift; sourceTree = ""; }; 83 | A187E7A450E9DEFE653D4A84CC52A88A /* Pods-SkeletonDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SkeletonDemo.release.xcconfig"; sourceTree = ""; }; 84 | AB508E3A761B2E92B236BBD59D542E7B /* Pods-SkeletonDemo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SkeletonDemo-resources.sh"; sourceTree = ""; }; 85 | AE150461C08125A6618A11FCF3FB9A94 /* AssociationPolicy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssociationPolicy.swift; path = Sources/Helpers/AssociationPolicy.swift; sourceTree = ""; }; 86 | B340E93748EC56135D612383C00E66CC /* CALayer+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "CALayer+Extensions.swift"; path = "Sources/Extensions/CALayer+Extensions.swift"; sourceTree = ""; }; 87 | B948EBA8264CB57F13BD5D77E3C3B253 /* Pods_SkeletonDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_SkeletonDemo.framework; path = "Pods-SkeletonDemo.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | C589F2BA3611473D82BCC7BB6F663D9C /* UIView+IBInspectable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+IBInspectable.swift"; path = "Sources/Extensions/UIView+IBInspectable.swift"; sourceTree = ""; }; 89 | CAA2FA288FBB7D93951D6DAB05557031 /* GenericCollectionView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GenericCollectionView.swift; path = Sources/Collections/Generics/GenericCollectionView.swift; sourceTree = ""; }; 90 | CF3B04C8869F9EAB483D96EFA33CA35D /* CollectionSkeletonProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CollectionSkeletonProtocol.swift; path = Sources/Collections/CollectionSkeletonProtocol.swift; sourceTree = ""; }; 91 | D2A56A409ABB8E7F9B54D8FCFDDF13C6 /* Pods-SkeletonDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SkeletonDemo.debug.xcconfig"; sourceTree = ""; }; 92 | D45C869F88FCEB5FA4E1450332922B60 /* SkeletonDefaultConfig.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SkeletonDefaultConfig.swift; path = Sources/SkeletonDefaultConfig.swift; sourceTree = ""; }; 93 | D6FC1AB5BA7089445A421297A61C74D3 /* SkeletonView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SkeletonView-prefix.pch"; sourceTree = ""; }; 94 | DB8CD860DFB6204C5242B0B90B05735F /* Pods-SkeletonDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SkeletonDemo-acknowledgements.plist"; sourceTree = ""; }; 95 | E444B15D7FEFCF2178E2163C46F15997 /* Pods-SkeletonDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SkeletonDemo-frameworks.sh"; sourceTree = ""; }; 96 | E79D5E00C1E6E323D483BF74095B7A31 /* UIView+Frame.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIView+Frame.swift"; path = "Sources/Extensions/UIView+Frame.swift"; sourceTree = ""; }; 97 | FA4B4902C5612D26A5CA7FA5FEFF851E /* UITableView+CollectionSkeleton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UITableView+CollectionSkeleton.swift"; path = "Sources/Collections/TableViews/UITableView+CollectionSkeleton.swift"; sourceTree = ""; }; 98 | FAFDA4AEFCBF9AA0D9ABB0A6C3B186BE /* Pods-SkeletonDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-SkeletonDemo-umbrella.h"; sourceTree = ""; }; 99 | /* End PBXFileReference section */ 100 | 101 | /* Begin PBXFrameworksBuildPhase section */ 102 | 535A91CFC1BB2D61820F91C035C5A7E3 /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | DA0A264CCAD63F103BE7B8BFAE14DE4D /* Foundation.framework in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | B3F8722BE18D4EA0ECC9D9CA70D79FD1 /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | B386BE27F5CC5091271840487A93E9D3 /* Foundation.framework in Frameworks */, 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | /* End PBXFrameworksBuildPhase section */ 119 | 120 | /* Begin PBXGroup section */ 121 | 00C1BB3448DCD19F851DC9B6E3A0D932 /* Pods-SkeletonDemo */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 25C81AC1ED288EE55D924BA21E659249 /* Info.plist */, 125 | 3BB0F01E70ACBBA1D06CDE6BFDD7547C /* Pods-SkeletonDemo.modulemap */, 126 | 45BD865C3A84FA25B011707CB71EF264 /* Pods-SkeletonDemo-acknowledgements.markdown */, 127 | DB8CD860DFB6204C5242B0B90B05735F /* Pods-SkeletonDemo-acknowledgements.plist */, 128 | 937040CD27045E1E30B019D35769C8B6 /* Pods-SkeletonDemo-dummy.m */, 129 | E444B15D7FEFCF2178E2163C46F15997 /* Pods-SkeletonDemo-frameworks.sh */, 130 | AB508E3A761B2E92B236BBD59D542E7B /* Pods-SkeletonDemo-resources.sh */, 131 | FAFDA4AEFCBF9AA0D9ABB0A6C3B186BE /* Pods-SkeletonDemo-umbrella.h */, 132 | D2A56A409ABB8E7F9B54D8FCFDDF13C6 /* Pods-SkeletonDemo.debug.xcconfig */, 133 | A187E7A450E9DEFE653D4A84CC52A88A /* Pods-SkeletonDemo.release.xcconfig */, 134 | ); 135 | name = "Pods-SkeletonDemo"; 136 | path = "Target Support Files/Pods-SkeletonDemo"; 137 | sourceTree = ""; 138 | }; 139 | 2D017A2718181BC64EFF99811082E0A8 /* Support Files */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 8BFBA416115F14EE816C8B4CD0F731C5 /* Info.plist */, 143 | 0037854F006E93DDF646520D260D464F /* SkeletonView.modulemap */, 144 | 85DA67253D48FE830E38E71F57C40098 /* SkeletonView.xcconfig */, 145 | 8A7D3E0EDCF7BA742B9B98B8A9F23A51 /* SkeletonView-dummy.m */, 146 | D6FC1AB5BA7089445A421297A61C74D3 /* SkeletonView-prefix.pch */, 147 | 40586D48A8875296B8403BC0A250325B /* SkeletonView-umbrella.h */, 148 | ); 149 | name = "Support Files"; 150 | path = "../Target Support Files/SkeletonView"; 151 | sourceTree = ""; 152 | }; 153 | 7DB346D0F39D3F0E887471402A8071AB = { 154 | isa = PBXGroup; 155 | children = ( 156 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 157 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 158 | B98EEC70BA2CDD738CD19EB1E04C800D /* Pods */, 159 | A08861C686222A069BAFEE6942BD4BC4 /* Products */, 160 | 957C96CBFBFE1147235650EACDF06C6B /* Targets Support Files */, 161 | ); 162 | sourceTree = ""; 163 | }; 164 | 90F7380DE9394FA7BAE63D8E51674075 /* SkeletonView */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | AE150461C08125A6618A11FCF3FB9A94 /* AssociationPolicy.swift */, 168 | B340E93748EC56135D612383C00E66CC /* CALayer+Extensions.swift */, 169 | CF3B04C8869F9EAB483D96EFA33CA35D /* CollectionSkeletonProtocol.swift */, 170 | 5DE4C97535B2795F64900E3F912CED03 /* ContainsMultilineText.swift */, 171 | CAA2FA288FBB7D93951D6DAB05557031 /* GenericCollectionView.swift */, 172 | 333CD41CC0856179162D085F8B750C33 /* PrepareForSkeletonProtocol.swift */, 173 | 8ACB65862D9656CFD584B999CE0839FE /* RecursiveProtocol.swift */, 174 | 3514964E3511FC1E22C02BA5E62E2429 /* SkeletonAnimationBuilder.swift */, 175 | 3A65DE22DB8E5F1BE0579B657B2ED8EE /* SkeletonCollectionDataSource.swift */, 176 | 9800866DC4C133B74FBDBA38509F1399 /* SkeletonCollectionDelegate.swift */, 177 | 0ECA2C53C180E8928AC522EEBA0A48D4 /* SkeletonCollectionViewProtocols.swift */, 178 | D45C869F88FCEB5FA4E1450332922B60 /* SkeletonDefaultConfig.swift */, 179 | 2D1AD772F1DB00F89C2EE6B823F7B926 /* SkeletonFlow.swift */, 180 | 39BB2AC6E93B75D257F239AE7022532A /* SkeletonGradient.swift */, 181 | 8909699751EFA39005A075027B564BE5 /* SkeletonLayer.swift */, 182 | 839758AD9B240155F6EEEB3B26AD7DBA /* SkeletonReusableCell.swift */, 183 | 4C53E242DEBD86606F770DE445FAA2E3 /* SkeletonTableViewProtocols.swift */, 184 | 50575677E3F1758E6ACC77137D0C17E3 /* SkeletonView.swift */, 185 | 7FF98EC3E5F156E623B51B08DAC83B58 /* UICollectionView+CollectionSkeleton.swift */, 186 | 35EA6FB9AE8E21EE5FC96EDFC68AA280 /* UIColor+Skeleton.swift */, 187 | FA4B4902C5612D26A5CA7FA5FEFF851E /* UITableView+CollectionSkeleton.swift */, 188 | 64603B1271C07D8AE4013C3EEFCB4007 /* UIView+CollectionSkeleton.swift */, 189 | E79D5E00C1E6E323D483BF74095B7A31 /* UIView+Frame.swift */, 190 | C589F2BA3611473D82BCC7BB6F663D9C /* UIView+IBInspectable.swift */, 191 | 50AAD0C475F77447D023D1983D923F3D /* UIView+UIApplicationDelegate.swift */, 192 | 2D017A2718181BC64EFF99811082E0A8 /* Support Files */, 193 | ); 194 | name = SkeletonView; 195 | path = SkeletonView; 196 | sourceTree = ""; 197 | }; 198 | 957C96CBFBFE1147235650EACDF06C6B /* Targets Support Files */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | 00C1BB3448DCD19F851DC9B6E3A0D932 /* Pods-SkeletonDemo */, 202 | ); 203 | name = "Targets Support Files"; 204 | sourceTree = ""; 205 | }; 206 | A08861C686222A069BAFEE6942BD4BC4 /* Products */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | B948EBA8264CB57F13BD5D77E3C3B253 /* Pods_SkeletonDemo.framework */, 210 | 22FC26B78BE10F43566CF988C6A7AA26 /* SkeletonView.framework */, 211 | ); 212 | name = Products; 213 | sourceTree = ""; 214 | }; 215 | B98EEC70BA2CDD738CD19EB1E04C800D /* Pods */ = { 216 | isa = PBXGroup; 217 | children = ( 218 | 90F7380DE9394FA7BAE63D8E51674075 /* SkeletonView */, 219 | ); 220 | name = Pods; 221 | sourceTree = ""; 222 | }; 223 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | D35AF013A5F0BAD4F32504907A52519E /* iOS */, 227 | ); 228 | name = Frameworks; 229 | sourceTree = ""; 230 | }; 231 | D35AF013A5F0BAD4F32504907A52519E /* iOS */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */, 235 | ); 236 | name = iOS; 237 | sourceTree = ""; 238 | }; 239 | /* End PBXGroup section */ 240 | 241 | /* Begin PBXHeadersBuildPhase section */ 242 | AB57D2FAE8D8A18E5F2BEBD1557EACC0 /* Headers */ = { 243 | isa = PBXHeadersBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | C5F13488070D5DA922D69B3B99FC353B /* Pods-SkeletonDemo-umbrella.h in Headers */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | E0020AE08FA8AAB2BEFC3DA2AACB918F /* Headers */ = { 251 | isa = PBXHeadersBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | 9DDD423250D9F6F0F08A161B65C50450 /* SkeletonView-umbrella.h in Headers */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXHeadersBuildPhase section */ 259 | 260 | /* Begin PBXNativeTarget section */ 261 | 7317CF3E83FF2993C3066FCC75786317 /* Pods-SkeletonDemo */ = { 262 | isa = PBXNativeTarget; 263 | buildConfigurationList = 3F83FA2419B00E5423A1DECBA391BFB4 /* Build configuration list for PBXNativeTarget "Pods-SkeletonDemo" */; 264 | buildPhases = ( 265 | 9899A1BCC048C21F9D92170F62F669AC /* Sources */, 266 | B3F8722BE18D4EA0ECC9D9CA70D79FD1 /* Frameworks */, 267 | AB57D2FAE8D8A18E5F2BEBD1557EACC0 /* Headers */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | EAB2C4DF007F0F9BF6AECA29F3A8BDF8 /* PBXTargetDependency */, 273 | ); 274 | name = "Pods-SkeletonDemo"; 275 | productName = "Pods-SkeletonDemo"; 276 | productReference = B948EBA8264CB57F13BD5D77E3C3B253 /* Pods_SkeletonDemo.framework */; 277 | productType = "com.apple.product-type.framework"; 278 | }; 279 | 9175D2F10D001CD0918070A3F05E1FB3 /* SkeletonView */ = { 280 | isa = PBXNativeTarget; 281 | buildConfigurationList = F5C9641439CC706C04BCA79B9E470A73 /* Build configuration list for PBXNativeTarget "SkeletonView" */; 282 | buildPhases = ( 283 | E9667928414FF565E00DFDDBA8F0F023 /* Sources */, 284 | 535A91CFC1BB2D61820F91C035C5A7E3 /* Frameworks */, 285 | E0020AE08FA8AAB2BEFC3DA2AACB918F /* Headers */, 286 | ); 287 | buildRules = ( 288 | ); 289 | dependencies = ( 290 | ); 291 | name = SkeletonView; 292 | productName = SkeletonView; 293 | productReference = 22FC26B78BE10F43566CF988C6A7AA26 /* SkeletonView.framework */; 294 | productType = "com.apple.product-type.framework"; 295 | }; 296 | /* End PBXNativeTarget section */ 297 | 298 | /* Begin PBXProject section */ 299 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 300 | isa = PBXProject; 301 | attributes = { 302 | LastSwiftUpdateCheck = 0830; 303 | LastUpgradeCheck = 0700; 304 | }; 305 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 306 | compatibilityVersion = "Xcode 3.2"; 307 | developmentRegion = English; 308 | hasScannedForEncodings = 0; 309 | knownRegions = ( 310 | en, 311 | ); 312 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 313 | productRefGroup = A08861C686222A069BAFEE6942BD4BC4 /* Products */; 314 | projectDirPath = ""; 315 | projectRoot = ""; 316 | targets = ( 317 | 7317CF3E83FF2993C3066FCC75786317 /* Pods-SkeletonDemo */, 318 | 9175D2F10D001CD0918070A3F05E1FB3 /* SkeletonView */, 319 | ); 320 | }; 321 | /* End PBXProject section */ 322 | 323 | /* Begin PBXSourcesBuildPhase section */ 324 | 9899A1BCC048C21F9D92170F62F669AC /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | 3894E3CC802288F1D5311C20A8F4959C /* Pods-SkeletonDemo-dummy.m in Sources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | E9667928414FF565E00DFDDBA8F0F023 /* Sources */ = { 333 | isa = PBXSourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | 15345DEE41436B4D5141F41346226099 /* AssociationPolicy.swift in Sources */, 337 | 3601D473A28AD20928F03418AC4BD709 /* CALayer+Extensions.swift in Sources */, 338 | 71B7B3E9C9583BA11890CBD0F2375C25 /* CollectionSkeletonProtocol.swift in Sources */, 339 | 272DD095161AF3929E2A195437B40E94 /* ContainsMultilineText.swift in Sources */, 340 | 4223CBBE76307A50C35F238C1CBDA311 /* GenericCollectionView.swift in Sources */, 341 | 0C18C6758EAAC7EEEF1C20EDACB14461 /* PrepareForSkeletonProtocol.swift in Sources */, 342 | 244A98B0738EBE5C9A8B7E40185C9EBF /* RecursiveProtocol.swift in Sources */, 343 | A6A75815D8D020D14760844C8FBEC718 /* SkeletonAnimationBuilder.swift in Sources */, 344 | BA9465793D9DA8E250498FFC0B6F0C0C /* SkeletonCollectionDataSource.swift in Sources */, 345 | C1E98E7EE9D5B28511394F7D45BEAAE3 /* SkeletonCollectionDelegate.swift in Sources */, 346 | 14F76443F848C1AD1E6184C1A8088A10 /* SkeletonCollectionViewProtocols.swift in Sources */, 347 | 6275570CA76D38637B2064C9D99DFAC1 /* SkeletonDefaultConfig.swift in Sources */, 348 | 90FF8305A893C7798C38092AD6B952B5 /* SkeletonFlow.swift in Sources */, 349 | 9974E7F97B2BB629E1CA004C32BB07B4 /* SkeletonGradient.swift in Sources */, 350 | D26522E300514466D61D258CEF0B13BD /* SkeletonLayer.swift in Sources */, 351 | 30CB37141129792700793A309B5B7422 /* SkeletonReusableCell.swift in Sources */, 352 | DE324F92C19E4CF1522E3A4C85A884DD /* SkeletonTableViewProtocols.swift in Sources */, 353 | E010BF69780C58A48457608E9A335FE8 /* SkeletonView-dummy.m in Sources */, 354 | 1F0853C12BA4D9089926951C39CDF18C /* SkeletonView.swift in Sources */, 355 | 68C2EB093254CC78B4B2D99F733DF0AF /* UICollectionView+CollectionSkeleton.swift in Sources */, 356 | 49575AC0C3C414A7037C3297FEBF72DB /* UIColor+Skeleton.swift in Sources */, 357 | C1B9E18733A99A61AE0C43EAFBBBBD07 /* UITableView+CollectionSkeleton.swift in Sources */, 358 | 0821A0FB10F930234E449A0117E15743 /* UIView+CollectionSkeleton.swift in Sources */, 359 | 2FF492A8E341B1CCB46F1BE301612EFD /* UIView+Frame.swift in Sources */, 360 | B4D08FD046931116469A337152FD7A99 /* UIView+IBInspectable.swift in Sources */, 361 | 56D3465D40663F59F768FF7F765039AA /* UIView+UIApplicationDelegate.swift in Sources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | /* End PBXSourcesBuildPhase section */ 366 | 367 | /* Begin PBXTargetDependency section */ 368 | EAB2C4DF007F0F9BF6AECA29F3A8BDF8 /* PBXTargetDependency */ = { 369 | isa = PBXTargetDependency; 370 | name = SkeletonView; 371 | target = 9175D2F10D001CD0918070A3F05E1FB3 /* SkeletonView */; 372 | targetProxy = FD22359C1DBCE1E2846113F7B63C99BD /* PBXContainerItemProxy */; 373 | }; 374 | /* End PBXTargetDependency section */ 375 | 376 | /* Begin XCBuildConfiguration section */ 377 | 4BA5B5E5AAF363A9A20E5B18A269B152 /* Release */ = { 378 | isa = XCBuildConfiguration; 379 | baseConfigurationReference = A187E7A450E9DEFE653D4A84CC52A88A /* Pods-SkeletonDemo.release.xcconfig */; 380 | buildSettings = { 381 | CODE_SIGN_IDENTITY = ""; 382 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 383 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 384 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 385 | CURRENT_PROJECT_VERSION = 1; 386 | DEFINES_MODULE = YES; 387 | DYLIB_COMPATIBILITY_VERSION = 1; 388 | DYLIB_CURRENT_VERSION = 1; 389 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 390 | INFOPLIST_FILE = "Target Support Files/Pods-SkeletonDemo/Info.plist"; 391 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 392 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 394 | MACH_O_TYPE = staticlib; 395 | MODULEMAP_FILE = "Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.modulemap"; 396 | OTHER_LDFLAGS = ""; 397 | OTHER_LIBTOOLFLAGS = ""; 398 | PODS_ROOT = "$(SRCROOT)"; 399 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 400 | PRODUCT_NAME = Pods_SkeletonDemo; 401 | SDKROOT = iphoneos; 402 | SKIP_INSTALL = YES; 403 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 404 | TARGETED_DEVICE_FAMILY = "1,2"; 405 | VALIDATE_PRODUCT = YES; 406 | VERSIONING_SYSTEM = "apple-generic"; 407 | VERSION_INFO_PREFIX = ""; 408 | }; 409 | name = Release; 410 | }; 411 | 50DC830C5FE8E6DD815D72D14580C4C8 /* Debug */ = { 412 | isa = XCBuildConfiguration; 413 | baseConfigurationReference = D2A56A409ABB8E7F9B54D8FCFDDF13C6 /* Pods-SkeletonDemo.debug.xcconfig */; 414 | buildSettings = { 415 | CODE_SIGN_IDENTITY = ""; 416 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 418 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 419 | CURRENT_PROJECT_VERSION = 1; 420 | DEFINES_MODULE = YES; 421 | DYLIB_COMPATIBILITY_VERSION = 1; 422 | DYLIB_CURRENT_VERSION = 1; 423 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 424 | INFOPLIST_FILE = "Target Support Files/Pods-SkeletonDemo/Info.plist"; 425 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 426 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 427 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 428 | MACH_O_TYPE = staticlib; 429 | MODULEMAP_FILE = "Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.modulemap"; 430 | OTHER_LDFLAGS = ""; 431 | OTHER_LIBTOOLFLAGS = ""; 432 | PODS_ROOT = "$(SRCROOT)"; 433 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 434 | PRODUCT_NAME = Pods_SkeletonDemo; 435 | SDKROOT = iphoneos; 436 | SKIP_INSTALL = YES; 437 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 438 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 439 | TARGETED_DEVICE_FAMILY = "1,2"; 440 | VERSIONING_SYSTEM = "apple-generic"; 441 | VERSION_INFO_PREFIX = ""; 442 | }; 443 | name = Debug; 444 | }; 445 | 6B97988BF4CBC827AF53389A2450BF43 /* Release */ = { 446 | isa = XCBuildConfiguration; 447 | baseConfigurationReference = 85DA67253D48FE830E38E71F57C40098 /* SkeletonView.xcconfig */; 448 | buildSettings = { 449 | CODE_SIGN_IDENTITY = ""; 450 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 451 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 452 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 453 | CURRENT_PROJECT_VERSION = 1; 454 | DEFINES_MODULE = YES; 455 | DYLIB_COMPATIBILITY_VERSION = 1; 456 | DYLIB_CURRENT_VERSION = 1; 457 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 458 | GCC_PREFIX_HEADER = "Target Support Files/SkeletonView/SkeletonView-prefix.pch"; 459 | INFOPLIST_FILE = "Target Support Files/SkeletonView/Info.plist"; 460 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 461 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 463 | MODULEMAP_FILE = "Target Support Files/SkeletonView/SkeletonView.modulemap"; 464 | PRODUCT_NAME = SkeletonView; 465 | SDKROOT = iphoneos; 466 | SKIP_INSTALL = YES; 467 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 468 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 469 | SWIFT_VERSION = 4.0; 470 | TARGETED_DEVICE_FAMILY = "1,2"; 471 | VALIDATE_PRODUCT = YES; 472 | VERSIONING_SYSTEM = "apple-generic"; 473 | VERSION_INFO_PREFIX = ""; 474 | }; 475 | name = Release; 476 | }; 477 | 6F9224530522DD3C735EC96CF142642E /* Release */ = { 478 | isa = XCBuildConfiguration; 479 | buildSettings = { 480 | ALWAYS_SEARCH_USER_PATHS = NO; 481 | CLANG_ANALYZER_NONNULL = YES; 482 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 483 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 484 | CLANG_CXX_LIBRARY = "libc++"; 485 | CLANG_ENABLE_MODULES = YES; 486 | CLANG_ENABLE_OBJC_ARC = YES; 487 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 488 | CLANG_WARN_BOOL_CONVERSION = YES; 489 | CLANG_WARN_COMMA = YES; 490 | CLANG_WARN_CONSTANT_CONVERSION = YES; 491 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 492 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 493 | CLANG_WARN_EMPTY_BODY = YES; 494 | CLANG_WARN_ENUM_CONVERSION = YES; 495 | CLANG_WARN_INFINITE_RECURSION = YES; 496 | CLANG_WARN_INT_CONVERSION = YES; 497 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 498 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 499 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 500 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 501 | CLANG_WARN_STRICT_PROTOTYPES = YES; 502 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 503 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 504 | CLANG_WARN_UNREACHABLE_CODE = YES; 505 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 506 | CODE_SIGNING_REQUIRED = NO; 507 | COPY_PHASE_STRIP = NO; 508 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 509 | ENABLE_NS_ASSERTIONS = NO; 510 | ENABLE_STRICT_OBJC_MSGSEND = YES; 511 | GCC_C_LANGUAGE_STANDARD = gnu11; 512 | GCC_NO_COMMON_BLOCKS = YES; 513 | GCC_PREPROCESSOR_DEFINITIONS = ( 514 | "POD_CONFIGURATION_RELEASE=1", 515 | "$(inherited)", 516 | ); 517 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 518 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 519 | GCC_WARN_UNDECLARED_SELECTOR = YES; 520 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 521 | GCC_WARN_UNUSED_FUNCTION = YES; 522 | GCC_WARN_UNUSED_VARIABLE = YES; 523 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 524 | MTL_ENABLE_DEBUG_INFO = NO; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 527 | STRIP_INSTALLED_PRODUCT = NO; 528 | SYMROOT = "${SRCROOT}/../build"; 529 | }; 530 | name = Release; 531 | }; 532 | B57951D085A1B98A97F8A1062A5E5C5B /* Debug */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | ALWAYS_SEARCH_USER_PATHS = NO; 536 | CLANG_ANALYZER_NONNULL = YES; 537 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 538 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 539 | CLANG_CXX_LIBRARY = "libc++"; 540 | CLANG_ENABLE_MODULES = YES; 541 | CLANG_ENABLE_OBJC_ARC = YES; 542 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 543 | CLANG_WARN_BOOL_CONVERSION = YES; 544 | CLANG_WARN_COMMA = YES; 545 | CLANG_WARN_CONSTANT_CONVERSION = YES; 546 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 547 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 548 | CLANG_WARN_EMPTY_BODY = YES; 549 | CLANG_WARN_ENUM_CONVERSION = YES; 550 | CLANG_WARN_INFINITE_RECURSION = YES; 551 | CLANG_WARN_INT_CONVERSION = YES; 552 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 553 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 554 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 555 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 556 | CLANG_WARN_STRICT_PROTOTYPES = YES; 557 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 558 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 559 | CLANG_WARN_UNREACHABLE_CODE = YES; 560 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 561 | CODE_SIGNING_REQUIRED = NO; 562 | COPY_PHASE_STRIP = NO; 563 | DEBUG_INFORMATION_FORMAT = dwarf; 564 | ENABLE_STRICT_OBJC_MSGSEND = YES; 565 | ENABLE_TESTABILITY = YES; 566 | GCC_C_LANGUAGE_STANDARD = gnu11; 567 | GCC_DYNAMIC_NO_PIC = NO; 568 | GCC_NO_COMMON_BLOCKS = YES; 569 | GCC_OPTIMIZATION_LEVEL = 0; 570 | GCC_PREPROCESSOR_DEFINITIONS = ( 571 | "POD_CONFIGURATION_DEBUG=1", 572 | "DEBUG=1", 573 | "$(inherited)", 574 | ); 575 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 576 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 577 | GCC_WARN_UNDECLARED_SELECTOR = YES; 578 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 579 | GCC_WARN_UNUSED_FUNCTION = YES; 580 | GCC_WARN_UNUSED_VARIABLE = YES; 581 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 582 | MTL_ENABLE_DEBUG_INFO = YES; 583 | ONLY_ACTIVE_ARCH = YES; 584 | PRODUCT_NAME = "$(TARGET_NAME)"; 585 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 586 | STRIP_INSTALLED_PRODUCT = NO; 587 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 588 | SYMROOT = "${SRCROOT}/../build"; 589 | }; 590 | name = Debug; 591 | }; 592 | DE80590EC542F9FEC469CB1F5DC7AED2 /* Debug */ = { 593 | isa = XCBuildConfiguration; 594 | baseConfigurationReference = 85DA67253D48FE830E38E71F57C40098 /* SkeletonView.xcconfig */; 595 | buildSettings = { 596 | CODE_SIGN_IDENTITY = ""; 597 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 598 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 599 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 600 | CURRENT_PROJECT_VERSION = 1; 601 | DEFINES_MODULE = YES; 602 | DYLIB_COMPATIBILITY_VERSION = 1; 603 | DYLIB_CURRENT_VERSION = 1; 604 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 605 | GCC_PREFIX_HEADER = "Target Support Files/SkeletonView/SkeletonView-prefix.pch"; 606 | INFOPLIST_FILE = "Target Support Files/SkeletonView/Info.plist"; 607 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 608 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 609 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 610 | MODULEMAP_FILE = "Target Support Files/SkeletonView/SkeletonView.modulemap"; 611 | PRODUCT_NAME = SkeletonView; 612 | SDKROOT = iphoneos; 613 | SKIP_INSTALL = YES; 614 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 615 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 616 | SWIFT_VERSION = 4.0; 617 | TARGETED_DEVICE_FAMILY = "1,2"; 618 | VERSIONING_SYSTEM = "apple-generic"; 619 | VERSION_INFO_PREFIX = ""; 620 | }; 621 | name = Debug; 622 | }; 623 | /* End XCBuildConfiguration section */ 624 | 625 | /* Begin XCConfigurationList section */ 626 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 627 | isa = XCConfigurationList; 628 | buildConfigurations = ( 629 | B57951D085A1B98A97F8A1062A5E5C5B /* Debug */, 630 | 6F9224530522DD3C735EC96CF142642E /* Release */, 631 | ); 632 | defaultConfigurationIsVisible = 0; 633 | defaultConfigurationName = Release; 634 | }; 635 | 3F83FA2419B00E5423A1DECBA391BFB4 /* Build configuration list for PBXNativeTarget "Pods-SkeletonDemo" */ = { 636 | isa = XCConfigurationList; 637 | buildConfigurations = ( 638 | 50DC830C5FE8E6DD815D72D14580C4C8 /* Debug */, 639 | 4BA5B5E5AAF363A9A20E5B18A269B152 /* Release */, 640 | ); 641 | defaultConfigurationIsVisible = 0; 642 | defaultConfigurationName = Release; 643 | }; 644 | F5C9641439CC706C04BCA79B9E470A73 /* Build configuration list for PBXNativeTarget "SkeletonView" */ = { 645 | isa = XCConfigurationList; 646 | buildConfigurations = ( 647 | DE80590EC542F9FEC469CB1F5DC7AED2 /* Debug */, 648 | 6B97988BF4CBC827AF53389A2450BF43 /* Release */, 649 | ); 650 | defaultConfigurationIsVisible = 0; 651 | defaultConfigurationName = Release; 652 | }; 653 | /* End XCConfigurationList section */ 654 | }; 655 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 656 | } 657 | -------------------------------------------------------------------------------- /Pods/SkeletonView/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Juanpe Catalán 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Pods/SkeletonView/README.md: -------------------------------------------------------------------------------- 1 | ![](Assets/header.jpg) 2 | 3 |

4 | 5 | 6 | 7 | 8 | 9 | CocoaPods 10 | 11 | 12 | Carthage 13 | 14 | 15 | CocoaPods downloads 16 | 17 | 18 | Twitter: @JuanpeCatalan 19 | 20 | 21 | License 22 | 23 | 24 | License 25 | 26 |

27 | 28 | Today almost all apps have async processes, such as Api requests, long running processes, etc. And while the processes are working, usually developers place a loading view to show users that something is going on. 29 | 30 | ```SkeletonView``` has been conceived to address this need, an elegant way to show users that something is happening and also prepare them to which contents he is waiting. 31 | 32 | Enjoy it! 🙂 33 | 34 | * [Features](#-features) 35 | * [Requirements](#-supported-os--sdk-versions) 36 | * [Example Project](#-example) 37 | * [Installation](#-installation) 38 | * [Cocoapods](#using-cocoapods) 39 | * [Carthage](#using-carthage) 40 | * [How to use](#-how-to-use) 41 | * [Collections](#-collections) 42 | * [Multiline text](#-multiline-text) 43 | * [Custom colors](#-custom-colors) 44 | * [Custom animations](#-custom-animations) 45 | * [Hierarchy](#-hierarchy) 46 | * [Documentation](#-documentation) 47 | * [Next steps](#-next-steps) 48 | * [Contributed](#-contributed) 49 | * [Author](#-author) 50 | * [License](#-license) 51 | 52 | 53 | ## 🌟 Features 54 | 55 | - [x] Easy to use 56 | - [x] All UIViews are skeletonables 57 | - [x] Fully customizable 58 | - [x] Universal (iPhone & iPad) 59 | - [x] Interface Builder friendly 60 | - [x] Simple Swift syntax 61 | - [x] Lightweight readable codebase 62 | 63 | ### 📋 Supported OS & SDK Versions 64 | 65 | * iOS 9.0+ 66 | * tvOS 9.0+ 67 | * Swift 4 68 | 69 | ### 🔮 Example 70 | 71 | To run the example project, clone the repo and run `SkeletonViewExample` target. 72 | 73 | ![](Assets/demoApp2.png) 74 | 75 | ## 📲 Installation 76 | 77 | #### Using [CocoaPods](https://cocoapods.org) 78 | 79 | Edit your `Podfile` and specify the dependency: 80 | 81 | ```ruby 82 | pod "SkeletonView" 83 | ``` 84 | 85 | #### Using [Carthage](https://github.com/carthage) 86 | 87 | Edit your `Cartfile` and specify the dependency: 88 | 89 | ```bash 90 | github "Juanpe/SkeletonView" 91 | ``` 92 | 93 | ## 🐒 How to use 94 | 95 | Only **3** steps needed to use `SkeletonView`: 96 | 97 | **1.** Import SkeletonView in proper place. 98 | ```swift 99 | import SkeletonView 100 | ``` 101 | 102 | **2.** Now, set which views will be `skeletonables`. You achieve this in two ways: 103 | 104 | **Using code:** 105 | ```swift 106 | avatarImageView.isSkeletonable = true 107 | ``` 108 | **Using IB/Storyboards:** 109 | 110 | ![](Assets/storyboard.png) 111 | 112 | **3.** Once you've set the views, you can show the **skeleton**. To do so, you have **4** choices: 113 | 114 | ```swift 115 | (1) view.showSkeleton() // Solid 116 | (2) view.showGradientSkeleton() // Gradient 117 | (3) view.showAnimatedSkeleton() // Solid animated 118 | (4) view.showAnimatedGradientSkeleton() // Gradient animated 119 | ``` 120 | 121 | **Preview** 122 | 123 | 124 | 125 | 128 | 131 | 134 | 137 | 138 | 139 | 142 | 145 | 148 | 151 | 152 |
126 |
Solid
127 |
129 |
Gradient
130 |
132 |
Solid Animated
133 |
135 |
Gradient Animated
136 |
140 | 141 | 143 | 144 | 146 | 147 | 149 | 150 |
153 | 154 | > **IMPORTANT!** 155 | >>```SkeletonView``` is recursive, so if you want show the skeleton in all skeletonable views, you only need to call the show method in the main container view. For example, with UIViewControllers 156 | 157 | ### 🌿 Collections 158 | 159 | Now, ```SkeletonView``` is compatible with ```UITableView``` and ```UICollectionView```. 160 | 161 | ###### UITableView 162 | 163 | If you want to show the skeleton in a ```UITableView```, you need to conform to ```SkeletonTableViewDataSource``` protocol. 164 | 165 | ``` swift 166 | public protocol SkeletonTableViewDataSource: UITableViewDataSource { 167 | func numSections(in collectionSkeletonView: UITableView) -> Int 168 | func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int 169 | func collectionSkeletonView(_ skeletonView: UITableView, cellIdenfierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier 170 | } 171 | ``` 172 | As you can see, this protocol inherits from ```UITableViewDataSource```, so you can replace this protocol with the skeleton protocol. 173 | 174 | This protocol has a default implementation: 175 | 176 | ``` swift 177 | func numSections(in collectionSkeletonView: UITableView) -> Int 178 | // Default: 1 179 | ``` 180 | 181 | ``` swift 182 | func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int 183 | // Default: 184 | // It calculates how many cells need to populate whole tableview 185 | ``` 186 | 187 | There is only one method you need to implement to let Skeleton know the cell identifier. This method doesn't have default implementation: 188 | ``` swift 189 | func collectionSkeletonView(_ skeletonView: UITableView, cellIdenfierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier 190 | ``` 191 | 192 | **Example** 193 | ``` swift 194 | func collectionSkeletonView(_ skeletonView: UITableView, cellIdenfierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier { 195 | return "CellIdentifier" 196 | } 197 | ``` 198 | 199 | > **IMPORTANT!** 200 | > If you are using resizable cells (`tableView.rowHeight = UITableViewAutomaticDimension` ), it's mandatory define the `estimatedRowHeight`. 201 | 202 | ###### UICollectionView 203 | 204 | For ```UICollectionView```, you need to conform to ```SkeletonCollectionViewDataSource``` protocol. 205 | 206 | ``` swift 207 | public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource { 208 | func numSections(in collectionSkeletonView: UICollectionView) -> Int 209 | func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int 210 | func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier 211 | } 212 | ``` 213 | 214 | The rest of the process is the same as ```UITableView``` 215 | 216 | ### 📰 Multiline text 217 | 218 | 219 | ![](Assets/multilines2.png) 220 | 221 | When using elements with text, ```SkeletonView``` draws lines to simulate text. 222 | Besides, you can decide how many lines you want. If ```numberOfLines``` is set to zero, it will calculate how many lines needed to populate the whole skeleton and it will be drawn. Instead, if you set it to one, two or any number greater than zero, it will only draw this number of lines. 223 | 224 | **NEW** Now, you can set the filling percent of the last line. **Default: 70%** 225 | 226 | To modify the percent **using code**, set the property: 227 | ```swift 228 | descriptionTextView.lastLineFillPercent = 50 229 | ``` 230 | 231 | Or, if you prefer use **IB/Storyboard**: 232 | 233 | ![](Assets/lastline_storyboard.png) 234 | 235 | 236 | ### 🎨 Custom colors 237 | 238 | You can decide which color the skeleton is tinted with. You only need to pass as a parameter the color or gradient you want. 239 | 240 | **Using solid colors** 241 | ``` swift 242 | view.showSkeleton(usingColor: UIColor.gray) // Solid 243 | // or 244 | view.showSkeleton(usingColor: UIColor(red: 25.0, green: 30.0, blue: 255.0, alpha: 1.0)) 245 | ``` 246 | **Using gradients** 247 | ``` swift 248 | let gradient = SkeletonGradient(baseColor: UIColor.midnightBlue) 249 | view.showGradientSkeleton(usingGradient: gradient) // Gradient 250 | ``` 251 | 252 | Besides, ```SkeletonView``` features 20 flat colors 🤙🏼 253 | 254 | ```UIColor.turquoise, UIColor.greenSea, UIColor.sunFlower, UIColor.flatOrange ...``` 255 | 256 | ![](Assets/flatcolors.png) 257 | ###### Image captured from website [https://flatuicolors.com](https://flatuicolors.com) 258 | 259 | ### 🤓 Custom animations 260 | 261 | Now, ```SkeletonView``` has two built-in animations, *pulse* for solid skeletons and *sliding* for gradients. 262 | 263 | Besides, if you want to do your own skeleton animation, it's really easy. 264 | 265 | 266 | Skeleton provides the `showAnimatedSkeleton` function which has a ```SkeletonLayerAnimation``` closure where you can define your custom animation. 267 | 268 | ```swift 269 | public typealias SkeletonLayerAnimation = (CALayer) -> CAAnimation 270 | ``` 271 | 272 | You can call the function like this: 273 | 274 | ```swift 275 | view.showAnimatedSkeleton { (layer) -> CAAnimation in 276 | let animation = CAAnimation() 277 | // Customize here your animation 278 | 279 | return animation 280 | } 281 | ``` 282 | 283 | **NEW** It's available ```SkeletonAnimationBuilder```. It's a builder to make ```SkeletonLayerAnimation```. 284 | 285 | Today, you can create **sliding animations** for gradients, deciding the **direction** and setting the **duration** of the animation (default = 1.5s). 286 | 287 | ```swift 288 | // func makeSlidingAnimation(withDirection direction: GradientDirection, duration: CFTimeInterval = 1.5) -> SkeletonLayerAnimation 289 | 290 | let animation = SkeletonAnimationBuilder().makeSlidingAnimation(withDirection: .leftToRight) 291 | view.showAnimatedGradientSkeleton(usingGradient: gradient, animation: animation) 292 | 293 | ``` 294 | 295 | ```GradientDirection``` is an enum, with this cases: 296 | 297 | | Direction | Preview 298 | |------- | ------- 299 | | .leftRight | ![](Assets/sliding_left_to_right.gif) 300 | | .rightLeft | ![](Assets/sliding_right_to_left.gif) 301 | | .topBottom | ![](Assets/sliding_top_to_bottom.gif) 302 | | .bottomTop | ![](Assets/sliding_bottom_to_top.gif) 303 | | .topLeftBottomRight | ![](Assets/sliding_topLeft_to_bottomRight.gif) 304 | | .bottomRightTopLeft | ![](Assets/sliding_bottomRight_to_topLeft.gif) 305 | 306 | > **😉 TRICK!** 307 | Exist another way to create sliding animations, just using this shortcut: 308 | >>```let animation = GradientDirection.leftToRight.slidingAnimation()``` 309 | 310 | ### 👨‍👧‍👦 Hierarchy 311 | 312 | Since ```SkeletonView``` is recursive, and we want skeleton to be very efficient, we want to stop recursion as soon as possible. For this reason, you must set the container view as `Skeletonable`, because Skeleton will stop looking for `skeletonable` subviews as soon as a view is not Skeletonable, breaking then the recursion. 313 | 314 | Because an image is worth a thousand words: 315 | 316 | > ```ìsSkeletonable```= ☠️ 317 | 318 | | Configuration | Result 319 | |------- | ------- 320 | |![](Assets/no_skeletonable.png) | ![](Assets/no_skeletonables_result.png) 321 | |![](Assets/container_no_skeletonable.png) | ![](Assets/no_skeletonables_result.png) 322 | |![](Assets/container_skeletonable.png) | ![](Assets/container_skeletonable_result.png) 323 | |![](Assets/all_skeletonables.png) | ![](Assets/all_skeletonables_result.png) 324 | 325 | 326 | 327 | ### 📚 Documentation 328 | Coming soon...😅 329 | 330 | ## 📬 Next steps 331 | 332 | * [x] Set the filling percent of the last line in multiline elements 333 | * [x] Add more gradient animations 334 | * [x] Supported resizable cells 335 | * [x] CollectionView compatible 336 | * [x] tvOS compatible 337 | * [ ] Add recovery state 338 | * [ ] Custom collections compatible 339 | * [ ] Add animations when it shows/hides the skeletons 340 | * [ ] MacOS and WatchOS compatible 341 | 342 | ## ❤️ Contributed 343 | This is an open source project, so feel free to contribute. How? 344 | - Open an [issue](https://github.com/Juanpe/SkeletonView/issues/new). 345 | - Send feedback via [email](mailto://juanpecatalan.com). 346 | - Propose your own fixes, suggestions and open a pull request with the changes. 347 | 348 | See [all contributors](https://github.com/Juanpe/SkeletonView/graphs/contributors) 349 | 350 | ###### Project generated with [SwiftPlate](https://github.com/JohnSundell/SwiftPlate) 351 | 352 | ## 👨🏻‍💻 Author 353 | [1.1]: http://i.imgur.com/tXSoThF.png 354 | [1]: http://www.twitter.com/JuanpeCatalan 355 | 356 | * Juanpe Catalán [![alt text][1.1]][1] 357 | 358 | ## 👮🏻 License 359 | 360 | ``` 361 | MIT License 362 | 363 | Copyright (c) 2017 Juanpe Catalán 364 | 365 | Permission is hereby granted, free of charge, to any person obtaining a copy 366 | of this software and associated documentation files (the "Software"), to deal 367 | in the Software without restriction, including without limitation the rights 368 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 369 | copies of the Software, and to permit persons to whom the Software is 370 | furnished to do so, subject to the following conditions: 371 | 372 | The above copyright notice and this permission notice shall be included in all 373 | copies or substantial portions of the Software. 374 | 375 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 376 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 377 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 378 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 379 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 380 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 381 | SOFTWARE. 382 | ``` 383 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/CollectionSkeletonProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionSkeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum CollectionAssociatedKeys { 12 | static var dummyDataSource = "dummyDataSource" 13 | static var dummyDelegate = "dummyDelegate" 14 | } 15 | 16 | protocol CollectionSkeleton { 17 | var skeletonDataSource: SkeletonCollectionDataSource? { get set } 18 | var skeletonDelegate: SkeletonCollectionDelegate? { get set } 19 | var estimatedNumberOfRows: Int { get } 20 | 21 | func addDummyDataSource() 22 | func removeDummyDataSource(reloadAfter: Bool) 23 | func disableUserInteraction() 24 | func enableUserInteraction() 25 | } 26 | 27 | extension CollectionSkeleton where Self: UIScrollView { 28 | var estimatedNumberOfRows: Int { return 0 } 29 | func addDummyDataSource() {} 30 | func removeDummyDataSource(reloadAfter: Bool) {} 31 | func disableUserInteraction() { isUserInteractionEnabled = false } 32 | func enableUserInteraction() { isUserInteractionEnabled = true } 33 | } 34 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/CollectionViews/SkeletonCollectionViewProtocols.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonCollectionViewProtocols.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 06/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource { 13 | func numSections(in collectionSkeletonView: UICollectionView) -> Int 14 | func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int 15 | func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier 16 | } 17 | 18 | public extension SkeletonCollectionViewDataSource { 19 | 20 | func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 21 | return skeletonView.estimatedNumberOfRows 22 | } 23 | 24 | func numSections(in collectionSkeletonView: UICollectionView) -> Int { return 1 } 25 | } 26 | 27 | public protocol SkeletonCollectionViewDelegate: UICollectionViewDelegate { } 28 | 29 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/CollectionViews/UICollectionView+CollectionSkeleton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+CollectionSkeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/02/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UICollectionView: CollectionSkeleton { 12 | 13 | var estimatedNumberOfRows: Int { 14 | guard let flowlayout = collectionViewLayout as? UICollectionViewFlowLayout else { return 0 } 15 | return Int(ceil(frame.height/flowlayout.itemSize.height)) 16 | } 17 | 18 | var skeletonDataSource: SkeletonCollectionDataSource? { 19 | get { return objc_getAssociatedObject(self, &CollectionAssociatedKeys.dummyDataSource) as? SkeletonCollectionDataSource } 20 | set { 21 | objc_setAssociatedObject(self, &CollectionAssociatedKeys.dummyDataSource, newValue, AssociationPolicy.retain.objc) 22 | self.dataSource = newValue 23 | } 24 | } 25 | 26 | var skeletonDelegate: SkeletonCollectionDelegate? { 27 | get { return objc_getAssociatedObject(self, &CollectionAssociatedKeys.dummyDelegate) as? SkeletonCollectionDelegate } 28 | set { 29 | objc_setAssociatedObject(self, &CollectionAssociatedKeys.dummyDelegate, newValue, AssociationPolicy.retain.objc) 30 | self.delegate = newValue 31 | } 32 | } 33 | 34 | func addDummyDataSource() { 35 | guard let originalDataSource = self.dataSource as? SkeletonCollectionViewDataSource, 36 | !(originalDataSource is SkeletonCollectionDataSource) 37 | else { return } 38 | 39 | let dataSource = SkeletonCollectionDataSource(collectionViewDataSource: originalDataSource, rowHeight: 0.0) 40 | self.skeletonDataSource = dataSource 41 | reloadData() 42 | } 43 | 44 | func removeDummyDataSource(reloadAfter: Bool) { 45 | guard let dataSource = self.dataSource as? SkeletonCollectionDataSource else { return } 46 | self.skeletonDataSource = nil 47 | self.dataSource = dataSource.originalCollectionViewDataSource 48 | if reloadAfter { self.reloadData() } 49 | } 50 | } 51 | 52 | extension UICollectionView: GenericCollectionView { 53 | var scrollView: UIScrollView { return self } 54 | } 55 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/Generics/GenericCollectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GenericCollectionView.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 30/03/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol GenericCollectionView { 12 | var scrollView: UIScrollView { get } 13 | } 14 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/Generics/SkeletonReusableCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonReusableCell.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 30/03/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol SkeletonReusableCell { } 12 | 13 | extension UITableViewCell: SkeletonReusableCell { } 14 | 15 | extension UICollectionViewCell: SkeletonReusableCell { } 16 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/SkeletonCollectionDataSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonCollectionDataSource.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public typealias ReusableCellIdentifier = String 12 | 13 | class SkeletonCollectionDataSource: NSObject { 14 | 15 | weak var originalTableViewDataSource: SkeletonTableViewDataSource? 16 | weak var originalCollectionViewDataSource: SkeletonCollectionViewDataSource? 17 | var rowHeight: CGFloat = 0.0 18 | 19 | convenience init(tableViewDataSource: SkeletonTableViewDataSource? = nil, collectionViewDataSource: SkeletonCollectionViewDataSource? = nil, rowHeight: CGFloat = 0.0) { 20 | self.init() 21 | self.originalTableViewDataSource = tableViewDataSource 22 | self.originalCollectionViewDataSource = collectionViewDataSource 23 | self.rowHeight = rowHeight 24 | } 25 | } 26 | 27 | // MARK: - UITableViewDataSource 28 | extension SkeletonCollectionDataSource: UITableViewDataSource { 29 | 30 | func numberOfSections(in tableView: UITableView) -> Int { 31 | return originalTableViewDataSource?.numSections(in:tableView) ?? 0 32 | } 33 | 34 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 35 | return originalTableViewDataSource?.collectionSkeletonView(tableView, numberOfRowsInSection:section) ?? 0 36 | } 37 | 38 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 39 | let cellIdentifier = originalTableViewDataSource?.collectionSkeletonView(tableView, cellIdenfierForRowAt: indexPath) ?? "" 40 | let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) 41 | return cell 42 | } 43 | } 44 | 45 | // MARK: - UICollectionViewDataSource 46 | extension SkeletonCollectionDataSource: UICollectionViewDataSource { 47 | 48 | func numberOfSections(in collectionView: UICollectionView) -> Int { 49 | return originalCollectionViewDataSource?.numSections(in: collectionView) ?? 0 50 | } 51 | 52 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 53 | return originalCollectionViewDataSource?.collectionSkeletonView(collectionView, numberOfItemsInSection: section) ?? 0 54 | } 55 | 56 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 57 | let cellIdentifier = originalCollectionViewDataSource?.collectionSkeletonView(collectionView, cellIdentifierForItemAt: indexPath) ?? "" 58 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) 59 | return cell 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/SkeletonCollectionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonCollectionDelegate.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 30/03/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SkeletonCollectionDelegate: NSObject { 12 | 13 | weak var originalTableViewDelegate: SkeletonTableViewDelegate? 14 | weak var originalCollectionViewDelegate: SkeletonCollectionViewDelegate? 15 | 16 | init(tableViewDelegate: SkeletonTableViewDelegate? = nil, collectionViewDelegate: SkeletonCollectionViewDelegate? = nil) { 17 | self.originalTableViewDelegate = tableViewDelegate 18 | self.originalCollectionViewDelegate = collectionViewDelegate 19 | } 20 | } 21 | 22 | // MARK: - UITableViewDataSource 23 | extension SkeletonCollectionDelegate: UITableViewDelegate { } 24 | 25 | // MARK: - UICollectionViewDataSource 26 | extension SkeletonCollectionDelegate: UICollectionViewDelegate { } 27 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/TableViews/SkeletonTableViewProtocols.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonTableViewProtocols.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 06/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol SkeletonTableViewDataSource: UITableViewDataSource { 12 | func numSections(in collectionSkeletonView: UITableView) -> Int 13 | func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int 14 | func collectionSkeletonView(_ skeletonView: UITableView, cellIdenfierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier 15 | } 16 | 17 | public extension SkeletonTableViewDataSource { 18 | 19 | func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int { 20 | return skeletonView.estimatedNumberOfRows 21 | } 22 | 23 | func numSections(in collectionSkeletonView: UITableView) -> Int { return 1 } 24 | } 25 | 26 | public protocol SkeletonTableViewDelegate: UITableViewDelegate { 27 | } 28 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/TableViews/UITableView+CollectionSkeleton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+CollectionSkeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/02/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableView: CollectionSkeleton { 12 | 13 | var estimatedNumberOfRows: Int { 14 | return Int(ceil(frame.height/rowHeight)) 15 | } 16 | 17 | var skeletonDataSource: SkeletonCollectionDataSource? { 18 | get { return objc_getAssociatedObject(self, &CollectionAssociatedKeys.dummyDataSource) as? SkeletonCollectionDataSource } 19 | set { 20 | objc_setAssociatedObject(self, &CollectionAssociatedKeys.dummyDataSource, newValue, AssociationPolicy.retain.objc) 21 | self.dataSource = newValue 22 | } 23 | } 24 | 25 | var skeletonDelegate: SkeletonCollectionDelegate? { 26 | get { return objc_getAssociatedObject(self, &CollectionAssociatedKeys.dummyDelegate) as? SkeletonCollectionDelegate } 27 | set { 28 | objc_setAssociatedObject(self, &CollectionAssociatedKeys.dummyDelegate, newValue, AssociationPolicy.retain.objc) 29 | self.delegate = newValue 30 | } 31 | } 32 | 33 | func addDummyDataSource() { 34 | guard let originalDataSource = self.dataSource as? SkeletonTableViewDataSource, 35 | !(originalDataSource is SkeletonCollectionDataSource) 36 | else { return } 37 | let dataSource = SkeletonCollectionDataSource(tableViewDataSource: originalDataSource, rowHeight: calculateRowHeight()) 38 | self.skeletonDataSource = dataSource 39 | reloadData() 40 | } 41 | 42 | func removeDummyDataSource(reloadAfter: Bool) { 43 | guard let dataSource = self.dataSource as? SkeletonCollectionDataSource else { return } 44 | restoreRowHeight() 45 | self.skeletonDataSource = nil 46 | self.dataSource = dataSource.originalTableViewDataSource 47 | if reloadAfter { self.reloadData() } 48 | } 49 | 50 | private func restoreRowHeight() { 51 | guard let dataSource = self.dataSource as? SkeletonCollectionDataSource else { return } 52 | rowHeight = dataSource.rowHeight 53 | } 54 | 55 | private func calculateRowHeight() -> CGFloat { 56 | guard rowHeight == UITableViewAutomaticDimension else { return rowHeight } 57 | rowHeight = estimatedRowHeight 58 | return estimatedRowHeight 59 | } 60 | } 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Collections/UIView+CollectionSkeleton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+CollectionSkeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/02/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | func addDummyDataSourceIfNeeded() { 13 | guard let collection = self as? CollectionSkeleton else { return } 14 | collection.addDummyDataSource() 15 | collection.disableUserInteraction() 16 | } 17 | 18 | func removeDummyDataSourceIfNeeded(reloadAfter reload: Bool = true) { 19 | guard let collection = self as? CollectionSkeleton else { return } 20 | collection.removeDummyDataSource(reloadAfter: reload) 21 | collection.enableUserInteraction() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Extensions/CALayer+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonLayer+Animations.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 03/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension CALayer { 12 | @objc func tint(withColors colors: [UIColor]) { 13 | recursiveSearch(inArray: skeletonSublayers, 14 | leafBlock: { backgroundColor = colors.first?.cgColor }) { 15 | $0.tint(withColors: colors) 16 | } 17 | } 18 | } 19 | 20 | extension CAGradientLayer { 21 | override func tint(withColors colors: [UIColor]) { 22 | recursiveSearch(inArray: skeletonSublayers, 23 | leafBlock: { self.colors = colors.map { $0.cgColor } }) { 24 | $0.tint(withColors: colors) 25 | } 26 | } 27 | } 28 | 29 | 30 | // MARK: Skeleton sublayers 31 | extension CALayer { 32 | 33 | static let skeletonSubLayersName = "SkeletonSubLayersName" 34 | 35 | var skeletonSublayers: [CALayer] { 36 | return sublayers?.filter { $0.name == CALayer.skeletonSubLayersName } ?? [CALayer]() 37 | } 38 | 39 | func addMultilinesLayers(lines: Int, type: SkeletonType, lastLineFillPercent: Int) { 40 | let numberOfSublayers = calculateNumLines(maxLines: lines) 41 | for index in 0.. Int { 54 | let spaceRequitedForEachLine = SkeletonDefaultConfig.multilineHeight + SkeletonDefaultConfig.multilineSpacing 55 | var numberOfSublayers = Int(round(CGFloat(bounds.height)/CGFloat(spaceRequitedForEachLine))) 56 | if maxLines != 0, maxLines <= numberOfSublayers { numberOfSublayers = maxLines } 57 | return numberOfSublayers 58 | } 59 | } 60 | 61 | // MARK: Animations 62 | public extension CALayer { 63 | 64 | var pulse: CAAnimation { 65 | let pulseAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.backgroundColor)) 66 | pulseAnimation.fromValue = backgroundColor 67 | pulseAnimation.toValue = UIColor(cgColor: backgroundColor!).complementaryColor.cgColor 68 | pulseAnimation.duration = 1 69 | pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 70 | pulseAnimation.autoreverses = true 71 | pulseAnimation.repeatCount = .infinity 72 | return pulseAnimation 73 | } 74 | 75 | var sliding: CAAnimation { 76 | let startPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint)) 77 | startPointAnim.fromValue = CGPoint(x: -1, y: 0.5) 78 | startPointAnim.toValue = CGPoint(x:1, y: 0.5) 79 | 80 | let endPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint)) 81 | endPointAnim.fromValue = CGPoint(x: 0, y: 0.5) 82 | endPointAnim.toValue = CGPoint(x:2, y: 0.5) 83 | 84 | let animGroup = CAAnimationGroup() 85 | animGroup.animations = [startPointAnim, endPointAnim] 86 | animGroup.duration = 1.5 87 | animGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 88 | animGroup.repeatCount = .infinity 89 | 90 | return animGroup 91 | } 92 | 93 | func playAnimation(_ anim: SkeletonLayerAnimation, key: String) { 94 | recursiveSearch(inArray: skeletonSublayers, 95 | leafBlock: { add(anim(self), forKey: key) }) { 96 | $0.playAnimation(anim, key: key) 97 | } 98 | } 99 | 100 | func stopAnimation(forKey key: String) { 101 | recursiveSearch(inArray: skeletonSublayers, 102 | leafBlock: { removeAnimation(forKey: key) }) { 103 | $0.stopAnimation(forKey: key) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Extensions/UIColor+Skeleton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Skeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 03/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | 13 | convenience init(_ hex: UInt) { 14 | self.init( 15 | red: CGFloat((hex & 0xFF0000) >> 16) / 255.0, 16 | green: CGFloat((hex & 0x00FF00) >> 8) / 255.0, 17 | blue: CGFloat(hex & 0x0000FF) / 255.0, 18 | alpha: CGFloat(1.0) 19 | ) 20 | } 21 | 22 | func isLight() -> Bool { 23 | // algorithm from: http://www.w3.org/WAI/ER/WD-AERT/#color-contrast 24 | guard let components = cgColor.components, 25 | components.count >= 3 else { return false } 26 | let brightness = ((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000 27 | return !(brightness < 0.5) 28 | } 29 | 30 | public var complementaryColor: UIColor { 31 | return isLight() ? darker : lighter 32 | } 33 | 34 | public var lighter: UIColor { 35 | return adjust(by: 1.35) 36 | } 37 | 38 | public var darker: UIColor { 39 | return adjust(by: 0.94) 40 | } 41 | 42 | func adjust(by percent: CGFloat) -> UIColor { 43 | var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 44 | getHue(&h, saturation: &s, brightness: &b, alpha: &a) 45 | return UIColor(hue: h, saturation: s, brightness: b * percent, alpha: a) 46 | } 47 | 48 | func makeGradient() -> [UIColor] { 49 | return [self, self.complementaryColor, self] 50 | } 51 | } 52 | 53 | public extension UIColor { 54 | static var greenSea = UIColor(0x16a085) 55 | static var turquoise = UIColor(0x1abc9c) 56 | static var emerald = UIColor(0x2ecc71) 57 | static var peterRiver = UIColor(0x3498db) 58 | static var amethyst = UIColor(0x9b59b6) 59 | static var wetAsphalt = UIColor(0x34495e) 60 | static var nephritis = UIColor(0x27ae60) 61 | static var belizeHole = UIColor(0x2980b9) 62 | static var wisteria = UIColor(0x8e44ad) 63 | static var midnightBlue = UIColor(0x2c3e50) 64 | static var sunFlower = UIColor(0xf1c40f) 65 | static var carrot = UIColor(0xe67e22) 66 | static var alizarin = UIColor(0xe74c3c) 67 | static var clouds = UIColor(0xecf0f1) 68 | static var concrete = UIColor(0x95a5a6) 69 | static var flatOrange = UIColor(0xf39c12) 70 | static var pumpkin = UIColor(0xd35400) 71 | static var pomegranate = UIColor(0xc0392b) 72 | static var silver = UIColor(0xbdc3c7) 73 | static var asbestos = UIColor(0x7f8c8d) 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Extensions/UIView+Frame.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Frame.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 06/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: Frame 12 | extension UIView { 13 | 14 | var maxBoundsEstimated: CGRect { 15 | return CGRect(origin: .zero, size: maxSizeEstimated) 16 | } 17 | 18 | var maxSizeEstimated: CGSize { 19 | return CGSize(width: maxWidthEstimated, height: maxHeightEstimated) 20 | } 21 | 22 | var maxWidthEstimated: CGFloat { 23 | let constraintsWidth = constraints.filter({ $0.firstAttribute == NSLayoutAttribute.width }) 24 | return max(between: frame.size.width, andContantsOf: constraintsWidth) 25 | } 26 | 27 | var maxHeightEstimated: CGFloat { 28 | let constraintsHeight = constraints.filter({ $0.firstAttribute == NSLayoutAttribute.height }) 29 | return max(between: frame.size.height, andContantsOf: constraintsHeight) 30 | } 31 | 32 | private func max(between value: CGFloat, andContantsOf constraints: [NSLayoutConstraint]) -> CGFloat { 33 | let max = constraints.reduce(value, { max, constraint in 34 | var tempMax = max 35 | if constraint.constant > tempMax { tempMax = constraint.constant } 36 | return tempMax 37 | }) 38 | return max 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Extensions/UIView+IBInspectable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+IBInspectable.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 01/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private enum AssociatedKeys { 12 | static var skeletonable = "skeletonable" 13 | static var status = "status" 14 | static var skeletonLayer = "layer" 15 | static var flowDelegate = "flowDelegate" 16 | static var isSkeletonAnimated = "isSkeletonAnimated" 17 | } 18 | 19 | public extension UIView { 20 | 21 | @IBInspectable 22 | var isSkeletonable: Bool { 23 | get { return skeletonable } 24 | set { skeletonable = newValue } 25 | } 26 | 27 | var isSkeletonActive: Bool { 28 | return status == .on || (subviewsSkeletonables.first(where: { $0.isSkeletonActive }) != nil) 29 | } 30 | } 31 | 32 | extension UIView { 33 | 34 | enum Status { 35 | case on 36 | case off 37 | } 38 | 39 | var flowDelegate: SkeletonFlowDelegate? { 40 | get { return objc_getAssociatedObject(self, &AssociatedKeys.flowDelegate) as? SkeletonFlowDelegate } 41 | set { objc_setAssociatedObject(self, &AssociatedKeys.flowDelegate, newValue, AssociationPolicy.retain.objc) } 42 | } 43 | 44 | var skeletonLayer: SkeletonLayer? { 45 | get { return objc_getAssociatedObject(self, &AssociatedKeys.skeletonLayer) as? SkeletonLayer } 46 | set { objc_setAssociatedObject(self, &AssociatedKeys.skeletonLayer, newValue, AssociationPolicy.retain.objc) } 47 | } 48 | 49 | var status: Status! { 50 | get { return objc_getAssociatedObject(self, &AssociatedKeys.status) as? Status ?? .off } 51 | set { objc_setAssociatedObject(self, &AssociatedKeys.status, newValue, AssociationPolicy.retain.objc) } 52 | } 53 | 54 | var skeletonIsAnimated: Bool! { 55 | get { return objc_getAssociatedObject(self, &AssociatedKeys.isSkeletonAnimated) as? Bool ?? false } 56 | set { objc_setAssociatedObject(self, &AssociatedKeys.isSkeletonAnimated, newValue, AssociationPolicy.retain.objc) } 57 | } 58 | 59 | fileprivate var skeletonable: Bool! { 60 | get { return objc_getAssociatedObject(self, &AssociatedKeys.skeletonable) as? Bool ?? false } 61 | set { objc_setAssociatedObject(self, &AssociatedKeys.skeletonable, newValue, AssociationPolicy.retain.objc) } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Extensions/UIView+UIApplicationDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+UIApplicationDelegate.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 08/02/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | enum Constants { 14 | static let becomeActiveNotification = NSNotification.Name.UIApplicationDidBecomeActive 15 | static let enterForegroundNotification = NSNotification.Name.UIApplicationDidEnterBackground 16 | static let needAnimatedSkeletonKey = "needAnimateSkeleton" 17 | } 18 | 19 | func addAppNotificationsObservers() { 20 | NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: Constants.becomeActiveNotification, object: nil) 21 | NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: Constants.enterForegroundNotification, object: nil) 22 | } 23 | 24 | func removeAppNoticationsObserver() { 25 | NotificationCenter.default.removeObserver(self, name: Constants.becomeActiveNotification, object: nil) 26 | NotificationCenter.default.removeObserver(self, name: Constants.enterForegroundNotification, object: nil) 27 | } 28 | 29 | @objc func appDidBecomeActive() { 30 | if UserDefaults.standard.bool(forKey: Constants.needAnimatedSkeletonKey) { 31 | startSkeletonAnimation() 32 | } 33 | } 34 | 35 | @objc func appDidEnterBackground() { 36 | UserDefaults.standard.set((isSkeletonActive && skeletonIsAnimated), forKey: Constants.needAnimatedSkeletonKey) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Helpers/AssociationPolicy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AssociationPolicy.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | //Partially copy/pasted from https://github.com/jameslintaylor/AssociatedObjects/blob/master/AssociatedObjects/AssociatedObjects.swift 12 | enum AssociationPolicy: UInt { 13 | // raw values map to objc_AssociationPolicy's raw values 14 | case assign = 0 15 | case copy = 771 16 | case copyNonatomic = 3 17 | case retain = 769 18 | case retainNonatomic = 1 19 | 20 | var objc: objc_AssociationPolicy { 21 | return objc_AssociationPolicy(rawValue: rawValue)! 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Helpers/ContainsMultilineText.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContainsMultilineText.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 07/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private enum AssociatedKeys { 12 | static var lastLineFillingPercent = "lastLineFillingPercent" 13 | } 14 | 15 | protocol ContainsMultilineText { 16 | var numLines: Int { get } 17 | var lastLineFillingPercent: Int { get } 18 | } 19 | 20 | extension ContainsMultilineText { 21 | var numLines: Int { return 0 } 22 | } 23 | 24 | public extension UILabel { 25 | 26 | @IBInspectable 27 | var lastLineFillPercent: Int { 28 | get { return lastLineFillingPercent } 29 | set { lastLineFillingPercent = min(newValue, 100) } 30 | } 31 | } 32 | 33 | public extension UITextView { 34 | 35 | @IBInspectable 36 | var lastLineFillPercent: Int { 37 | get { return lastLineFillingPercent } 38 | set { lastLineFillingPercent = min(newValue, 100) } 39 | } 40 | } 41 | 42 | extension UILabel: ContainsMultilineText { 43 | var numLines: Int { 44 | return numberOfLines 45 | } 46 | 47 | var lastLineFillingPercent: Int { 48 | get { return objc_getAssociatedObject(self, &AssociatedKeys.lastLineFillingPercent) as? Int ?? SkeletonDefaultConfig.multilineLastLineFillPercent } 49 | set { objc_setAssociatedObject(self, &AssociatedKeys.lastLineFillingPercent, newValue, AssociationPolicy.retain.objc) } 50 | } 51 | } 52 | extension UITextView: ContainsMultilineText { 53 | 54 | var lastLineFillingPercent: Int { 55 | get { return objc_getAssociatedObject(self, &AssociatedKeys.lastLineFillingPercent) as? Int ?? SkeletonDefaultConfig.multilineLastLineFillPercent } 56 | set { objc_setAssociatedObject(self, &AssociatedKeys.lastLineFillingPercent, newValue, AssociationPolicy.retain.objc) } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Helpers/PrepareForSkeletonProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrepareForSkeleton.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 04/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol PrepareForSkeleton { 12 | func prepareViewForSkeleton() 13 | } 14 | 15 | extension UILabel: PrepareForSkeleton { 16 | func prepareViewForSkeleton() { 17 | text = nil 18 | resignFirstResponder() 19 | } 20 | } 21 | 22 | extension UITextView: PrepareForSkeleton { 23 | func prepareViewForSkeleton() { 24 | text = nil 25 | resignFirstResponder() 26 | } 27 | } 28 | 29 | extension UIImageView: PrepareForSkeleton { 30 | func prepareViewForSkeleton() { 31 | image = nil 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/Helpers/RecursiveProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelperProtocols.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 06/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias VoidBlock = () -> Void 12 | typealias RecursiveBlock = (T) -> Void 13 | 14 | //MARK: Recursive 15 | protocol Recursive { 16 | associatedtype Element 17 | func recursiveSearch(inArray array:[Element], leafBlock: VoidBlock, recursiveBlock: RecursiveBlock) 18 | } 19 | 20 | extension Recursive { 21 | func recursiveSearch(inArray array:[Element], leafBlock: VoidBlock, recursiveBlock: RecursiveBlock) { 22 | guard array.count > 0 else { 23 | leafBlock() 24 | return 25 | } 26 | array.forEach { recursiveBlock($0) } 27 | } 28 | } 29 | 30 | extension UIView: Recursive { 31 | typealias Element = UIView 32 | } 33 | extension CALayer: Recursive { 34 | typealias Element = CALayer 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonAnimationBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonAnimationBuilder.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 17/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias GradientAnimationPoint = (from: CGPoint, to: CGPoint) 12 | 13 | public enum GradientDirection { 14 | case leftRight 15 | case rightLeft 16 | case topBottom 17 | case bottomTop 18 | case topLeftBottomRight 19 | case bottomRightTopLeft 20 | 21 | public func slidingAnimation(duration: CFTimeInterval = 1.5) -> SkeletonLayerAnimation { 22 | return SkeletonAnimationBuilder().makeSlidingAnimation(withDirection: self, duration: duration) 23 | } 24 | 25 | var startPoint: GradientAnimationPoint { 26 | switch self { 27 | case .leftRight: 28 | return (from: CGPoint(x:-1, y:0.5), to: CGPoint(x:1, y:0.5)) 29 | case .rightLeft: 30 | return (from: CGPoint(x:1, y:0.5), to: CGPoint(x:-1, y:0.5)) 31 | case .topBottom: 32 | return (from: CGPoint(x:0.5, y:-1), to: CGPoint(x:0.5, y:1)) 33 | case .bottomTop: 34 | return (from: CGPoint(x:0.5, y:1), to: CGPoint(x:0.5, y:-1)) 35 | case .topLeftBottomRight: 36 | return (from: CGPoint(x:-1, y:-1), to: CGPoint(x:1, y:1)) 37 | case .bottomRightTopLeft: 38 | return (from: CGPoint(x:1, y:1), to: CGPoint(x:-1, y:-1)) 39 | } 40 | } 41 | 42 | var endPoint: GradientAnimationPoint { 43 | switch self { 44 | case .leftRight: 45 | return (from: CGPoint(x:0, y:0.5), to: CGPoint(x:2, y:0.5)) 46 | case .rightLeft: 47 | return ( from: CGPoint(x:2, y:0.5), to: CGPoint(x:0, y:0.5)) 48 | case .topBottom: 49 | return ( from: CGPoint(x:0.5, y:0), to: CGPoint(x:0.5, y:2)) 50 | case .bottomTop: 51 | return ( from: CGPoint(x:0.5, y:2), to: CGPoint(x:0.5, y:0)) 52 | case .topLeftBottomRight: 53 | return ( from: CGPoint(x:0, y:0), to: CGPoint(x:2, y:2)) 54 | case .bottomRightTopLeft: 55 | return ( from: CGPoint(x:2, y:2), to: CGPoint(x:0, y:0)) 56 | } 57 | } 58 | } 59 | 60 | public class SkeletonAnimationBuilder { 61 | 62 | public init() { 63 | } 64 | 65 | public func makeSlidingAnimation(withDirection direction: GradientDirection, duration: CFTimeInterval = 1.5) -> SkeletonLayerAnimation { 66 | return { layer in 67 | 68 | let startPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.startPoint)) 69 | startPointAnim.fromValue = direction.startPoint.from 70 | startPointAnim.toValue = direction.startPoint.to 71 | 72 | let endPointAnim = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.endPoint)) 73 | endPointAnim.fromValue = direction.endPoint.from 74 | endPointAnim.toValue = direction.endPoint.to 75 | 76 | let animGroup = CAAnimationGroup() 77 | animGroup.animations = [startPointAnim, endPointAnim] 78 | animGroup.duration = duration 79 | animGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 80 | animGroup.repeatCount = .infinity 81 | 82 | return animGroup 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonDefaultConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonDefaultConfig.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 06/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public enum SkeletonDefaultConfig { 12 | 13 | public static let tintColor = UIColor.clouds 14 | 15 | public static let gradient = SkeletonGradient(baseColor: tintColor) 16 | 17 | public static let multilineHeight: CGFloat = 15 18 | 19 | public static let multilineSpacing: CGFloat = 10 20 | 21 | public static let multilineLastLineFillPercent = 70 22 | } 23 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonFlow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonFlow.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 08/02/2018. 6 | // Copyright © 2018 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol SkeletonFlowDelegate { 12 | func willBeginShowingSkeletons(withRootView rootView: UIView) 13 | func willBeginHidingSkeletons(withRootView rootView: UIView) 14 | } 15 | 16 | class SkeletonFlowHandler: SkeletonFlowDelegate { 17 | 18 | func willBeginShowingSkeletons(withRootView rootView: UIView) { 19 | rootView.addAppNotificationsObservers() 20 | } 21 | 22 | func willBeginHidingSkeletons(withRootView rootView: UIView) { 23 | rootView.removeAppNoticationsObserver() 24 | rootView.flowDelegate = nil 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonGradient.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonGradient.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 05/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public struct SkeletonGradient { 12 | 13 | private var gradientColors: [UIColor] 14 | 15 | public var colors: [UIColor] { 16 | return gradientColors 17 | } 18 | 19 | public init(baseColor: UIColor, secondaryColor: UIColor? = nil) { 20 | if let secondary = secondaryColor { 21 | self.gradientColors = [baseColor, secondary, baseColor] 22 | } else { 23 | self.gradientColors = baseColor.makeGradient() 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonLayer.swift 3 | // SkeletonView-iOS 4 | // 5 | // Created by Juanpe Catalán on 02/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SkeletonLayerFactory { 12 | 13 | func makeSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], andHolder holder: UIView) -> SkeletonLayer { 14 | return SkeletonLayer(withType: type, usingColors: colors, andSkeletonHolder: holder) 15 | } 16 | 17 | func makeMultilineLayer(withType type: SkeletonType, for index: Int, width: CGFloat) -> CALayer { 18 | let spaceRequiredForEachLine = SkeletonDefaultConfig.multilineHeight + SkeletonDefaultConfig.multilineSpacing 19 | let layer = type.layer 20 | layer.anchorPoint = .zero 21 | layer.name = CALayer.skeletonSubLayersName 22 | layer.frame = CGRect(x: 0.0, y: CGFloat(index) * spaceRequiredForEachLine, width: width, height: SkeletonDefaultConfig.multilineHeight) 23 | return layer 24 | } 25 | } 26 | 27 | public typealias SkeletonLayerAnimation = (CALayer) -> CAAnimation 28 | 29 | public enum SkeletonType { 30 | case solid 31 | case gradient 32 | 33 | var layer: CALayer { 34 | switch self { 35 | case .solid: 36 | return CALayer() 37 | case .gradient: 38 | return CAGradientLayer() 39 | } 40 | } 41 | 42 | var layerAnimation: SkeletonLayerAnimation { 43 | switch self { 44 | case .solid: 45 | return { $0.pulse } 46 | case .gradient: 47 | return { $0.sliding } 48 | } 49 | } 50 | } 51 | 52 | struct SkeletonLayer { 53 | 54 | private var maskLayer: CALayer 55 | private weak var holder: UIView? 56 | 57 | var type: SkeletonType { 58 | return maskLayer is CAGradientLayer ? .gradient : .solid 59 | } 60 | 61 | var contentLayer: CALayer { 62 | return maskLayer 63 | } 64 | 65 | init(withType type: SkeletonType, usingColors colors: [UIColor], andSkeletonHolder holder: UIView) { 66 | self.holder = holder 67 | self.maskLayer = type.layer 68 | self.maskLayer.anchorPoint = .zero 69 | self.maskLayer.bounds = holder.maxBoundsEstimated 70 | addMultilinesIfNeeded() 71 | self.maskLayer.tint(withColors: colors) 72 | } 73 | 74 | func removeLayer() { 75 | maskLayer.removeFromSuperlayer() 76 | } 77 | 78 | func addMultilinesIfNeeded() { 79 | guard let multiLineView = holder as? ContainsMultilineText else { return } 80 | maskLayer.addMultilinesLayers(lines: multiLineView.numLines, type: type, lastLineFillPercent: multiLineView.lastLineFillingPercent) 81 | } 82 | } 83 | 84 | extension SkeletonLayer { 85 | 86 | func start(_ anim: SkeletonLayerAnimation? = nil) { 87 | let animation = anim ?? type.layerAnimation 88 | contentLayer.playAnimation(animation, key: "skeletonAnimation") 89 | } 90 | 91 | func stopAnimation() { 92 | contentLayer.stopAnimation(forKey: "skeletonAnimation") 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Pods/SkeletonView/Sources/SkeletonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonView.swift 3 | // SkeletonView 4 | // 5 | // Created by Juanpe Catalán on 01/11/2017. 6 | // Copyright © 2017 SkeletonView. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension UIView { 12 | 13 | func showSkeleton(usingColor color: UIColor = SkeletonDefaultConfig.tintColor) { 14 | showSkeleton(withType: .solid, usingColors: [color]) 15 | } 16 | 17 | func showGradientSkeleton(usingGradient gradient: SkeletonGradient = SkeletonDefaultConfig.gradient) { 18 | showSkeleton(withType: .gradient, usingColors: gradient.colors) 19 | } 20 | 21 | func showAnimatedSkeleton(usingColor color: UIColor = SkeletonDefaultConfig.tintColor, animation: SkeletonLayerAnimation? = nil) { 22 | showSkeleton(withType: .solid, usingColors: [color], animated: true, animation: animation) 23 | } 24 | 25 | func showAnimatedGradientSkeleton(usingGradient gradient: SkeletonGradient = SkeletonDefaultConfig.gradient, animation: SkeletonLayerAnimation? = nil) { 26 | showSkeleton(withType: .gradient, usingColors: gradient.colors, animated: true, animation: animation) 27 | } 28 | 29 | func hideSkeleton(reloadDataAfter reload: Bool = true) { 30 | flowDelegate?.willBeginHidingSkeletons(withRootView: self) 31 | recursiveHideSkeleton(reloadDataAfter: reload) 32 | } 33 | 34 | func startSkeletonAnimation(_ anim: SkeletonLayerAnimation? = nil) { 35 | skeletonIsAnimated = true 36 | recursiveSearch(inArray: subviewsSkeletonables, 37 | leafBlock: startSkeletonLayerAnimationBlock(anim)) { 38 | $0.startSkeletonAnimation(anim) 39 | } 40 | } 41 | 42 | func stopSkeletonAnimation() { 43 | skeletonIsAnimated = false 44 | recursiveSearch(inArray: subviewsSkeletonables, 45 | leafBlock: stopSkeletonLayerAnimationBlock) { 46 | $0.stopSkeletonAnimation() 47 | } 48 | } 49 | } 50 | 51 | extension UIView { 52 | 53 | func showSkeleton(withType type: SkeletonType = .solid, usingColors colors: [UIColor], animated: Bool = false, animation: SkeletonLayerAnimation? = nil) { 54 | skeletonIsAnimated = animated 55 | flowDelegate = SkeletonFlowHandler() 56 | flowDelegate?.willBeginShowingSkeletons(withRootView: self) 57 | recursiveShowSkeleton(withType: type, usingColors: colors, animated: animated, animation: animation) 58 | } 59 | 60 | fileprivate func recursiveShowSkeleton(withType type: SkeletonType = .solid, usingColors colors: [UIColor], animated: Bool = false, animation: SkeletonLayerAnimation? = nil) { 61 | addDummyDataSourceIfNeeded() 62 | recursiveSearch(inArray: subviewsSkeletonables, 63 | leafBlock: { 64 | guard !isSkeletonActive else { return } 65 | isUserInteractionEnabled = false 66 | (self as? PrepareForSkeleton)?.prepareViewForSkeleton() 67 | addSkeletonLayer(withType: type, usingColors: colors, animated: animated, animation: animation) 68 | }) { 69 | $0.recursiveShowSkeleton(withType: type, usingColors: colors, animated: animated, animation: animation) 70 | } 71 | } 72 | 73 | fileprivate func recursiveHideSkeleton(reloadDataAfter reload: Bool = true) { 74 | removeDummyDataSourceIfNeeded() 75 | isUserInteractionEnabled = true 76 | recursiveSearch(inArray: subviewsSkeletonables, 77 | leafBlock: { 78 | removeSkeletonLayer() 79 | }, recursiveBlock: { 80 | $0.recursiveHideSkeleton(reloadDataAfter: reload) 81 | }) 82 | } 83 | 84 | fileprivate func startSkeletonLayerAnimationBlock(_ anim: SkeletonLayerAnimation? = nil) -> VoidBlock { 85 | return { 86 | guard let layer = self.skeletonLayer else { return } 87 | layer.start(anim) 88 | } 89 | } 90 | 91 | fileprivate var stopSkeletonLayerAnimationBlock: VoidBlock { 92 | return { 93 | guard let layer = self.skeletonLayer else { return } 94 | layer.stopAnimation() 95 | } 96 | } 97 | } 98 | 99 | extension UIView { 100 | @objc var subviewsSkeletonables: [UIView] { 101 | return subviews.filter { $0.isSkeletonable } 102 | } 103 | } 104 | 105 | extension UITableView { 106 | override var subviewsSkeletonables: [UIView] { 107 | return visibleCells.filter { $0.isSkeletonable } 108 | } 109 | } 110 | 111 | extension UITableViewCell { 112 | override var subviewsSkeletonables: [UIView] { 113 | return contentView.subviews.filter { $0.isSkeletonable } 114 | } 115 | } 116 | 117 | extension UICollectionView { 118 | override var subviewsSkeletonables: [UIView] { 119 | return subviews.filter { $0.isSkeletonable } 120 | } 121 | } 122 | 123 | extension UICollectionViewCell { 124 | override var subviewsSkeletonables: [UIView] { 125 | return contentView.subviews.filter { $0.isSkeletonable } 126 | } 127 | } 128 | 129 | extension UIStackView { 130 | override var subviewsSkeletonables: [UIView] { 131 | return arrangedSubviews.filter { $0.isSkeletonable } 132 | } 133 | } 134 | 135 | extension UIView { 136 | 137 | func addSkeletonLayer(withType type: SkeletonType, usingColors colors: [UIColor], gradientDirection direction: GradientDirection? = nil, animated: Bool, animation: SkeletonLayerAnimation? = nil) { 138 | self.skeletonLayer = SkeletonLayerFactory().makeSkeletonLayer(withType: type, usingColors: colors, andHolder: self) 139 | layer.insertSublayer(skeletonLayer!.contentLayer, at: UInt32.max) 140 | if animated { skeletonLayer!.start(animation) } 141 | status = .on 142 | } 143 | 144 | func removeSkeletonLayer() { 145 | guard isSkeletonActive, 146 | let layer = skeletonLayer else { return } 147 | layer.stopAnimation() 148 | layer.removeLayer() 149 | skeletonLayer = nil 150 | status = .off 151 | } 152 | } 153 | 154 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## SkeletonView 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2017 Juanpe Catalán 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | Generated by CocoaPods - https://cocoapods.org 30 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2017 Juanpe Catalán 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | 40 | License 41 | MIT 42 | Title 43 | SkeletonView 44 | Type 45 | PSGroupSpecifier 46 | 47 | 48 | FooterText 49 | Generated by CocoaPods - https://cocoapods.org 50 | Title 51 | 52 | Type 53 | PSGroupSpecifier 54 | 55 | 56 | StringsTable 57 | Acknowledgements 58 | Title 59 | Acknowledgements 60 | 61 | 62 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_SkeletonDemo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_SkeletonDemo 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 12 | 13 | install_framework() 14 | { 15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 16 | local source="${BUILT_PRODUCTS_DIR}/$1" 17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 19 | elif [ -r "$1" ]; then 20 | local source="$1" 21 | fi 22 | 23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | 25 | if [ -L "${source}" ]; then 26 | echo "Symlinked..." 27 | source="$(readlink "${source}")" 28 | fi 29 | 30 | # Use filter instead of exclude so missing patterns don't throw errors. 31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 33 | 34 | local basename 35 | basename="$(basename -s .framework "$1")" 36 | binary="${destination}/${basename}.framework/${basename}" 37 | if ! [ -r "$binary" ]; then 38 | binary="${destination}/${basename}" 39 | fi 40 | 41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 43 | strip_invalid_archs "$binary" 44 | fi 45 | 46 | # Resign the code if required by the build settings to avoid unstable apps 47 | code_sign_if_enabled "${destination}/$(basename "$1")" 48 | 49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 51 | local swift_runtime_libs 52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 53 | for lib in $swift_runtime_libs; do 54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 56 | code_sign_if_enabled "${destination}/${lib}" 57 | done 58 | fi 59 | } 60 | 61 | # Copies the dSYM of a vendored framework 62 | install_dsym() { 63 | local source="$1" 64 | if [ -r "$source" ]; then 65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" 66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" 67 | fi 68 | } 69 | 70 | # Signs a framework with the provided identity 71 | code_sign_if_enabled() { 72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 73 | # Use the current code_sign_identitiy 74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'" 76 | 77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 78 | code_sign_cmd="$code_sign_cmd &" 79 | fi 80 | echo "$code_sign_cmd" 81 | eval "$code_sign_cmd" 82 | fi 83 | } 84 | 85 | # Strip invalid architectures 86 | strip_invalid_archs() { 87 | binary="$1" 88 | # Get architectures for current file 89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 90 | stripped="" 91 | for arch in $archs; do 92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 93 | # Strip non-valid architectures in-place 94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 95 | stripped="$stripped $arch" 96 | fi 97 | done 98 | if [[ "$stripped" ]]; then 99 | echo "Stripped $binary of architectures:$stripped" 100 | fi 101 | } 102 | 103 | 104 | if [[ "$CONFIGURATION" == "Debug" ]]; then 105 | install_framework "${BUILT_PRODUCTS_DIR}/SkeletonView/SkeletonView.framework" 106 | fi 107 | if [[ "$CONFIGURATION" == "Release" ]]; then 108 | install_framework "${BUILT_PRODUCTS_DIR}/SkeletonView/SkeletonView.framework" 109 | fi 110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 111 | wait 112 | fi 113 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 14 | 15 | case "${TARGETED_DEVICE_FAMILY}" in 16 | 1,2) 17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 18 | ;; 19 | 1) 20 | TARGET_DEVICE_ARGS="--target-device iphone" 21 | ;; 22 | 2) 23 | TARGET_DEVICE_ARGS="--target-device ipad" 24 | ;; 25 | 3) 26 | TARGET_DEVICE_ARGS="--target-device tv" 27 | ;; 28 | 4) 29 | TARGET_DEVICE_ARGS="--target-device watch" 30 | ;; 31 | *) 32 | TARGET_DEVICE_ARGS="--target-device mac" 33 | ;; 34 | esac 35 | 36 | install_resource() 37 | { 38 | if [[ "$1" = /* ]] ; then 39 | RESOURCE_PATH="$1" 40 | else 41 | RESOURCE_PATH="${PODS_ROOT}/$1" 42 | fi 43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 44 | cat << EOM 45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 46 | EOM 47 | exit 1 48 | fi 49 | case $RESOURCE_PATH in 50 | *.storyboard) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.xib) 55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 57 | ;; 58 | *.framework) 59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 63 | ;; 64 | *.xcdatamodel) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 67 | ;; 68 | *.xcdatamodeld) 69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 71 | ;; 72 | *.xcmappingmodel) 73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 75 | ;; 76 | *.xcassets) 77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 79 | ;; 80 | *) 81 | echo "$RESOURCE_PATH" || true 82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 83 | ;; 84 | esac 85 | } 86 | 87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 92 | fi 93 | rm -f "$RESOURCES_TO_COPY" 94 | 95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 96 | then 97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 99 | while read line; do 100 | if [[ $line != "${PODS_ROOT}*" ]]; then 101 | XCASSET_FILES+=("$line") 102 | fi 103 | done <<<"$OTHER_XCASSETS" 104 | 105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 106 | fi 107 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_SkeletonDemoVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_SkeletonDemoVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SkeletonView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SkeletonView/SkeletonView.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "SkeletonView" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_SkeletonDemo { 2 | umbrella header "Pods-SkeletonDemo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SkeletonView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/SkeletonView/SkeletonView.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "SkeletonView" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/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.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/SkeletonView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SkeletonView : NSObject 3 | @end 4 | @implementation PodsDummy_SkeletonView 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/SkeletonView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/SkeletonView-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double SkeletonViewVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char SkeletonViewVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/SkeletonView.modulemap: -------------------------------------------------------------------------------- 1 | framework module SkeletonView { 2 | umbrella header "SkeletonView-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SkeletonView/SkeletonView.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SkeletonView 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SkeletonView 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SkeletonDemo 2 | Skeleton Screen加载占位图,在页面数据没显示之前,加载一个与页面有数据样式布局类似的界面,facebook,简书,微信读书等使用中 3 | -------------------------------------------------------------------------------- /SkeletonDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0F8FCD496E6F63F2D8C90C20 /* Pods_SkeletonDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9904588AD1A3A3F65191348C /* Pods_SkeletonDemo.framework */; }; 11 | CF0F55B320EC6AF60026CA7C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55B220EC6AF60026CA7C /* AppDelegate.swift */; }; 12 | CF0F55B520EC6AF70026CA7C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55B420EC6AF70026CA7C /* ViewController.swift */; }; 13 | CF0F55B820EC6AF70026CA7C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CF0F55B620EC6AF70026CA7C /* Main.storyboard */; }; 14 | CF0F55BA20EC6AF70026CA7C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CF0F55B920EC6AF70026CA7C /* Assets.xcassets */; }; 15 | CF0F55BD20EC6AF70026CA7C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CF0F55BB20EC6AF70026CA7C /* LaunchScreen.storyboard */; }; 16 | CF0F55C820EC6AF70026CA7C /* SkeletonDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55C720EC6AF70026CA7C /* SkeletonDemoTests.swift */; }; 17 | CF0F55D320EC6AF70026CA7C /* SkeletonDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55D220EC6AF70026CA7C /* SkeletonDemoUITests.swift */; }; 18 | CF0F55E220EC70990026CA7C /* CustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55E020EC70990026CA7C /* CustomCell.swift */; }; 19 | CF0F55E320EC70990026CA7C /* CustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF0F55E120EC70990026CA7C /* CustomCell.xib */; }; 20 | CF0F55E720EC7ED40026CA7C /* HeaderVeiw.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF0F55E620EC7ED40026CA7C /* HeaderVeiw.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | CF0F55C420EC6AF70026CA7C /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = CF0F55A720EC6AF60026CA7C /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = CF0F55AE20EC6AF60026CA7C; 29 | remoteInfo = SkeletonDemo; 30 | }; 31 | CF0F55CF20EC6AF70026CA7C /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = CF0F55A720EC6AF60026CA7C /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = CF0F55AE20EC6AF60026CA7C; 36 | remoteInfo = SkeletonDemo; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 749E0B27BE20BDCC1E798617 /* Pods-SkeletonDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SkeletonDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.debug.xcconfig"; sourceTree = ""; }; 42 | 96F019AAFE71102AD2E9ACD5 /* Pods-SkeletonDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SkeletonDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo.release.xcconfig"; sourceTree = ""; }; 43 | 9904588AD1A3A3F65191348C /* Pods_SkeletonDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SkeletonDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | CF0F55AF20EC6AF60026CA7C /* SkeletonDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SkeletonDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | CF0F55B220EC6AF60026CA7C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 46 | CF0F55B420EC6AF70026CA7C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 47 | CF0F55B720EC6AF70026CA7C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 48 | CF0F55B920EC6AF70026CA7C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 49 | CF0F55BC20EC6AF70026CA7C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 50 | CF0F55BE20EC6AF70026CA7C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | CF0F55C320EC6AF70026CA7C /* SkeletonDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SkeletonDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | CF0F55C720EC6AF70026CA7C /* SkeletonDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonDemoTests.swift; sourceTree = ""; }; 53 | CF0F55C920EC6AF70026CA7C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | CF0F55CE20EC6AF70026CA7C /* SkeletonDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SkeletonDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | CF0F55D220EC6AF70026CA7C /* SkeletonDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkeletonDemoUITests.swift; sourceTree = ""; }; 56 | CF0F55D420EC6AF70026CA7C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | CF0F55E020EC70990026CA7C /* CustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCell.swift; sourceTree = ""; }; 58 | CF0F55E120EC70990026CA7C /* CustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomCell.xib; sourceTree = ""; }; 59 | CF0F55E620EC7ED40026CA7C /* HeaderVeiw.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderVeiw.swift; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | CF0F55AC20EC6AF60026CA7C /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 0F8FCD496E6F63F2D8C90C20 /* Pods_SkeletonDemo.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | CF0F55C020EC6AF70026CA7C /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | CF0F55CB20EC6AF70026CA7C /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | 0B87C1F6E82402947968138C /* Frameworks */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 9904588AD1A3A3F65191348C /* Pods_SkeletonDemo.framework */, 92 | ); 93 | name = Frameworks; 94 | sourceTree = ""; 95 | }; 96 | CF0F55A620EC6AF60026CA7C = { 97 | isa = PBXGroup; 98 | children = ( 99 | CF0F55B120EC6AF60026CA7C /* SkeletonDemo */, 100 | CF0F55C620EC6AF70026CA7C /* SkeletonDemoTests */, 101 | CF0F55D120EC6AF70026CA7C /* SkeletonDemoUITests */, 102 | CF0F55B020EC6AF60026CA7C /* Products */, 103 | E0C770B133899F099E6FF09E /* Pods */, 104 | 0B87C1F6E82402947968138C /* Frameworks */, 105 | ); 106 | sourceTree = ""; 107 | }; 108 | CF0F55B020EC6AF60026CA7C /* Products */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | CF0F55AF20EC6AF60026CA7C /* SkeletonDemo.app */, 112 | CF0F55C320EC6AF70026CA7C /* SkeletonDemoTests.xctest */, 113 | CF0F55CE20EC6AF70026CA7C /* SkeletonDemoUITests.xctest */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | CF0F55B120EC6AF60026CA7C /* SkeletonDemo */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | CF0F55B220EC6AF60026CA7C /* AppDelegate.swift */, 122 | CF0F55B420EC6AF70026CA7C /* ViewController.swift */, 123 | CF0F55E020EC70990026CA7C /* CustomCell.swift */, 124 | CF0F55E620EC7ED40026CA7C /* HeaderVeiw.swift */, 125 | CF0F55E120EC70990026CA7C /* CustomCell.xib */, 126 | CF0F55B620EC6AF70026CA7C /* Main.storyboard */, 127 | CF0F55B920EC6AF70026CA7C /* Assets.xcassets */, 128 | CF0F55BB20EC6AF70026CA7C /* LaunchScreen.storyboard */, 129 | CF0F55BE20EC6AF70026CA7C /* Info.plist */, 130 | ); 131 | path = SkeletonDemo; 132 | sourceTree = ""; 133 | }; 134 | CF0F55C620EC6AF70026CA7C /* SkeletonDemoTests */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | CF0F55C720EC6AF70026CA7C /* SkeletonDemoTests.swift */, 138 | CF0F55C920EC6AF70026CA7C /* Info.plist */, 139 | ); 140 | path = SkeletonDemoTests; 141 | sourceTree = ""; 142 | }; 143 | CF0F55D120EC6AF70026CA7C /* SkeletonDemoUITests */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | CF0F55D220EC6AF70026CA7C /* SkeletonDemoUITests.swift */, 147 | CF0F55D420EC6AF70026CA7C /* Info.plist */, 148 | ); 149 | path = SkeletonDemoUITests; 150 | sourceTree = ""; 151 | }; 152 | E0C770B133899F099E6FF09E /* Pods */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 749E0B27BE20BDCC1E798617 /* Pods-SkeletonDemo.debug.xcconfig */, 156 | 96F019AAFE71102AD2E9ACD5 /* Pods-SkeletonDemo.release.xcconfig */, 157 | ); 158 | name = Pods; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | CF0F55AE20EC6AF60026CA7C /* SkeletonDemo */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = CF0F55D720EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemo" */; 167 | buildPhases = ( 168 | 2984B004D627AB21D8498C41 /* [CP] Check Pods Manifest.lock */, 169 | CF0F55AB20EC6AF60026CA7C /* Sources */, 170 | CF0F55AC20EC6AF60026CA7C /* Frameworks */, 171 | CF0F55AD20EC6AF60026CA7C /* Resources */, 172 | DAA8239735CB77782AA645D8 /* [CP] Embed Pods Frameworks */, 173 | D9E1D4DE3391C15927EE3040 /* [CP] Copy Pods Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = SkeletonDemo; 180 | productName = SkeletonDemo; 181 | productReference = CF0F55AF20EC6AF60026CA7C /* SkeletonDemo.app */; 182 | productType = "com.apple.product-type.application"; 183 | }; 184 | CF0F55C220EC6AF70026CA7C /* SkeletonDemoTests */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = CF0F55DA20EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemoTests" */; 187 | buildPhases = ( 188 | CF0F55BF20EC6AF70026CA7C /* Sources */, 189 | CF0F55C020EC6AF70026CA7C /* Frameworks */, 190 | CF0F55C120EC6AF70026CA7C /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | CF0F55C520EC6AF70026CA7C /* PBXTargetDependency */, 196 | ); 197 | name = SkeletonDemoTests; 198 | productName = SkeletonDemoTests; 199 | productReference = CF0F55C320EC6AF70026CA7C /* SkeletonDemoTests.xctest */; 200 | productType = "com.apple.product-type.bundle.unit-test"; 201 | }; 202 | CF0F55CD20EC6AF70026CA7C /* SkeletonDemoUITests */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = CF0F55DD20EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemoUITests" */; 205 | buildPhases = ( 206 | CF0F55CA20EC6AF70026CA7C /* Sources */, 207 | CF0F55CB20EC6AF70026CA7C /* Frameworks */, 208 | CF0F55CC20EC6AF70026CA7C /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | CF0F55D020EC6AF70026CA7C /* PBXTargetDependency */, 214 | ); 215 | name = SkeletonDemoUITests; 216 | productName = SkeletonDemoUITests; 217 | productReference = CF0F55CE20EC6AF70026CA7C /* SkeletonDemoUITests.xctest */; 218 | productType = "com.apple.product-type.bundle.ui-testing"; 219 | }; 220 | /* End PBXNativeTarget section */ 221 | 222 | /* Begin PBXProject section */ 223 | CF0F55A720EC6AF60026CA7C /* Project object */ = { 224 | isa = PBXProject; 225 | attributes = { 226 | LastSwiftUpdateCheck = 0920; 227 | LastUpgradeCheck = 0920; 228 | ORGANIZATIONNAME = "知言网络"; 229 | TargetAttributes = { 230 | CF0F55AE20EC6AF60026CA7C = { 231 | CreatedOnToolsVersion = 9.2; 232 | ProvisioningStyle = Automatic; 233 | }; 234 | CF0F55C220EC6AF70026CA7C = { 235 | CreatedOnToolsVersion = 9.2; 236 | ProvisioningStyle = Automatic; 237 | TestTargetID = CF0F55AE20EC6AF60026CA7C; 238 | }; 239 | CF0F55CD20EC6AF70026CA7C = { 240 | CreatedOnToolsVersion = 9.2; 241 | ProvisioningStyle = Automatic; 242 | TestTargetID = CF0F55AE20EC6AF60026CA7C; 243 | }; 244 | }; 245 | }; 246 | buildConfigurationList = CF0F55AA20EC6AF60026CA7C /* Build configuration list for PBXProject "SkeletonDemo" */; 247 | compatibilityVersion = "Xcode 8.0"; 248 | developmentRegion = en; 249 | hasScannedForEncodings = 0; 250 | knownRegions = ( 251 | en, 252 | Base, 253 | ); 254 | mainGroup = CF0F55A620EC6AF60026CA7C; 255 | productRefGroup = CF0F55B020EC6AF60026CA7C /* Products */; 256 | projectDirPath = ""; 257 | projectRoot = ""; 258 | targets = ( 259 | CF0F55AE20EC6AF60026CA7C /* SkeletonDemo */, 260 | CF0F55C220EC6AF70026CA7C /* SkeletonDemoTests */, 261 | CF0F55CD20EC6AF70026CA7C /* SkeletonDemoUITests */, 262 | ); 263 | }; 264 | /* End PBXProject section */ 265 | 266 | /* Begin PBXResourcesBuildPhase section */ 267 | CF0F55AD20EC6AF60026CA7C /* Resources */ = { 268 | isa = PBXResourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | CF0F55BD20EC6AF70026CA7C /* LaunchScreen.storyboard in Resources */, 272 | CF0F55BA20EC6AF70026CA7C /* Assets.xcassets in Resources */, 273 | CF0F55E320EC70990026CA7C /* CustomCell.xib in Resources */, 274 | CF0F55B820EC6AF70026CA7C /* Main.storyboard in Resources */, 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | }; 278 | CF0F55C120EC6AF70026CA7C /* Resources */ = { 279 | isa = PBXResourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | CF0F55CC20EC6AF70026CA7C /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXResourcesBuildPhase section */ 293 | 294 | /* Begin PBXShellScriptBuildPhase section */ 295 | 2984B004D627AB21D8498C41 /* [CP] Check Pods Manifest.lock */ = { 296 | isa = PBXShellScriptBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | ); 300 | inputPaths = ( 301 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 302 | "${PODS_ROOT}/Manifest.lock", 303 | ); 304 | name = "[CP] Check Pods Manifest.lock"; 305 | outputPaths = ( 306 | "$(DERIVED_FILE_DIR)/Pods-SkeletonDemo-checkManifestLockResult.txt", 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | shellPath = /bin/sh; 310 | 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"; 311 | showEnvVarsInLog = 0; 312 | }; 313 | D9E1D4DE3391C15927EE3040 /* [CP] Copy Pods Resources */ = { 314 | isa = PBXShellScriptBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | ); 318 | inputPaths = ( 319 | ); 320 | name = "[CP] Copy Pods Resources"; 321 | outputPaths = ( 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | shellPath = /bin/sh; 325 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-resources.sh\"\n"; 326 | showEnvVarsInLog = 0; 327 | }; 328 | DAA8239735CB77782AA645D8 /* [CP] Embed Pods Frameworks */ = { 329 | isa = PBXShellScriptBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | ); 333 | inputPaths = ( 334 | "${SRCROOT}/Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-frameworks.sh", 335 | "${BUILT_PRODUCTS_DIR}/SkeletonView/SkeletonView.framework", 336 | ); 337 | name = "[CP] Embed Pods Frameworks"; 338 | outputPaths = ( 339 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SkeletonView.framework", 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | shellPath = /bin/sh; 343 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SkeletonDemo/Pods-SkeletonDemo-frameworks.sh\"\n"; 344 | showEnvVarsInLog = 0; 345 | }; 346 | /* End PBXShellScriptBuildPhase section */ 347 | 348 | /* Begin PBXSourcesBuildPhase section */ 349 | CF0F55AB20EC6AF60026CA7C /* Sources */ = { 350 | isa = PBXSourcesBuildPhase; 351 | buildActionMask = 2147483647; 352 | files = ( 353 | CF0F55B520EC6AF70026CA7C /* ViewController.swift in Sources */, 354 | CF0F55E220EC70990026CA7C /* CustomCell.swift in Sources */, 355 | CF0F55B320EC6AF60026CA7C /* AppDelegate.swift in Sources */, 356 | CF0F55E720EC7ED40026CA7C /* HeaderVeiw.swift in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | CF0F55BF20EC6AF70026CA7C /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | CF0F55C820EC6AF70026CA7C /* SkeletonDemoTests.swift in Sources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | CF0F55CA20EC6AF70026CA7C /* Sources */ = { 369 | isa = PBXSourcesBuildPhase; 370 | buildActionMask = 2147483647; 371 | files = ( 372 | CF0F55D320EC6AF70026CA7C /* SkeletonDemoUITests.swift in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | /* End PBXSourcesBuildPhase section */ 377 | 378 | /* Begin PBXTargetDependency section */ 379 | CF0F55C520EC6AF70026CA7C /* PBXTargetDependency */ = { 380 | isa = PBXTargetDependency; 381 | target = CF0F55AE20EC6AF60026CA7C /* SkeletonDemo */; 382 | targetProxy = CF0F55C420EC6AF70026CA7C /* PBXContainerItemProxy */; 383 | }; 384 | CF0F55D020EC6AF70026CA7C /* PBXTargetDependency */ = { 385 | isa = PBXTargetDependency; 386 | target = CF0F55AE20EC6AF60026CA7C /* SkeletonDemo */; 387 | targetProxy = CF0F55CF20EC6AF70026CA7C /* PBXContainerItemProxy */; 388 | }; 389 | /* End PBXTargetDependency section */ 390 | 391 | /* Begin PBXVariantGroup section */ 392 | CF0F55B620EC6AF70026CA7C /* Main.storyboard */ = { 393 | isa = PBXVariantGroup; 394 | children = ( 395 | CF0F55B720EC6AF70026CA7C /* Base */, 396 | ); 397 | name = Main.storyboard; 398 | sourceTree = ""; 399 | }; 400 | CF0F55BB20EC6AF70026CA7C /* LaunchScreen.storyboard */ = { 401 | isa = PBXVariantGroup; 402 | children = ( 403 | CF0F55BC20EC6AF70026CA7C /* Base */, 404 | ); 405 | name = LaunchScreen.storyboard; 406 | sourceTree = ""; 407 | }; 408 | /* End PBXVariantGroup section */ 409 | 410 | /* Begin XCBuildConfiguration section */ 411 | CF0F55D520EC6AF70026CA7C /* Debug */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | ALWAYS_SEARCH_USER_PATHS = NO; 415 | CLANG_ANALYZER_NONNULL = YES; 416 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 417 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 418 | CLANG_CXX_LIBRARY = "libc++"; 419 | CLANG_ENABLE_MODULES = YES; 420 | CLANG_ENABLE_OBJC_ARC = YES; 421 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 422 | CLANG_WARN_BOOL_CONVERSION = YES; 423 | CLANG_WARN_COMMA = YES; 424 | CLANG_WARN_CONSTANT_CONVERSION = YES; 425 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 426 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 427 | CLANG_WARN_EMPTY_BODY = YES; 428 | CLANG_WARN_ENUM_CONVERSION = YES; 429 | CLANG_WARN_INFINITE_RECURSION = YES; 430 | CLANG_WARN_INT_CONVERSION = YES; 431 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 432 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 433 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 434 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 435 | CLANG_WARN_STRICT_PROTOTYPES = YES; 436 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 437 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 438 | CLANG_WARN_UNREACHABLE_CODE = YES; 439 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 440 | CODE_SIGN_IDENTITY = "iPhone Developer"; 441 | COPY_PHASE_STRIP = NO; 442 | DEBUG_INFORMATION_FORMAT = dwarf; 443 | ENABLE_STRICT_OBJC_MSGSEND = YES; 444 | ENABLE_TESTABILITY = YES; 445 | GCC_C_LANGUAGE_STANDARD = gnu11; 446 | GCC_DYNAMIC_NO_PIC = NO; 447 | GCC_NO_COMMON_BLOCKS = YES; 448 | GCC_OPTIMIZATION_LEVEL = 0; 449 | GCC_PREPROCESSOR_DEFINITIONS = ( 450 | "DEBUG=1", 451 | "$(inherited)", 452 | ); 453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 455 | GCC_WARN_UNDECLARED_SELECTOR = YES; 456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 457 | GCC_WARN_UNUSED_FUNCTION = YES; 458 | GCC_WARN_UNUSED_VARIABLE = YES; 459 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 460 | MTL_ENABLE_DEBUG_INFO = YES; 461 | ONLY_ACTIVE_ARCH = YES; 462 | SDKROOT = iphoneos; 463 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 464 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 465 | }; 466 | name = Debug; 467 | }; 468 | CF0F55D620EC6AF70026CA7C /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | CLANG_ANALYZER_NONNULL = YES; 473 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 475 | CLANG_CXX_LIBRARY = "libc++"; 476 | CLANG_ENABLE_MODULES = YES; 477 | CLANG_ENABLE_OBJC_ARC = YES; 478 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 479 | CLANG_WARN_BOOL_CONVERSION = YES; 480 | CLANG_WARN_COMMA = YES; 481 | CLANG_WARN_CONSTANT_CONVERSION = YES; 482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 483 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 484 | CLANG_WARN_EMPTY_BODY = YES; 485 | CLANG_WARN_ENUM_CONVERSION = YES; 486 | CLANG_WARN_INFINITE_RECURSION = YES; 487 | CLANG_WARN_INT_CONVERSION = YES; 488 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 489 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 491 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 492 | CLANG_WARN_STRICT_PROTOTYPES = YES; 493 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 494 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 495 | CLANG_WARN_UNREACHABLE_CODE = YES; 496 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 497 | CODE_SIGN_IDENTITY = "iPhone Developer"; 498 | COPY_PHASE_STRIP = NO; 499 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 500 | ENABLE_NS_ASSERTIONS = NO; 501 | ENABLE_STRICT_OBJC_MSGSEND = YES; 502 | GCC_C_LANGUAGE_STANDARD = gnu11; 503 | GCC_NO_COMMON_BLOCKS = YES; 504 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 505 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 506 | GCC_WARN_UNDECLARED_SELECTOR = YES; 507 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 508 | GCC_WARN_UNUSED_FUNCTION = YES; 509 | GCC_WARN_UNUSED_VARIABLE = YES; 510 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 511 | MTL_ENABLE_DEBUG_INFO = NO; 512 | SDKROOT = iphoneos; 513 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 514 | VALIDATE_PRODUCT = YES; 515 | }; 516 | name = Release; 517 | }; 518 | CF0F55D820EC6AF70026CA7C /* Debug */ = { 519 | isa = XCBuildConfiguration; 520 | baseConfigurationReference = 749E0B27BE20BDCC1E798617 /* Pods-SkeletonDemo.debug.xcconfig */; 521 | buildSettings = { 522 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 523 | CODE_SIGN_STYLE = Automatic; 524 | INFOPLIST_FILE = SkeletonDemo/Info.plist; 525 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 527 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemo; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | SWIFT_VERSION = 4.0; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | }; 532 | name = Debug; 533 | }; 534 | CF0F55D920EC6AF70026CA7C /* Release */ = { 535 | isa = XCBuildConfiguration; 536 | baseConfigurationReference = 96F019AAFE71102AD2E9ACD5 /* Pods-SkeletonDemo.release.xcconfig */; 537 | buildSettings = { 538 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 539 | CODE_SIGN_STYLE = Automatic; 540 | INFOPLIST_FILE = SkeletonDemo/Info.plist; 541 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 542 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 543 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemo; 544 | PRODUCT_NAME = "$(TARGET_NAME)"; 545 | SWIFT_VERSION = 4.0; 546 | TARGETED_DEVICE_FAMILY = "1,2"; 547 | }; 548 | name = Release; 549 | }; 550 | CF0F55DB20EC6AF70026CA7C /* Debug */ = { 551 | isa = XCBuildConfiguration; 552 | buildSettings = { 553 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 554 | BUNDLE_LOADER = "$(TEST_HOST)"; 555 | CODE_SIGN_STYLE = Automatic; 556 | INFOPLIST_FILE = SkeletonDemoTests/Info.plist; 557 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 558 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemoTests; 559 | PRODUCT_NAME = "$(TARGET_NAME)"; 560 | SWIFT_VERSION = 4.0; 561 | TARGETED_DEVICE_FAMILY = "1,2"; 562 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SkeletonDemo.app/SkeletonDemo"; 563 | }; 564 | name = Debug; 565 | }; 566 | CF0F55DC20EC6AF70026CA7C /* Release */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 570 | BUNDLE_LOADER = "$(TEST_HOST)"; 571 | CODE_SIGN_STYLE = Automatic; 572 | INFOPLIST_FILE = SkeletonDemoTests/Info.plist; 573 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 574 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemoTests; 575 | PRODUCT_NAME = "$(TARGET_NAME)"; 576 | SWIFT_VERSION = 4.0; 577 | TARGETED_DEVICE_FAMILY = "1,2"; 578 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SkeletonDemo.app/SkeletonDemo"; 579 | }; 580 | name = Release; 581 | }; 582 | CF0F55DE20EC6AF70026CA7C /* Debug */ = { 583 | isa = XCBuildConfiguration; 584 | buildSettings = { 585 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 586 | CODE_SIGN_STYLE = Automatic; 587 | INFOPLIST_FILE = SkeletonDemoUITests/Info.plist; 588 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 589 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemoUITests; 590 | PRODUCT_NAME = "$(TARGET_NAME)"; 591 | SWIFT_VERSION = 4.0; 592 | TARGETED_DEVICE_FAMILY = "1,2"; 593 | TEST_TARGET_NAME = SkeletonDemo; 594 | }; 595 | name = Debug; 596 | }; 597 | CF0F55DF20EC6AF70026CA7C /* Release */ = { 598 | isa = XCBuildConfiguration; 599 | buildSettings = { 600 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 601 | CODE_SIGN_STYLE = Automatic; 602 | INFOPLIST_FILE = SkeletonDemoUITests/Info.plist; 603 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 604 | PRODUCT_BUNDLE_IDENTIFIER = com.zhiyan.SkeletonDemoUITests; 605 | PRODUCT_NAME = "$(TARGET_NAME)"; 606 | SWIFT_VERSION = 4.0; 607 | TARGETED_DEVICE_FAMILY = "1,2"; 608 | TEST_TARGET_NAME = SkeletonDemo; 609 | }; 610 | name = Release; 611 | }; 612 | /* End XCBuildConfiguration section */ 613 | 614 | /* Begin XCConfigurationList section */ 615 | CF0F55AA20EC6AF60026CA7C /* Build configuration list for PBXProject "SkeletonDemo" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | CF0F55D520EC6AF70026CA7C /* Debug */, 619 | CF0F55D620EC6AF70026CA7C /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | CF0F55D720EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemo" */ = { 625 | isa = XCConfigurationList; 626 | buildConfigurations = ( 627 | CF0F55D820EC6AF70026CA7C /* Debug */, 628 | CF0F55D920EC6AF70026CA7C /* Release */, 629 | ); 630 | defaultConfigurationIsVisible = 0; 631 | defaultConfigurationName = Release; 632 | }; 633 | CF0F55DA20EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemoTests" */ = { 634 | isa = XCConfigurationList; 635 | buildConfigurations = ( 636 | CF0F55DB20EC6AF70026CA7C /* Debug */, 637 | CF0F55DC20EC6AF70026CA7C /* Release */, 638 | ); 639 | defaultConfigurationIsVisible = 0; 640 | defaultConfigurationName = Release; 641 | }; 642 | CF0F55DD20EC6AF70026CA7C /* Build configuration list for PBXNativeTarget "SkeletonDemoUITests" */ = { 643 | isa = XCConfigurationList; 644 | buildConfigurations = ( 645 | CF0F55DE20EC6AF70026CA7C /* Debug */, 646 | CF0F55DF20EC6AF70026CA7C /* Release */, 647 | ); 648 | defaultConfigurationIsVisible = 0; 649 | defaultConfigurationName = Release; 650 | }; 651 | /* End XCConfigurationList section */ 652 | }; 653 | rootObject = CF0F55A720EC6AF60026CA7C /* Project object */; 654 | } 655 | -------------------------------------------------------------------------------- /SkeletonDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SkeletonDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SkeletonDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daomoer/SkeletonDemo/a5987fb574098dfa34fbda2a01cc9bbbdc5fd663/SkeletonDemo/.DS_Store -------------------------------------------------------------------------------- /SkeletonDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SkeletonDemo 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | 19 | let rootVC = ViewController() 20 | let rootNAV = UINavigationController.init(rootViewController: rootVC) 21 | self.window?.rootViewController = rootNAV 22 | self.window?.makeKeyAndVisible() 23 | 24 | 25 | return true 26 | } 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daomoer/SkeletonDemo/a5987fb574098dfa34fbda2a01cc9bbbdc5fd663/SkeletonDemo/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/经典.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "经典@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/经典.imageset/经典@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daomoer/SkeletonDemo/a5987fb574098dfa34fbda2a01cc9bbbdc5fd663/SkeletonDemo/Assets.xcassets/经典.imageset/经典@2x.png -------------------------------------------------------------------------------- /SkeletonDemo/Assets.xcassets/经典@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daomoer/SkeletonDemo/a5987fb574098dfa34fbda2a01cc9bbbdc5fd663/SkeletonDemo/Assets.xcassets/经典@2x.png -------------------------------------------------------------------------------- /SkeletonDemo/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 | -------------------------------------------------------------------------------- /SkeletonDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SkeletonDemo/CustomCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomCell.swift 3 | // SkeletonDemo 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CustomCell: UITableViewCell { 12 | @IBOutlet weak var iconImage: UIImageView! 13 | 14 | @IBOutlet weak var subLabel: UILabel! 15 | @IBOutlet weak var titleLabel: UILabel! 16 | override func awakeFromNib() { 17 | super.awakeFromNib() 18 | // Initialization code 19 | iconImage.layer.masksToBounds = true 20 | iconImage.layer.cornerRadius = self.iconImage.frame.width/2 21 | } 22 | 23 | override func setSelected(_ selected: Bool, animated: Bool) { 24 | super.setSelected(selected, animated: animated) 25 | 26 | // Configure the view for the selected state 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /SkeletonDemo/CustomCell.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 | 46 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SkeletonDemo/HeaderVeiw.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeaderVeiw.swift 3 | // SkeletonDemo 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HeaderVeiw: UIView { 12 | var iconImageView : UIImageView! 13 | var titleLabel : UILabel! 14 | 15 | override init(frame: CGRect) { 16 | super.init(frame: frame) 17 | setUpUI() 18 | } 19 | 20 | required init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | } 23 | 24 | func setUpUI(){ 25 | self.backgroundColor = UIColor.white 26 | iconImageView = UIImageView.init(frame: CGRect(x:UIScreen.main.bounds.width/2-40, y:10, width:80, height:80)) 27 | iconImageView.isSkeletonable = true 28 | self.addSubview(iconImageView) 29 | 30 | titleLabel = UILabel.init(frame: CGRect(x:15, y: 100, width:UIScreen.main.bounds.width-30, height:100)) 31 | titleLabel.numberOfLines = 4 32 | titleLabel.isSkeletonable = true 33 | self.addSubview(titleLabel) 34 | 35 | } 36 | 37 | // 给cell赋值,项目中一般使用model,我这里直接写死了 38 | func setValueForHeader(){ 39 | iconImageView.image = UIImage(named:"经典") 40 | titleLabel.text = "悲时俗之迫阨兮,愿轻举而远游。质菲薄而无因兮,焉讬乘而上浮?遭沈浊而污秽兮,独郁结其谁语!夜耿耿而不寐兮,魂营营而至曙。惟天地之无穷兮,哀人生之长勤。往者余弗及兮,来者吾不闻。" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SkeletonDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SkeletonDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SkeletonDemo 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SkeletonView 11 | 12 | class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SkeletonTableViewDelegate, SkeletonTableViewDataSource{ 13 | 14 | let identifier = "CustomCell" 15 | var headerView : HeaderVeiw? 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | self.view.backgroundColor = UIColor.white 20 | self.navigationItem.title = "Skeleton Screen加载占位图" 21 | 22 | let tableView = UITableView.init(frame: CGRect(x:0, y:0, width:UIScreen.main.bounds.width, height:UIScreen.main.bounds.height)) 23 | tableView.delegate = self 24 | tableView.dataSource = self 25 | view.addSubview(tableView) 26 | tableView.estimatedRowHeight = 80 27 | 28 | self.headerView = HeaderVeiw.init(frame: CGRect(x:0, y:0, width:UIScreen.main.bounds.width, height:220)) 29 | tableView.tableHeaderView = self.headerView 30 | 31 | //注册nib 32 | tableView.register(UINib.init(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: identifier) 33 | 34 | tableView.isSkeletonable = true 35 | 36 | 37 | DispatchQueue.main.asyncAfter(deadline: .now() + 4) { 38 | self.view.hideSkeleton() 39 | self.headerView?.hideSkeleton() 40 | } 41 | } 42 | 43 | override func viewDidAppear(_ animated: Bool) { 44 | super.viewDidAppear(animated) 45 | self.view.showAnimatedSkeleton() 46 | self.headerView?.showAnimatedGradientSkeleton() 47 | } 48 | 49 | 50 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 51 | return 5 52 | } 53 | 54 | func collectionSkeletonView(_ skeletonView: UITableView, cellIdenfierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier { 55 | return "CustomCell" 56 | } 57 | 58 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 59 | let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as! CustomCell 60 | headerView?.setValueForHeader() 61 | cell.iconImage.image = UIImage(named:"经典") 62 | cell.titleLabel.text = "大大大标题" 63 | cell.subLabel.text = "下峥嵘而无地兮,上寥廓而无天。视倏忽而无见兮,听惝恍而无闻。超无为以至清兮,与泰初而为邻。" 64 | 65 | return cell 66 | } 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /SkeletonDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SkeletonDemoTests/SkeletonDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonDemoTests.swift 3 | // SkeletonDemoTests 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SkeletonDemo 11 | 12 | class SkeletonDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /SkeletonDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SkeletonDemoUITests/SkeletonDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonDemoUITests.swift 3 | // SkeletonDemoUITests 4 | // 5 | // Created by Domo on 2018/7/4. 6 | // Copyright © 2018年 知言网络. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SkeletonDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------