From af43eb9da7df7ba5fbb9c9e16dd57e7db9ad2099 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 26 Aug 2020 23:40:46 +0300 Subject: [PATCH 1/7] Add Refresh Control --- TIUIElements/README.md | 4 +- .../Views/RefreshControl/RefreshControl.swift | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift diff --git a/TIUIElements/README.md b/TIUIElements/README.md index 50d4e5af..a24f58bf 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..452fd057 --- /dev/null +++ b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift @@ -0,0 +1,45 @@ +import UIKit + +open class RefreshControl: UIRefreshControl { + private var action: Selector? + private var target: NSObjectProtocol? + + 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) + } + + if action != nil, target != nil { + performRefreshAction() + } + } + + private func performRefreshAction() { + CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { [weak self] in + guard let action = self?.action else { + return + } + + self?.target?.perform(action) + } + } +} From b2b386185cd72ac85aabc0d1609fdd1930988523 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 26 Aug 2020 23:41:44 +0300 Subject: [PATCH 2/7] Up version --- CHANGELOG.md | 3 +++ LeadKit.podspec | 2 +- TIUIElements/README.md | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4d10132..5ef952f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +### 0.9.43 +- **Add**: `RefreshControl` - a basic UIRefreshControl with fixed refresh action. + ### 0.9.42 - **Fix**: Logic bugs of `PaginationWrapper`. diff --git a/LeadKit.podspec b/LeadKit.podspec index 74dd2806..f0e3e393 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKit" - s.version = "0.9.42" + s.version = "0.9.43" 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 a24f58bf..68d1da24 100644 --- a/TIUIElements/README.md +++ b/TIUIElements/README.md @@ -2,7 +2,7 @@ Bunch of useful protocols and views: -- RefreshControl - a basic UIRefreshControl with fixed refresh action. +- `RefreshControl` - a basic UIRefreshControl with fixed refresh action. # Installation via SPM From d29903d51bc90abca164a50e478d58c9fd7ed0bf Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 26 Aug 2020 23:51:46 +0300 Subject: [PATCH 3/7] Code correction --- .../Sources/Views/RefreshControl/RefreshControl.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift index 452fd057..64c4baab 100644 --- a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift +++ b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift @@ -32,7 +32,13 @@ open class RefreshControl: UIRefreshControl { performRefreshAction() } } - + + open override func endRefreshing() { + CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { + super.endRefreshing() + } + } + private func performRefreshAction() { CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { [weak self] in guard let action = self?.action else { From 86581223ea96b944a077afa07feec20a85c48f95 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Aug 2020 23:09:34 +0300 Subject: [PATCH 4/7] Add comments --- .../Sources/Views/RefreshControl/RefreshControl.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift index 64c4baab..129b84d4 100644 --- a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift +++ b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift @@ -4,6 +4,7 @@ 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) @@ -28,18 +29,22 @@ open class RefreshControl: UIRefreshControl { 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) { [weak self] in guard let action = self?.action else { return From 942ad1fb5712155ec97add075401f51cba59289e Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Aug 2020 23:11:15 +0300 Subject: [PATCH 5/7] Fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed3f87a6..31429196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ### 0.9.45 -- **Add**: `RefreshControl` - a basic UIRefreshControl with fixed refresh action. +- **Add**: `RefreshControl` - a basic UIRefreshControl with fixed refresh action. ### 0.9.44 - **Add**: `TIFoundationUtils` - set of helpers for Foundation framework classes. From a3d01311977ca0988e1bb8daacd7c21911f9bec1 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Aug 2020 23:11:38 +0300 Subject: [PATCH 6/7] Fix git --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31429196..13694890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,8 @@ #### TIFoundationUtils - **Add**: `CodableKeyValueStorage` - storage that can get and set codable objects by the key. - ### 0.9.43 - **Fix**: `OTPSwiftView`'s dependencies. ->>>>>>> master ### 0.9.42 - **Fix**: Logic bugs of `PaginationWrapper`. From 7f05a98894fa1f4f9e869ee37789843c516d1f00 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Sep 2020 10:19:47 +0300 Subject: [PATCH 7/7] Fix self capture --- .../Sources/Views/RefreshControl/RefreshControl.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift index 129b84d4..a78796fb 100644 --- a/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift +++ b/TIUIElements/Sources/Views/RefreshControl/RefreshControl.swift @@ -45,12 +45,8 @@ open class RefreshControl: UIRefreshControl { 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) { [weak self] in - guard let action = self?.action else { - return - } - - self?.target?.perform(action) + CFRunLoopPerformBlock(CFRunLoopGetMain(), CFRunLoopMode.defaultMode.rawValue) { + self.target?.perform(self.action) } } }