Compare commits

..

7 Commits

Author SHA1 Message Date
Juanpe Catalán e8d5eb61d8 update README file 2021-06-10 19:19:29 +02:00
Juanpe Catalán c2a029ed51 create disableWhenSkeletonIsActive property 2021-06-10 19:14:05 +02:00
Sam Harrison a1c8276980 Make CI action build targets, not just clean (#403) 2021-06-10 19:01:01 +02:00
Sam Harrison e9ac3a5ab3 Fix TableViewCell skeleton not being removed & automaticNumberOfRows reference (#402)
* Change TableView subviewsToSkeleton to all subviews

* Fix reference to automaticNumberOfRows from pr #401
2021-06-10 18:59:21 +02:00
Richard L Zarth III fb83a62f7b Add SkeletonCollectionDataSource.automaticNumberOfRows Constant (#401)
* Add automaticNumberOfRows constant to SkeletonCollectionDataSource.

* Update tableView(_:numberOfRowsInSection:) and collectionView(_:numberOfItemsInSection:) to use the new automaticNumberOfRows constant.

* Update README.

* Update README.md

Add an **IMPORTANT!** header to the automaticNumberOfRows mention in the README.

Co-authored-by: Juanpe Catalán <juanpecm@gmail.com>

Co-authored-by: Juanpe Catalán <juanpecm@gmail.com>
2021-06-09 18:45:44 +02:00
Juanpe Catalán 12521c1d87 update Info.plist 2021-05-31 17:20:11 +02:00
Juanpe c266035888 Bump version 1.16.0 2021-05-31 15:09:22 +00:00
13 changed files with 107 additions and 23 deletions
+1 -1
View File
@@ -16,4 +16,4 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build
run: xcodebuild clean -target '${{ matrix.build-config['target'] }}' -sdk '${{ matrix.build-config['sdk'] }}' -destination '${{ matrix.build-config['destination'] }}'
run: xcodebuild clean build -target '${{ matrix.build-config['target'] }}' -sdk '${{ matrix.build-config['sdk'] }}' -destination '${{ matrix.build-config['destination'] }}'
+13
View File
@@ -189,6 +189,10 @@ func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection s
// It calculates how many cells need to populate whole tableview
```
> 📣 **IMPORTANT!**
>
> If you return `SkeletonCollectionDataSource.automaticNumberOfRows` in the above method, it acts like the default behavior (i.e. it calculates how many cells needed to populate the whole tableview).
There is only one method you need to implement to let Skeleton know the cell identifier. This method doesn't have default implementation:
``` swift
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier
@@ -491,6 +495,15 @@ Sometimes you wanna hide some view when the animation starts, so there is a quic
view.isHiddenWhenSkeletonIsActive = true // This works only when isSkeletonable = true
```
**Don't modify user interaction when the skeleton is active**
By default, user interaction is disabled for skeletonized items, but if you don't want to modify the user interaction indicator when skeleton is active, you can use the `isDisableWhenSkeletonIsActive` property:
```swift
view.isDisableWhenSkeletonIsActive = false // The view will be active when the skeleton will be active.
```
**Debug**
To facilitate the debug tasks when something is not working fine. **`SkeletonView`** has some new tools.
+1 -1
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "SkeletonView"
s.version = "1.15.0"
s.version = "1.16.0"
s.summary = "An elegant way to show users that something is happening and also prepare them to which contents he is waiting"
s.description = <<-DESC
Today almost all apps have async processes, as API requests, long runing processes, etc. And while the processes are working, usually developers place a loading view to show users that something is going on.
+11 -2
View File
@@ -619,6 +619,7 @@
52D6D97B1BEFF229002C0205 = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 1000;
ProvisioningStyle = Automatic;
};
F5F899F11FABA607002E8FDA = {
CreatedOnToolsVersion = 9.1;
@@ -1117,8 +1118,10 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = NO;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1131,6 +1134,8 @@
ONLY_ACTIVE_ARCH = NO;
PRODUCT_BUNDLE_IDENTIFIER = "com.SkeletonView.SkeletonView-iOS";
PRODUCT_NAME = SkeletonView;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -1142,8 +1147,10 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = NO;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1155,6 +1162,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.SkeletonView.SkeletonView-iOS";
PRODUCT_NAME = SkeletonView;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
@@ -31,12 +31,16 @@ extension CollectionSkeleton where Self: UIScrollView {
func removeDummyDataSource(reloadAfter: Bool) {}
func disableUserInteraction() {
isUserInteractionEnabled = false
isScrollEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
isScrollEnabled = false
}
}
func enableUserInteraction() {
isUserInteractionEnabled = true
isScrollEnabled = true
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = true
isScrollEnabled = true
}
}
}
@@ -17,7 +17,7 @@ public protocol SkeletonCollectionViewDataSource: UICollectionViewDataSource {
public extension SkeletonCollectionViewDataSource {
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return skeletonView.estimatedNumberOfRows
return SkeletonCollectionDataSource.automaticNumberOfRows
}
func collectionSkeletonView(_ skeletonView: UICollectionView,
@@ -11,6 +11,8 @@ import UIKit
public typealias ReusableCellIdentifier = String
class SkeletonCollectionDataSource: NSObject {
static let automaticNumberOfRows = -1
weak var originalTableViewDataSource: SkeletonTableViewDataSource?
weak var originalCollectionViewDataSource: SkeletonCollectionViewDataSource?
var rowHeight: CGFloat = 0.0
@@ -32,7 +34,17 @@ extension SkeletonCollectionDataSource: UITableViewDataSource {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
originalTableViewDataSource?.collectionSkeletonView(tableView, numberOfRowsInSection: section) ?? 0
guard let originalTableViewDataSource = originalTableViewDataSource else {
return 0
}
let numberOfRows = originalTableViewDataSource.collectionSkeletonView(tableView, numberOfRowsInSection: section)
if numberOfRows == Self.automaticNumberOfRows {
return tableView.estimatedNumberOfRows
} else {
return numberOfRows
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
@@ -50,7 +62,17 @@ extension SkeletonCollectionDataSource: UICollectionViewDataSource {
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
originalCollectionViewDataSource?.collectionSkeletonView(collectionView, numberOfItemsInSection: section) ?? 0
guard let originalCollectionViewDataSource = originalCollectionViewDataSource else {
return 0
}
let numberOfItems = originalCollectionViewDataSource.collectionSkeletonView(collectionView, numberOfItemsInSection: section)
if numberOfItems == Self.automaticNumberOfRows {
return collectionView.estimatedNumberOfRows
} else {
return numberOfItems
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
@@ -16,7 +16,7 @@ public protocol SkeletonTableViewDataSource: UITableViewDataSource {
public extension SkeletonTableViewDataSource {
func collectionSkeletonView(_ skeletonView: UITableView, numberOfRowsInSection section: Int) -> Int {
return skeletonView.estimatedNumberOfRows
return SkeletonCollectionDataSource.automaticNumberOfRows
}
func numSections(in collectionSkeletonView: UITableView) -> Int { return 1 }
@@ -16,6 +16,7 @@ enum ViewAssociatedKeys {
static var buttonViewState = "buttonViewState"
static var currentSkeletonConfig = "currentSkeletonConfig"
static var skeletonCornerRadius = "skeletonCornerRadius"
static var disableWhenSkeletonIsActive = "disableWhenSkeletonIsActive"
}
// codebeat:enable[TOO_MANY_IVARS]
@@ -14,6 +14,12 @@ public extension UIView {
get { return hiddenWhenSkeletonIsActive }
set { hiddenWhenSkeletonIsActive = newValue }
}
@IBInspectable
var isDisableWhenSkeletonIsActive: Bool {
get { return disableWhenSkeletonIsActive }
set { disableWhenSkeletonIsActive = newValue }
}
@IBInspectable
var skeletonCornerRadius: Float {
@@ -34,6 +40,11 @@ public extension UIView {
get { return ao_get(pkey: &ViewAssociatedKeys.hiddenWhenSkeletonIsActive) as? Bool ?? false }
set { ao_set(newValue, pkey: &ViewAssociatedKeys.hiddenWhenSkeletonIsActive) }
}
private var disableWhenSkeletonIsActive: Bool {
get { return ao_get(pkey: &ViewAssociatedKeys.disableWhenSkeletonIsActive) as? Bool ?? true }
set { ao_set(newValue, pkey: &ViewAssociatedKeys.disableWhenSkeletonIsActive) }
}
private var skeletonableCornerRadius: Float {
get { return ao_get(pkey: &ViewAssociatedKeys.skeletonCornerRadius) as? Float ?? 0.0 }
@@ -10,7 +10,10 @@ import UIKit
extension UIView {
@objc func prepareViewForSkeleton() {
isUserInteractionEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
}
startTransition { [weak self] in
self?.backgroundColor = .clear
}
@@ -55,7 +58,11 @@ extension UILabel {
override func prepareViewForSkeleton() {
backgroundColor = .clear
isUserInteractionEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
}
resignFirstResponder()
startTransition { [weak self] in
self?.updateHeightConstraintsIfNeeded()
@@ -67,7 +74,11 @@ extension UILabel {
extension UITextView {
override func prepareViewForSkeleton() {
backgroundColor = .clear
isUserInteractionEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
}
resignFirstResponder()
startTransition { [weak self] in
self?.textColor = .clear
@@ -90,7 +101,11 @@ extension UITextField {
extension UIImageView {
override func prepareViewForSkeleton() {
backgroundColor = .clear
isUserInteractionEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
}
startTransition { [weak self] in
self?.image = nil
}
@@ -100,7 +115,11 @@ extension UIImageView {
extension UIButton {
override func prepareViewForSkeleton() {
backgroundColor = .clear
isUserInteractionEnabled = false
if isDisableWhenSkeletonIsActive {
isUserInteractionEnabled = false
}
startTransition { [weak self] in
self?.setTitle(nil, for: .normal)
}
+10 -5
View File
@@ -27,12 +27,17 @@ extension UIView: Recoverable {
guard let storedViewState = viewState else { return }
startTransition { [weak self] in
self?.layer.cornerRadius = storedViewState.cornerRadius
self?.layer.masksToBounds = storedViewState.clipToBounds
self?.isUserInteractionEnabled = storedViewState.isUserInteractionsEnabled
guard let self = self else { return }
if self?.backgroundColor == .clear || forced {
self?.backgroundColor = storedViewState.backgroundColor
self.layer.cornerRadius = storedViewState.cornerRadius
self.layer.masksToBounds = storedViewState.clipToBounds
if self.isDisableWhenSkeletonIsActive {
self.isUserInteractionEnabled = storedViewState.isUserInteractionsEnabled
}
if self.backgroundColor == .clear || forced {
self.backgroundColor = storedViewState.backgroundColor
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ extension UITableView {
// Some developer trying to call `view.showAnimatedSkeleton()`
// when the request or data is loading which sometimes happens before the ViewDidAppear
guard window != nil else { return [] }
return visibleCells + visibleSectionHeaders + visibleSectionFooters
return subviews
}
}