Revert "Drop iOS 14 and macOS 11 support"

This reverts commit dcef7f47ff.
This commit is contained in:
Arkadiusz Fal
2023-10-15 13:35:23 +02:00
parent 053b4a22b8
commit 94915b0496
45 changed files with 695 additions and 88 deletions

View File

@@ -0,0 +1,18 @@
//
// FramePreferenceKey.swift
// SwiftUI_Pull_to_Refresh
//
// Created by Geri Borbás on 21/09/2021.
//
import Foundation
import SwiftUI
struct FramePreferenceKey: PreferenceKey {
typealias Value = CGRect
static var defaultValue = CGRect.zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}

View File

@@ -0,0 +1,106 @@
//
// ScrollViewMatcher.swift
// SwiftUI_Pull_to_Refresh
//
// Created by Geri Borbás on 17/09/2021.
//
import Foundation
import SwiftUI
final class ScrollViewMatcher: UIViewControllerRepresentable {
let onMatch: (UIScrollView) -> Void
@Binding var geometryReaderFrame: CGRect
init(onResolve: @escaping (UIScrollView) -> Void, geometryReaderFrame: Binding<CGRect>) {
onMatch = onResolve
_geometryReaderFrame = geometryReaderFrame
}
func makeUIViewController(context _: Context) -> ScrollViewMatcherViewController {
ScrollViewMatcherViewController(onResolve: onMatch, geometryReaderFrame: geometryReaderFrame)
}
func updateUIViewController(_ viewController: ScrollViewMatcherViewController, context _: Context) {
viewController.geometryReaderFrame = geometryReaderFrame
}
}
final class ScrollViewMatcherViewController: UIViewController {
let onMatch: (UIScrollView) -> Void
private var scrollView: UIScrollView? {
didSet {
if oldValue != scrollView,
let scrollView
{
onMatch(scrollView)
}
}
}
var geometryReaderFrame: CGRect {
didSet {
match()
}
}
init(onResolve: @escaping (UIScrollView) -> Void, geometryReaderFrame: CGRect, debug _: Bool = false) {
onMatch = onResolve
self.geometryReaderFrame = geometryReaderFrame
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("Use init(onMatch:) to instantiate ScrollViewMatcherViewController.")
}
func match() {
// matchUsingHierarchy()
matchUsingGeometry()
}
func matchUsingHierarchy() {
if parent != nil {
// Lookup view ancestry for any `UIScrollView`.
view.searchViewAnchestorsFor { (scrollView: UIScrollView) in
self.scrollView = scrollView
}
}
}
func matchUsingGeometry() {
if let parent {
if let scrollViewsInHierarchy: [UIScrollView] = parent.view.viewsInHierarchy() {
// Return first match if only a single scroll view is found in the hierarchy.
if scrollViewsInHierarchy.count == 1,
let firstScrollViewInHierarchy = scrollViewsInHierarchy.first
{
scrollView = firstScrollViewInHierarchy
// Filter by frame origins if multiple matches found.
} else {
if let firstMatchingFrameOrigin = scrollViewsInHierarchy.filter({
$0.globalFrame.origin.close(to: geometryReaderFrame.origin)
}).first {
scrollView = firstMatchingFrameOrigin
}
}
}
}
}
override func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
match()
}
}
extension CGPoint {
/// Returns `true` if this point is close the other point (considering a ~1 pt tolerance).
func close(to point: CGPoint) -> Bool {
let inset = Double(1)
let rect = CGRect(x: x - inset, y: y - inset, width: inset * 2, height: inset * 2)
return rect.contains(point)
}
}