Skip to content

Commit

Permalink
Initial project
Browse files Browse the repository at this point in the history
  • Loading branch information
Adobels committed Jan 14, 2024
1 parent 3bc99e4 commit 6a16d11
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
8 changes: 8 additions & 0 deletions PullToRefreshControl/.gitignore
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
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>
23 changes: 23 additions & 0 deletions PullToRefreshControl/Package.swift
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"]),
]
)
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()
}
}
}
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
}
}
14 changes: 13 additions & 1 deletion README.md
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.

0 comments on commit 6a16d11

Please sign in to comment.