-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
124 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc |
8 changes: 8 additions & 0 deletions
8
...ToRefreshControl/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// swift-tools-version: 5.9 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "PullToRefreshControl", | ||
products: [ | ||
// Products define the executables and libraries a package produces, making them visible to other packages. | ||
.library( | ||
name: "PullToRefreshControl", | ||
targets: ["PullToRefreshControl"]), | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package, defining a module or a test suite. | ||
// Targets can depend on other targets in this package and products from dependencies. | ||
.target( | ||
name: "PullToRefreshControl"), | ||
.testTarget( | ||
name: "PullToRefreshControlTests", | ||
dependencies: ["PullToRefreshControl"]), | ||
] | ||
) |
60 changes: 60 additions & 0 deletions
60
PullToRefreshControl/Sources/PullToRefreshControl/PullToRefreshControl.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// PullToRefreshControl.swift | ||
// PullToRefreshControl | ||
// | ||
// Created by Blazej SLEBODA on 14/01/2024. | ||
// | ||
|
||
import UIKit | ||
|
||
public class PullToRefreshControl: UIRefreshControl { | ||
public override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
commonInit() | ||
} | ||
public required init?(coder: NSCoder) { | ||
super.init(coder: coder) | ||
commonInit() | ||
} | ||
private func commonInit() { | ||
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] _ in | ||
self?.cancelOrRestartRefreshingIfNeeded() | ||
} | ||
} | ||
public func pullToRefresh() { | ||
guard let superview = superview as? UITableView else { | ||
return | ||
} | ||
superview.contentOffset = .init(x: superview.contentOffset.x, y: -frame.height) | ||
beginRefreshing() | ||
sendActions(for: .valueChanged) | ||
} | ||
public func cancelOrRestartRefreshingIfNeeded() { | ||
cancelIncompletePullToRefreshIfNeeded() | ||
restartBeginRefreshingIfNeeded() | ||
} | ||
private func restartBeginRefreshingIfNeeded() { | ||
guard | ||
isRefreshing, | ||
let superview = superview as? UITableView | ||
else { return } | ||
let oldValueContentOffset = superview.contentOffset | ||
UIView.performWithoutAnimation { | ||
endRefreshing() | ||
} | ||
DispatchQueue.main.async { | ||
superview.contentOffset = oldValueContentOffset | ||
self.beginRefreshing() | ||
} | ||
} | ||
private func cancelIncompletePullToRefreshIfNeeded() { | ||
guard | ||
!isRefreshing, | ||
let superview = superview as? UITableView, | ||
superview.contentOffset != .zero | ||
else { return } | ||
UIView.performWithoutAnimation { [weak self] in | ||
self?.endRefreshing() | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
PullToRefreshControl/Tests/PullToRefreshControlTests/PullToRefreshControlTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import XCTest | ||
@testable import PullToRefreshControl | ||
|
||
final class PullToRefreshControlTests: XCTestCase { | ||
func testExample() throws { | ||
// XCTest Documentation | ||
// https://developer.apple.com/documentation/xctest | ||
|
||
// Defining Test Cases and Test Methods | ||
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,14 @@ | ||
# PullToRefreshControl | ||
UIRefreshControl with programatic pull to refresh and fixed paused animations and inclomplete pull to refresh | ||
|
||
"PullToRefreshControl" is a custom subclass of UIRefreshControl, designed to enhance the functionality of the standard pull-to-refresh action in iOS applications. This control is specifically tailored for use with UITableView, offering a programmable approach to initiate the refresh action and addressing a common issue where the refresh animation pauses or fails to resume correctly. | ||
|
||
Key Features | ||
|
||
1. Programmatic Refresh Triggering: | ||
The control introduces a method, pullToRefresh(), allowing developers to initiate the pull-to-refresh action programmatically. This is particularly useful for scenarios where the refresh needs to be triggered without user interaction, such as during the initial loading of the table view. | ||
2. Handling App State Transitions: | ||
It automatically manages the refresh control's state during various app state transitions. This includes scenarios where the app returns from the background, or when the user navigates back to the view controller containing the UITableView. | ||
3. Seamless Animation Continuity: | ||
The cancelOrRestartRefreshingIfNeeded() method ensures that the refresh animation continues seamlessly. It addresses the common issue where the animation gets paused or stuck, especially after the app transitions from the background or when returning from another view controller. | ||
4. Improved User Experience: | ||
By fixing the interrupted animation issue, this control provides a smoother and more consistent user experience. It maintains the visual feedback that users expect when they initiate a refresh action. |