diff --git a/CHANGELOG.md b/CHANGELOG.md index 2817a2ab..69c56b9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +### 0.10.2 +- **Add**: `RefreshControl` - a basic UIRefreshControl with fixed refresh action. + ### 0.10.1 - **Update**: Third party dependencies: `Alamofire` 5.2.2, `RxAlamofire` 5.6.1 @@ -18,7 +21,6 @@ #### TIFoundationUtils - **Add**: `CodableKeyValueStorage` - storage that can get and set codable objects by the key. - ### 0.9.43 - **Fix**: `OTPSwiftView`'s dependencies. diff --git a/LeadKit.podspec b/LeadKit.podspec index 01c7132b..f2c5d9de 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKit" - s.version = "0.10.1" + s.version = "0.10.2" s.summary = "iOS framework with a bunch of tools for rapid development" s.homepage = "https://github.com/TouchInstinct/LeadKit" s.license = "Apache License, Version 2.0" diff --git a/TIUIElements/README.md b/TIUIElements/README.md index 50d4e5af..68d1da24 100644 --- a/TIUIElements/README.md +++ b/TIUIElements/README.md @@ -1,6 +1,8 @@ # TIUIElements -Bunch of useful protocols and views. +Bunch of useful protocols and views: + +- `RefreshControl` - a basic UIRefreshControl with fixed refresh action. # Installation via SPM diff --git a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift new file mode 100644 index 00000000..a78796fb --- /dev/null +++ b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift @@ -0,0 +1,52 @@ +import UIKit + +open class RefreshControl: UIRefreshControl { + private var action: Selector? + private var target: NSObjectProtocol? + + // Handle .valueChanged event of refresh control + public override func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event) { + guard case .valueChanged = controlEvents else { + return super.addTarget(target, action: action, for: controlEvents) + } + + self.action = action + self.target = target as? NSObjectProtocol + } + + public override func removeTarget(_ target: Any?, action: Selector?, for controlEvents: UIControl.Event) { + guard self.action == action, self.target?.isEqual(target) ?? false else { + super.removeTarget(target, action: action, for: controlEvents) + return + } + + self.action = nil + self.target = nil + } + + public override func sendActions(for controlEvents: UIControl.Event) { + guard case .valueChanged = controlEvents else { + return super.sendActions(for: controlEvents) + } + + // Perform target's action + if action != nil, target != nil { + performRefreshAction() + } + } + + open override func endRefreshing() { + // Due to Apple's recommends + CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { + super.endRefreshing() + } + } + + private func performRefreshAction() { + // It is implemented the combined behavior of `touchUpInside` and `touchUpOutside` using `CFRunLoopPerformBlock`, + // which `UIRefreshControl` does not support + CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { + self.target?.perform(self.action) + } + } +}