From c1ad696937bb3d9c1f46bd460075fd409ec88d33 Mon Sep 17 00:00:00 2001 From: Yusuke Morishita Date: Tue, 7 Jul 2026 07:17:06 -0700 Subject: [PATCH 1/2] Tidy overlong lines and minor naming ahead of adopting a formatter No behavior change. - Wrap the 160+ character lines (the worst was 301 characters) in TabView, SwipeMenuView, and SwipeMenuViewController. - Rename single-letter locals (i -> index, m -> maskedCorners). - Drop redundant '= nil' optional initializations in the options. - Remove the stale 2017 'case infinity' TODO; nothing tracks it. - Trailing whitespace/newline fixes. --- .../SwipeMenuView.swift | 6 ++- .../SwipeMenuViewController.swift | 5 +- .../SwipeMenuViewOptions.swift | 5 +- Sources/SwipeMenuViewController/TabView.swift | 46 +++++++++++++------ 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/Sources/SwipeMenuViewController/SwipeMenuView.swift b/Sources/SwipeMenuViewController/SwipeMenuView.swift index e0d0847..0f7d305 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuView.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuView.swift @@ -299,7 +299,11 @@ open class SwipeMenuView: UIView { tabView = TabView(frame: CGRect(x: 0, y: 0, width: frame.width, height: options.tabView.height), options: options.tabView) tabView?.clipsToBounds = options.tabView.clipsToBounds - contentScrollView = ContentScrollView(frame: CGRect(x: 0, y: options.tabView.height, width: frame.width, height: frame.height - options.tabView.height), default: defaultIndex, options: options.contentScrollView) + let contentFrame = CGRect(x: 0, + y: options.tabView.height, + width: frame.width, + height: frame.height - options.tabView.height) + contentScrollView = ContentScrollView(frame: contentFrame, default: defaultIndex, options: options.contentScrollView) contentScrollView?.clipsToBounds = options.contentScrollView.clipsToBounds tabView?.update(defaultIndex) diff --git a/Sources/SwipeMenuViewController/SwipeMenuViewController.swift b/Sources/SwipeMenuViewController/SwipeMenuViewController.swift index de42f1f..498972b 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuViewController.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuViewController.swift @@ -87,7 +87,10 @@ open class SwipeMenuViewController: UIViewController, SwipeMenuViewDelegate, Swi /// than crashing. Override to provide pages that are not backed by `children`. open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController { guard children.indices.contains(index) else { - assertionFailure("SwipeMenuViewController: requested a page at \(index) but only \(children.count) child view controllers exist. Override the data source to provide the missing pages.") + assertionFailure(""" + SwipeMenuViewController: requested a page at \(index) but only \(children.count) \ + child view controllers exist. Override the data source to provide the missing pages. + """) // Return a detached placeholder rather than crashing. It is // intentionally not added via `addChild(_:)`: the default // `numberOfPages(in:)` counts `children`, so adding children on this diff --git a/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift b/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift index 8d73a68..9bbb4b8 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift @@ -8,7 +8,6 @@ public nonisolated struct SwipeMenuViewOptions: Sendable { public nonisolated enum Style: Sendable { case flexible case segmented - // TODO: case infinity } public nonisolated enum Indicator: Sendable { @@ -65,11 +64,11 @@ public nonisolated struct SwipeMenuViewOptions: Sendable { public nonisolated struct Circle: Sendable { /// The corner radius of the highlight when the indicator is `.circle`. /// Defaults to `nil`, which uses half the highlight's height (a capsule). - public var cornerRadius: CGFloat? = nil + public var cornerRadius: CGFloat? /// The corners rounded by `cornerRadius` when the indicator is `.circle`. /// Defaults to `nil`, which rounds all four corners. - public var maskedCorners: CACornerMask? = nil + public var maskedCorners: CACornerMask? } /// The padding around the indicator view. Defaults to `.zero`. diff --git a/Sources/SwipeMenuViewController/TabView.swift b/Sources/SwipeMenuViewController/TabView.swift index 2b0295f..98e83b6 100644 --- a/Sources/SwipeMenuViewController/TabView.swift +++ b/Sources/SwipeMenuViewController/TabView.swift @@ -299,11 +299,12 @@ open class TabView: UIScrollView { containerView.frame.size.width = containerWidth containerView.translatesAutoresizingMaskIntoConstraints = false - + let heightConstraint: NSLayoutConstraint switch options.indicator { case .underline: - heightConstraint = containerView.heightAnchor.constraint(equalToConstant: options.height - options.indicatorView.underline.height - options.indicatorView.padding.bottom) + let height = options.height - options.indicatorView.underline.height - options.indicatorView.padding.bottom + heightConstraint = containerView.heightAnchor.constraint(equalToConstant: height) case .circle, .none: heightConstraint = containerView.heightAnchor.constraint(equalToConstant: options.height) } @@ -334,8 +335,8 @@ open class TabView: UIScrollView { } private func updateSelectedItem(by newIndex: Int) { - for (i, itemView) in itemViews.enumerated() { - itemView.isSelected = i == newIndex + for (index, itemView) in itemViews.enumerated() { + itemView.isSelected = index == newIndex } } } @@ -358,20 +359,27 @@ extension TabView { switch options.indicator { case .underline: let itemView = itemViews[currentIndex] - indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + options.indicatorView.padding.left, y: itemView.frame.height - options.indicatorView.padding.vertical, width: itemView.frame.width - options.indicatorView.padding.horizontal, height: options.indicatorView.underline.height)) + let padding = options.indicatorView.padding + indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + padding.left, + y: itemView.frame.height - padding.vertical, + width: itemView.frame.width - padding.horizontal, + height: options.indicatorView.underline.height)) indicatorView.layer.cornerRadius = options.indicatorView.underline.cornerRadius indicatorView.backgroundColor = options.indicatorView.backgroundColor containerView.addSubview(indicatorView) case .circle: let itemView = itemViews[currentIndex] - let height = itemView.bounds.height - options.indicatorView.padding.vertical - indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + options.indicatorView.padding.left, y: 0, width: itemView.frame.width - options.indicatorView.padding.horizontal, height: height)) + let padding = options.indicatorView.padding + indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + padding.left, + y: 0, + width: itemView.frame.width - padding.horizontal, + height: itemView.bounds.height - padding.vertical)) indicatorView.layer.position.y = itemView.layer.position.y indicatorView.layer.cornerRadius = options.indicatorView.circle.cornerRadius ?? indicatorView.frame.height / 2 indicatorView.backgroundColor = options.indicatorView.backgroundColor - - if let m = options.indicatorView.circle.maskedCorners { - indicatorView.layer.maskedCorners = m + + if let maskedCorners = options.indicatorView.circle.maskedCorners { + indicatorView.layer.maskedCorners = maskedCorners } containerView.addSubview(indicatorView) @@ -432,11 +440,16 @@ extension TabView { guard let currentItem else { return } if options.indicatorView.isAnimationOnSwipeEnabled { + let padding = options.indicatorView.padding switch direction { case .forward: if let nextItem { - indicatorView.frame.origin.x = currentItem.frame.origin.x + (nextItem.frame.origin.x - currentItem.frame.origin.x) * ratio + options.indicatorView.padding.left - indicatorView.frame.size.width = currentItem.frame.size.width + (nextItem.frame.size.width - currentItem.frame.size.width) * ratio - options.indicatorView.padding.horizontal + indicatorView.frame.origin.x = currentItem.frame.origin.x + + (nextItem.frame.origin.x - currentItem.frame.origin.x) * ratio + + padding.left + indicatorView.frame.size.width = currentItem.frame.size.width + + (nextItem.frame.size.width - currentItem.frame.size.width) * ratio + - padding.horizontal if options.interpolatesTextColorOnSwipe { nextItem.titleLabel.textColor = options.itemView.textColor.convert(to: options.itemView.selectedTextColor, multiplier: ratio) currentItem.titleLabel.textColor = options.itemView.selectedTextColor.convert(to: options.itemView.textColor, multiplier: ratio) @@ -444,8 +457,12 @@ extension TabView { } case .reverse: if let previousItem { - indicatorView.frame.origin.x = previousItem.frame.origin.x + (currentItem.frame.origin.x - previousItem.frame.origin.x) * ratio + options.indicatorView.padding.left - indicatorView.frame.size.width = previousItem.frame.size.width + (currentItem.frame.size.width - previousItem.frame.size.width) * ratio - options.indicatorView.padding.horizontal + indicatorView.frame.origin.x = previousItem.frame.origin.x + + (currentItem.frame.origin.x - previousItem.frame.origin.x) * ratio + + padding.left + indicatorView.frame.size.width = previousItem.frame.size.width + + (currentItem.frame.size.width - previousItem.frame.size.width) * ratio + - padding.horizontal if options.interpolatesTextColorOnSwipe { previousItem.titleLabel.textColor = options.itemView.selectedTextColor.convert(to: options.itemView.textColor, multiplier: ratio) currentItem.titleLabel.textColor = options.itemView.textColor.convert(to: options.itemView.selectedTextColor, multiplier: ratio) @@ -530,4 +547,3 @@ extension TabView { } } } - From 14afd20c0372dfd811dbcf6bcb69c76cdb9d9450 Mon Sep 17 00:00:00 2001 From: Yusuke Morishita Date: Tue, 7 Jul 2026 07:19:56 -0700 Subject: [PATCH 2/2] Adopt swift-format for linting and formatting Add a .swift-format configuration (4-space indent, 160-column lines, existing line breaks respected) and normalize the codebase with the Swift 6 toolchain's built-in formatter: bracket indentation, trailing commas in multiline collections, one variable per declaration, ordered imports, and blank-line normalization. The four .forEach side-effect loops flagged by the ReplaceForEachWithForLoop rule are rewritten as for-in loops. A new swift-format CI job runs 'swift format lint --strict' and then verifies the tree is formatter-clean via git diff --exit-code. It selects the same Xcode as the build jobs so the bundled swift-format matches what contributors run locally. Existing job names are unchanged, so the required status checks are unaffected. --- .github/workflows/test.yml | 22 +++++ .swift-format | 12 +++ Example/Example/MenuViewController.swift | 18 ++-- Example/Example/OptionsViewController.swift | 95 ++++++++++--------- Example/Example/PageViewController.swift | 2 +- Example/Example/SwipeMenuSettings.swift | 2 +- .../ExampleTests/SwipeMenuSettingsTests.swift | 3 +- Package.swift | 2 +- .../ContentScrollView.swift | 9 +- .../SwipeMenuView.swift | 25 ++--- .../SwipeMenuViewController.swift | 16 ++-- .../SwipeMenuViewOptions.swift | 4 +- .../SwipeMenuViewController/TabItemView.swift | 2 +- Sources/SwipeMenuViewController/TabView.swift | 79 +++++++++------ .../UIColorExtension.swift | 13 ++- .../ContentScrollViewTests.swift | 1 + .../RetainCycleTests.swift | 3 +- .../SwipeMenuViewControllerTests.swift | 8 +- .../SwipeMenuViewOptionsTests.swift | 1 + .../SwipeMenuViewTests.swift | 14 +-- .../TabItemViewTests.swift | 1 + .../TabViewTests.swift | 17 +++- .../TestSupport.swift | 3 +- .../UIColorConversionTests.swift | 6 +- .../UIEdgeInsetsExtensionTests.swift | 5 +- 25 files changed, 230 insertions(+), 133 deletions(-) create mode 100644 .swift-format diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8de3ad..e0a8815 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,28 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + format: + name: swift-format + runs-on: macos-26 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v7 + - name: Select Xcode + # Use the same toolchain as the build jobs so the bundled swift-format + # version matches what contributors run locally. + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '^26.0' + - name: Lint + run: swift format lint --strict --recursive --parallel Sources Tests Example/Example Example/ExampleTests Package.swift + - name: Verify formatting + run: | + set -euo pipefail + swift format --in-place --recursive --parallel Sources Tests Example/Example Example/ExampleTests Package.swift + # Fail if the formatter produced any change, and surface the diff so + # the required fix is obvious from the log. + git diff --exit-code + package: name: Package tests (iOS Simulator) runs-on: macos-26 diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..ae35443 --- /dev/null +++ b/.swift-format @@ -0,0 +1,12 @@ +{ + "version": 1, + "lineLength": 160, + "indentation": { + "spaces": 4 + }, + "maximumBlankLines": 1, + "respectsExistingLineBreaks": true, + "lineBreakBeforeControlFlowKeywords": false, + "lineBreakBeforeEachArgument": false, + "prioritizeKeepingFunctionOutputTogether": true +} diff --git a/Example/Example/MenuViewController.swift b/Example/Example/MenuViewController.swift index 6b2e062..5c5f79c 100644 --- a/Example/Example/MenuViewController.swift +++ b/Example/Example/MenuViewController.swift @@ -1,5 +1,5 @@ -import UIKit import SwipeMenuViewController +import UIKit /// The example's root screen. /// @@ -10,7 +10,7 @@ final class MenuViewController: SwipeMenuViewController { private let pageTitles = [ "Bulbasaur", "Caterpie", "Golem", "Jynx", - "Marshtomp", "Salamence", "Riolu", "Araquanid" + "Marshtomp", "Salamence", "Riolu", "Araquanid", ] private var settings = SwipeMenuSettings() @@ -22,9 +22,11 @@ final class MenuViewController: SwipeMenuViewController { configuration.image = UIImage(systemName: "gearshape") configuration.cornerStyle = .capsule configuration.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(pointSize: 22, weight: .medium) - let button = UIButton(configuration: configuration, primaryAction: UIAction { [weak self] _ in - self?.presentOptions() - }) + let button = UIButton( + configuration: configuration, + primaryAction: UIAction { [weak self] _ in + self?.presentOptions() + }) button.accessibilityLabel = "Options" button.translatesAutoresizingMaskIntoConstraints = false return button @@ -33,7 +35,9 @@ final class MenuViewController: SwipeMenuViewController { private static let settingsButtonDiameter: CGFloat = 56 override func viewDidLoad() { - pageTitles.forEach { addChild(PageViewController(title: $0)) } + for pageTitle in pageTitles { + addChild(PageViewController(title: pageTitle)) + } super.viewDidLoad() @@ -62,7 +66,7 @@ final class MenuViewController: SwipeMenuViewController { settingsButton.widthAnchor.constraint(equalToConstant: Self.settingsButtonDiameter), settingsButton.heightAnchor.constraint(equalToConstant: Self.settingsButtonDiameter), settingsButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), - settingsButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16) + settingsButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16), ]) } diff --git a/Example/Example/OptionsViewController.swift b/Example/Example/OptionsViewController.swift index 60690a5..595de43 100644 --- a/Example/Example/OptionsViewController.swift +++ b/Example/Example/OptionsViewController.swift @@ -79,7 +79,7 @@ final class OptionsViewController: UIViewController { adjustWidthRow, itemWidthRow, makeSliderRow(title: "Tab margin", valueLabel: tabMarginValueLabel, slider: tabMarginSlider), - makeToggleRow(title: "Swipe between pages", toggle: contentScrollSwitch) + makeToggleRow(title: "Swipe between pages", toggle: contentScrollSwitch), ] let contentStack = UIStackView(arrangedSubviews: rows) @@ -104,59 +104,66 @@ final class OptionsViewController: UIViewController { contentStack.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), contentStack.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), contentStack.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor), - contentStack.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor) + contentStack.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor), ]) } // MARK: - Actions private func setUpActions() { - pageCountStepper.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.pageCount = Int(pageCountStepper.value) - pageCountValueLabel.text = "\(settings.pageCount)" - notifyChange() - }, for: .valueChanged) - - styleControl.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.setStyle(styleControl.selectedSegmentIndex == 0 ? .flexible : .segmented) - updateControls() - notifyChange() - }, for: .valueChanged) - - decorationControl.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.tabDecoration = SwipeMenuSettings.TabDecoration.allCases[decorationControl.selectedSegmentIndex] - notifyChange() - }, for: .valueChanged) - - adjustWidthSwitch.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.adjustsItemWidthToFit = adjustWidthSwitch.isOn - updateControls() - notifyChange() - }, for: .valueChanged) - - itemWidthSlider.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.itemWidth = CGFloat(itemWidthSlider.value) - itemWidthValueLabel.text = Self.format(settings.itemWidth) - }, for: .valueChanged) + pageCountStepper.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.pageCount = Int(pageCountStepper.value) + pageCountValueLabel.text = "\(settings.pageCount)" + notifyChange() + }, for: .valueChanged) + + styleControl.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.setStyle(styleControl.selectedSegmentIndex == 0 ? .flexible : .segmented) + updateControls() + notifyChange() + }, for: .valueChanged) + + decorationControl.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.tabDecoration = SwipeMenuSettings.TabDecoration.allCases[decorationControl.selectedSegmentIndex] + notifyChange() + }, for: .valueChanged) + + adjustWidthSwitch.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.adjustsItemWidthToFit = adjustWidthSwitch.isOn + updateControls() + notifyChange() + }, for: .valueChanged) + + itemWidthSlider.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.itemWidth = CGFloat(itemWidthSlider.value) + itemWidthValueLabel.text = Self.format(settings.itemWidth) + }, for: .valueChanged) itemWidthSlider.addAction(UIAction { [weak self] _ in self?.notifyChange() }, for: [.touchUpInside, .touchUpOutside]) - tabMarginSlider.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.tabMargin = CGFloat(tabMarginSlider.value) - tabMarginValueLabel.text = Self.format(settings.tabMargin) - }, for: .valueChanged) + tabMarginSlider.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.tabMargin = CGFloat(tabMarginSlider.value) + tabMarginValueLabel.text = Self.format(settings.tabMargin) + }, for: .valueChanged) tabMarginSlider.addAction(UIAction { [weak self] _ in self?.notifyChange() }, for: [.touchUpInside, .touchUpOutside]) - contentScrollSwitch.addAction(UIAction { [weak self] _ in - guard let self else { return } - settings.isContentScrollEnabled = contentScrollSwitch.isOn - notifyChange() - }, for: .valueChanged) + contentScrollSwitch.addAction( + UIAction { [weak self] _ in + guard let self else { return } + settings.isContentScrollEnabled = contentScrollSwitch.isOn + notifyChange() + }, for: .valueChanged) } private func reset() { diff --git a/Example/Example/PageViewController.swift b/Example/Example/PageViewController.swift index c6563e4..e1dd797 100644 --- a/Example/Example/PageViewController.swift +++ b/Example/Example/PageViewController.swift @@ -35,7 +35,7 @@ final class PageViewController: UIViewController { label.centerXAnchor.constraint(equalTo: view.centerXAnchor), label.centerYAnchor.constraint(equalTo: view.centerYAnchor), label.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 16), - label.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16) + label.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16), ]) } } diff --git a/Example/Example/SwipeMenuSettings.swift b/Example/Example/SwipeMenuSettings.swift index 0fdf564..1a2d9c0 100644 --- a/Example/Example/SwipeMenuSettings.swift +++ b/Example/Example/SwipeMenuSettings.swift @@ -1,5 +1,5 @@ -import UIKit import SwipeMenuViewController +import UIKit /// The user-adjustable configuration behind the example's swipe menu. /// diff --git a/Example/ExampleTests/SwipeMenuSettingsTests.swift b/Example/ExampleTests/SwipeMenuSettingsTests.swift index c38c3a7..f722107 100644 --- a/Example/ExampleTests/SwipeMenuSettingsTests.swift +++ b/Example/ExampleTests/SwipeMenuSettingsTests.swift @@ -1,6 +1,7 @@ +import SwipeMenuViewController import Testing import UIKit -import SwipeMenuViewController + @testable import Example @Suite("SwipeMenuSettings") diff --git a/Package.swift b/Package.swift index bf0e503..9a8269a 100644 --- a/Package.swift +++ b/Package.swift @@ -22,6 +22,6 @@ let package = Package( swiftSettings: [ .defaultIsolation(MainActor.self) ] - ) + ), ] ) diff --git a/Sources/SwipeMenuViewController/ContentScrollView.swift b/Sources/SwipeMenuViewController/ContentScrollView.swift index c04c333..885f5d8 100644 --- a/Sources/SwipeMenuViewController/ContentScrollView.swift +++ b/Sources/SwipeMenuViewController/ContentScrollView.swift @@ -82,7 +82,9 @@ open class ContentScrollView: UIScrollView { guard superview != nil else { return } // Discard the previous pages first so a reload replaces them instead of // stacking a second set of page views into the hierarchy. - pageViews.forEach { $0.removeFromSuperview() } + for pageView in pageViews { + pageView.removeFromSuperview() + } pageViews = [] setup() } @@ -98,7 +100,8 @@ open class ContentScrollView: UIScrollView { private func setup() { guard let dataSource, - dataSource.numberOfPages(in: self) > 0 else { return } + dataSource.numberOfPages(in: self) > 0 + else { return } setupScrollView() setupPages() @@ -141,7 +144,7 @@ open class ContentScrollView: UIScrollView { pageView.topAnchor.constraint(equalTo: self.topAnchor), pageView.widthAnchor.constraint(equalTo: self.widthAnchor), pageView.heightAnchor.constraint(equalTo: self.heightAnchor), - pageView.leadingAnchor.constraint(equalTo: leadingAnchor) + pageView.leadingAnchor.constraint(equalTo: leadingAnchor), ]) } } diff --git a/Sources/SwipeMenuViewController/SwipeMenuView.swift b/Sources/SwipeMenuViewController/SwipeMenuView.swift index 0f7d305..36a4a93 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuView.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuView.swift @@ -37,10 +37,10 @@ import UIKit } extension SwipeMenuViewDelegate { - public func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewWillSetupAt currentIndex: Int) { } - public func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewDidSetupAt currentIndex: Int) { } - public func swipeMenuView(_ swipeMenuView: SwipeMenuView, willChangeIndexFrom fromIndex: Int, to toIndex: Int) { } - public func swipeMenuView(_ swipeMenuView: SwipeMenuView, didChangeIndexFrom fromIndex: Int, to toIndex: Int) { } + public func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewWillSetupAt currentIndex: Int) {} + public func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewDidSetupAt currentIndex: Int) {} + public func swipeMenuView(_ swipeMenuView: SwipeMenuView, willChangeIndexFrom fromIndex: Int, to toIndex: Int) {} + public func swipeMenuView(_ swipeMenuView: SwipeMenuView, didChangeIndexFrom fromIndex: Int, to toIndex: Int) {} } // MARK: - SwipeMenuViewDataSource @@ -299,10 +299,11 @@ open class SwipeMenuView: UIView { tabView = TabView(frame: CGRect(x: 0, y: 0, width: frame.width, height: options.tabView.height), options: options.tabView) tabView?.clipsToBounds = options.tabView.clipsToBounds - let contentFrame = CGRect(x: 0, - y: options.tabView.height, - width: frame.width, - height: frame.height - options.tabView.height) + let contentFrame = CGRect( + x: 0, + y: options.tabView.height, + width: frame.width, + height: frame.height - options.tabView.height) contentScrollView = ContentScrollView(frame: contentFrame, default: defaultIndex, options: options.contentScrollView) contentScrollView?.clipsToBounds = options.contentScrollView.clipsToBounds @@ -321,8 +322,8 @@ open class SwipeMenuView: UIView { tabView.topAnchor.constraint(equalTo: self.topAnchor), tabView.leadingAnchor.constraint(equalTo: self.leadingAnchor), tabView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - tabView.heightAnchor.constraint(equalToConstant: options.tabView.height) - ]) + tabView.heightAnchor.constraint(equalToConstant: options.tabView.height), + ]) } private func layout(contentScrollView: ContentScrollView) { @@ -333,8 +334,8 @@ open class SwipeMenuView: UIView { contentScrollView.topAnchor.constraint(equalTo: self.topAnchor, constant: options.tabView.height), contentScrollView.leadingAnchor.constraint(equalTo: self.leadingAnchor), contentScrollView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - contentScrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor) - ]) + contentScrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor), + ]) } private func reset() { diff --git a/Sources/SwipeMenuViewController/SwipeMenuViewController.swift b/Sources/SwipeMenuViewController/SwipeMenuViewController.swift index 498972b..4bb6d57 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuViewController.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuViewController.swift @@ -39,30 +39,31 @@ open class SwipeMenuViewController: UIViewController, SwipeMenuViewDelegate, Swi // The top anchor is chosen once from the initial options. Toggling // `options.tabView.isSafeAreaEnabled` at runtime does not re-pin the // view, so configure the safe area behavior before the view loads. - let topAnchor = swipeMenuView.options.tabView.isSafeAreaEnabled + let topAnchor = + swipeMenuView.options.tabView.isSafeAreaEnabled ? view.safeAreaLayoutGuide.topAnchor : view.topAnchor NSLayoutConstraint.activate([ swipeMenuView.topAnchor.constraint(equalTo: topAnchor), swipeMenuView.leadingAnchor.constraint(equalTo: view.leadingAnchor), swipeMenuView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - swipeMenuView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + swipeMenuView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } // MARK: - SwipeMenuViewDelegate /// Called before the swipe menu view sets up its views. The default implementation does nothing; override to react. - open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewWillSetupAt currentIndex: Int) { } + open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewWillSetupAt currentIndex: Int) {} /// Called after the swipe menu view has set up its views. The default implementation does nothing; override to react. - open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewDidSetupAt currentIndex: Int) { } + open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewDidSetupAt currentIndex: Int) {} /// Called before the front page changes. The default implementation does nothing; override to react. - open func swipeMenuView(_ swipeMenuView: SwipeMenuView, willChangeIndexFrom fromIndex: Int, to toIndex: Int) { } + open func swipeMenuView(_ swipeMenuView: SwipeMenuView, willChangeIndexFrom fromIndex: Int, to toIndex: Int) {} /// Called after the front page has changed. The default implementation does nothing; override to react. - open func swipeMenuView(_ swipeMenuView: SwipeMenuView, didChangeIndexFrom fromIndex: Int, to toIndex: Int) { } + open func swipeMenuView(_ swipeMenuView: SwipeMenuView, didChangeIndexFrom fromIndex: Int, to toIndex: Int) {} // MARK: - SwipeMenuViewDataSource @@ -87,7 +88,8 @@ open class SwipeMenuViewController: UIViewController, SwipeMenuViewDelegate, Swi /// than crashing. Override to provide pages that are not backed by `children`. open func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController { guard children.indices.contains(index) else { - assertionFailure(""" + assertionFailure( + """ SwipeMenuViewController: requested a page at \(index) but only \(children.count) \ child view controllers exist. Override the data source to provide the missing pages. """) diff --git a/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift b/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift index 9bbb4b8..383c344 100644 --- a/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift +++ b/Sources/SwipeMenuViewController/SwipeMenuViewOptions.swift @@ -129,7 +129,7 @@ public nonisolated struct SwipeMenuViewOptions: Sendable { /// IndicatorView options public var indicatorView = IndicatorView() - public init() { } + public init() {} } public nonisolated struct ContentScrollView: Sendable { @@ -161,5 +161,5 @@ public nonisolated struct SwipeMenuViewOptions: Sendable { /// ContentScrollView options public var contentScrollView = ContentScrollView() - public init() { } + public init() {} } diff --git a/Sources/SwipeMenuViewController/TabItemView.swift b/Sources/SwipeMenuViewController/TabItemView.swift index 9d63c2b..c72856d 100644 --- a/Sources/SwipeMenuViewController/TabItemView.swift +++ b/Sources/SwipeMenuViewController/TabItemView.swift @@ -65,7 +65,7 @@ final class TabItemView: UIView { titleLabel.topAnchor.constraint(equalTo: topAnchor), titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor), titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor), - titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor) + titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor), ]) } } diff --git a/Sources/SwipeMenuViewController/TabView.swift b/Sources/SwipeMenuViewController/TabView.swift index 98e83b6..4d601fc 100644 --- a/Sources/SwipeMenuViewController/TabView.swift +++ b/Sources/SwipeMenuViewController/TabView.swift @@ -145,9 +145,11 @@ open class TabView: UIScrollView { /// - options: New tab options to apply before reloading. Pass `nil` to keep the current options. /// - defaultIndex: The tab to select after reloading. Pass `nil` to leave the selection unchanged. /// - animated: Whether moving to `defaultIndex` is animated. Defaults to `true`. - public func reloadData(options: SwipeMenuViewOptions.TabView? = nil, - default defaultIndex: Int? = nil, - animated: Bool = true) { + public func reloadData( + options: SwipeMenuViewOptions.TabView? = nil, + default defaultIndex: Int? = nil, + animated: Bool = true + ) { if let options { self.options = options @@ -156,7 +158,8 @@ open class TabView: UIScrollView { reset() guard let dataSource, - dataSource.numberOfItems(in: self) > 0 else { return } + dataSource.numberOfItems(in: self) > 0 + else { return } setupScrollView() setupContainerView(dataSource: dataSource) @@ -170,7 +173,9 @@ open class TabView: UIScrollView { func reset() { currentIndex = 0 - itemViews.forEach { $0.removeFromSuperview() } + for itemView in itemViews { + itemView.removeFromSuperview() + } indicatorView.removeFromSuperview() containerView.removeFromSuperview() itemViews = [] @@ -267,7 +272,7 @@ open class TabView: UIScrollView { NSLayoutConstraint.activate([ tabItemView.widthAnchor.constraint(equalToConstant: tabItemView.frame.width) - ]) + ]) case .segmented: let inset = layoutSafeAreaInsets tabItemView.frame.size.width = (frame.width - options.margin * 2 - inset.horizontal) / CGFloat(itemCount) @@ -284,8 +289,8 @@ open class TabView: UIScrollView { NSLayoutConstraint.activate([ tabItemView.topAnchor.constraint(equalTo: containerView.topAnchor), - tabItemView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) - ]) + tabItemView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + ]) xPosition += tabItemView.frame.size.width } @@ -318,8 +323,8 @@ open class TabView: UIScrollView { containerView.topAnchor.constraint(equalTo: self.topAnchor), leftMarginConstraint, containerView.widthAnchor.constraint(equalToConstant: containerWidth), - heightConstraint - ]) + heightConstraint, + ]) contentSize.width = containerWidth + options.margin * 2 + inset.horizontal case .segmented: widthConstraint = containerView.widthAnchor.constraint(equalTo: self.widthAnchor, constant: -(options.margin * 2 + inset.horizontal)) @@ -327,8 +332,8 @@ open class TabView: UIScrollView { containerView.topAnchor.constraint(equalTo: self.topAnchor), leftMarginConstraint, widthConstraint, - heightConstraint - ]) + heightConstraint, + ]) contentSize = .zero } @@ -360,20 +365,24 @@ extension TabView { case .underline: let itemView = itemViews[currentIndex] let padding = options.indicatorView.padding - indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + padding.left, - y: itemView.frame.height - padding.vertical, - width: itemView.frame.width - padding.horizontal, - height: options.indicatorView.underline.height)) + indicatorView = UIView( + frame: CGRect( + x: itemView.frame.origin.x + padding.left, + y: itemView.frame.height - padding.vertical, + width: itemView.frame.width - padding.horizontal, + height: options.indicatorView.underline.height)) indicatorView.layer.cornerRadius = options.indicatorView.underline.cornerRadius indicatorView.backgroundColor = options.indicatorView.backgroundColor containerView.addSubview(indicatorView) case .circle: let itemView = itemViews[currentIndex] let padding = options.indicatorView.padding - indicatorView = UIView(frame: CGRect(x: itemView.frame.origin.x + padding.left, - y: 0, - width: itemView.frame.width - padding.horizontal, - height: itemView.bounds.height - padding.vertical)) + indicatorView = UIView( + frame: CGRect( + x: itemView.frame.origin.x + padding.left, + y: 0, + width: itemView.frame.width - padding.horizontal, + height: itemView.bounds.height - padding.vertical)) indicatorView.layer.position.y = itemView.layer.position.y indicatorView.layer.cornerRadius = options.indicatorView.circle.cornerRadius ?? indicatorView.frame.height / 2 indicatorView.backgroundColor = options.indicatorView.backgroundColor @@ -407,7 +416,8 @@ extension TabView { private func resetIndicatorViewPosition(index: Int) { guard options.style == .segmented, let dataSource, - dataSource.numberOfItems(in: self) > 0 else { return } + dataSource.numberOfItems(in: self) > 0 + else { return } // Each `.segmented` tab item spans the full (unadjusted) cell width, so // that width is the indicator's per-tab stride. The indicator itself is @@ -425,9 +435,11 @@ extension TabView { update(index) if animated { - UIView.animate(withDuration: options.indicatorView.animationDuration, animations: { - self.updateIndicatorViewPosition(index: index) - }, completion: completion) + UIView.animate( + withDuration: options.indicatorView.animationDuration, + animations: { + self.updateIndicatorViewPosition(index: index) + }, completion: completion) } else { updateIndicatorViewPosition(index: index) } @@ -444,10 +456,12 @@ extension TabView { switch direction { case .forward: if let nextItem { - indicatorView.frame.origin.x = currentItem.frame.origin.x + indicatorView.frame.origin.x = + currentItem.frame.origin.x + (nextItem.frame.origin.x - currentItem.frame.origin.x) * ratio + padding.left - indicatorView.frame.size.width = currentItem.frame.size.width + indicatorView.frame.size.width = + currentItem.frame.size.width + (nextItem.frame.size.width - currentItem.frame.size.width) * ratio - padding.horizontal if options.interpolatesTextColorOnSwipe { @@ -457,10 +471,12 @@ extension TabView { } case .reverse: if let previousItem { - indicatorView.frame.origin.x = previousItem.frame.origin.x + indicatorView.frame.origin.x = + previousItem.frame.origin.x + (currentItem.frame.origin.x - previousItem.frame.origin.x) * ratio + padding.left - indicatorView.frame.size.width = previousItem.frame.size.width + indicatorView.frame.size.width = + previousItem.frame.size.width + (currentItem.frame.size.width - previousItem.frame.size.width) * ratio - padding.horizontal if options.interpolatesTextColorOnSwipe { @@ -522,15 +538,16 @@ extension TabView { } private func addTabItemGestures() { - itemViews.forEach { - $0.addGestureRecognizer(makeTapGestureRecognizer()) + for itemView in itemViews { + itemView.addGestureRecognizer(makeTapGestureRecognizer()) } } @objc private func tapItemView(_ recognizer: UITapGestureRecognizer) { guard let itemView = recognizer.view as? TabItemView, let index: Int = itemViews.firstIndex(of: itemView), - currentIndex != index else { return } + currentIndex != index + else { return } tabViewDelegate?.tabView(self, willSelectTabAt: index) moveTabItem(index: index, animated: true) update(index) diff --git a/Sources/SwipeMenuViewController/UIColorExtension.swift b/Sources/SwipeMenuViewController/UIColorExtension.swift index b37a3d1..7ee79d2 100644 --- a/Sources/SwipeMenuViewController/UIColorExtension.swift +++ b/Sources/SwipeMenuViewController/UIColorExtension.swift @@ -5,11 +5,18 @@ extension UIColor { func convert(to color: UIColor, multiplier: CGFloat) -> UIColor? { let ratio = min(max(multiplier, 0), 1) - var fromRed: CGFloat = 0, fromGreen: CGFloat = 0, fromBlue: CGFloat = 0, fromAlpha: CGFloat = 0 - var toRed: CGFloat = 0, toGreen: CGFloat = 0, toBlue: CGFloat = 0, toAlpha: CGFloat = 0 + var fromRed: CGFloat = 0 + var fromGreen: CGFloat = 0 + var fromBlue: CGFloat = 0 + var fromAlpha: CGFloat = 0 + var toRed: CGFloat = 0 + var toGreen: CGFloat = 0 + var toBlue: CGFloat = 0 + var toAlpha: CGFloat = 0 guard getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha), - color.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha) else { + color.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha) + else { return nil } diff --git a/Tests/SwipeMenuViewControllerTests/ContentScrollViewTests.swift b/Tests/SwipeMenuViewControllerTests/ContentScrollViewTests.swift index 5398235..f195fa0 100644 --- a/Tests/SwipeMenuViewControllerTests/ContentScrollViewTests.swift +++ b/Tests/SwipeMenuViewControllerTests/ContentScrollViewTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor diff --git a/Tests/SwipeMenuViewControllerTests/RetainCycleTests.swift b/Tests/SwipeMenuViewControllerTests/RetainCycleTests.swift index 680e379..36bd32b 100644 --- a/Tests/SwipeMenuViewControllerTests/RetainCycleTests.swift +++ b/Tests/SwipeMenuViewControllerTests/RetainCycleTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -30,7 +31,7 @@ struct RetainCycleTests { let container = UIView(frame: CGRect(x: 0, y: 0, width: 375, height: 667)) let view = SwipeMenuView(frame: container.bounds) view.dataSource = dataSource - container.addSubview(view) // triggers setup -> contentScrollView.dataSource = self + container.addSubview(view) // triggers setup -> contentScrollView.dataSource = self view.layoutIfNeeded() weakView = view view.removeFromSuperview() diff --git a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewControllerTests.swift b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewControllerTests.swift index 8d2452d..a2496a8 100644 --- a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewControllerTests.swift +++ b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewControllerTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -75,14 +76,15 @@ struct SwipeMenuViewControllerTests { // Find the constraint that pins swipeMenuView.topAnchor and confirm its // other end is the view's safe-area layout guide (not the view itself). let topConstraint = vc.view.constraints.first { constraint in - (constraint.firstItem === vc.swipeMenuView && constraint.firstAttribute == .top) || - (constraint.secondItem === vc.swipeMenuView && constraint.secondAttribute == .top) + (constraint.firstItem === vc.swipeMenuView && constraint.firstAttribute == .top) + || (constraint.secondItem === vc.swipeMenuView && constraint.secondAttribute == .top) } #expect(topConstraint != nil) if let topConstraint { - let otherItem: AnyObject? = (topConstraint.firstItem === vc.swipeMenuView) + let otherItem: AnyObject? = + (topConstraint.firstItem === vc.swipeMenuView) ? topConstraint.secondItem : topConstraint.firstItem #expect(otherItem === vc.view.safeAreaLayoutGuide) diff --git a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewOptionsTests.swift b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewOptionsTests.swift index ba774fc..b16f227 100644 --- a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewOptionsTests.swift +++ b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewOptionsTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController /// Constructs a `SwipeMenuViewOptions` from a `nonisolated` context. That this diff --git a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewTests.swift b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewTests.swift index ca2dd6f..f314e17 100644 --- a/Tests/SwipeMenuViewControllerTests/SwipeMenuViewTests.swift +++ b/Tests/SwipeMenuViewControllerTests/SwipeMenuViewTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -117,12 +118,13 @@ struct SwipeMenuViewTests { // Each jump contributes exactly one paired willChange/didChange, and the // view lands on the most recent target. #expect(view.currentIndex == 0) - #expect(delegate.events == [ - .willChange(from: 0, to: 2), - .didChange(from: 0, to: 2), - .willChange(from: 2, to: 0), - .didChange(from: 2, to: 0) - ]) + #expect( + delegate.events == [ + .willChange(from: 0, to: 2), + .didChange(from: 0, to: 2), + .willChange(from: 2, to: 0), + .didChange(from: 2, to: 0), + ]) } @Test("Selecting a tab during an in-flight jump keeps delegate calls paired") diff --git a/Tests/SwipeMenuViewControllerTests/TabItemViewTests.swift b/Tests/SwipeMenuViewControllerTests/TabItemViewTests.swift index c6b42ec..7912592 100644 --- a/Tests/SwipeMenuViewControllerTests/TabItemViewTests.swift +++ b/Tests/SwipeMenuViewControllerTests/TabItemViewTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor diff --git a/Tests/SwipeMenuViewControllerTests/TabViewTests.swift b/Tests/SwipeMenuViewControllerTests/TabViewTests.swift index 21a8c07..d3ee5b6 100644 --- a/Tests/SwipeMenuViewControllerTests/TabViewTests.swift +++ b/Tests/SwipeMenuViewControllerTests/TabViewTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -140,7 +141,7 @@ struct TabViewTests { tabView.topAnchor.constraint(equalTo: viewController.view.topAnchor), tabView.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor), tabView.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor), - tabView.heightAnchor.constraint(equalToConstant: options.height) + tabView.heightAnchor.constraint(equalToConstant: options.height), ]) viewController.view.layoutIfNeeded() // Build the items against the stable frame with the safe area in place. @@ -185,7 +186,7 @@ struct TabViewTests { tabView.topAnchor.constraint(equalTo: viewController.view.topAnchor), tabView.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor), tabView.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor), - tabView.heightAnchor.constraint(equalToConstant: options.height) + tabView.heightAnchor.constraint(equalToConstant: options.height), ]) viewController.view.layoutIfNeeded() // Build the items against the stable frame with the safe area in place. @@ -227,7 +228,7 @@ struct TabViewTests { tabView.topAnchor.constraint(equalTo: viewController.view.topAnchor), tabView.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor), tabView.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor), - tabView.heightAnchor.constraint(equalToConstant: options.height) + tabView.heightAnchor.constraint(equalToConstant: options.height), ]) viewController.view.layoutIfNeeded() // Build the items against the stable frame with no safe area yet. @@ -512,8 +513,14 @@ struct TabViewTests { /// Compares two colors by their RGBA components with a small tolerance. private func colorsEqual(_ lhs: UIColor, _ rhs: UIColor, tolerance: CGFloat = 0.01) -> Bool { - var lr: CGFloat = 0, lg: CGFloat = 0, lb: CGFloat = 0, la: CGFloat = 0 - var rr: CGFloat = 0, rg: CGFloat = 0, rb: CGFloat = 0, ra: CGFloat = 0 + var lr: CGFloat = 0 + var lg: CGFloat = 0 + var lb: CGFloat = 0 + var la: CGFloat = 0 + var rr: CGFloat = 0 + var rg: CGFloat = 0 + var rb: CGFloat = 0 + var ra: CGFloat = 0 lhs.getRed(&lr, green: &lg, blue: &lb, alpha: &la) rhs.getRed(&rr, green: &rg, blue: &rb, alpha: &ra) return abs(lr - rr) < tolerance && abs(lg - rg) < tolerance diff --git a/Tests/SwipeMenuViewControllerTests/TestSupport.swift b/Tests/SwipeMenuViewControllerTests/TestSupport.swift index 425909e..00e9ec3 100644 --- a/Tests/SwipeMenuViewControllerTests/TestSupport.swift +++ b/Tests/SwipeMenuViewControllerTests/TestSupport.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController // MARK: - SwipeMenuView stubs @@ -194,7 +195,7 @@ func hostTabView(_ tabView: TabView, width: CGFloat = 375) -> UIWindow { tabView.topAnchor.constraint(equalTo: container.topAnchor), tabView.leadingAnchor.constraint(equalTo: container.leadingAnchor), tabView.trailingAnchor.constraint(equalTo: container.trailingAnchor), - tabView.heightAnchor.constraint(equalToConstant: height) + tabView.heightAnchor.constraint(equalToConstant: height), ]) container.setNeedsLayout() diff --git a/Tests/SwipeMenuViewControllerTests/UIColorConversionTests.swift b/Tests/SwipeMenuViewControllerTests/UIColorConversionTests.swift index 6d5dd14..eb434e9 100644 --- a/Tests/SwipeMenuViewControllerTests/UIColorConversionTests.swift +++ b/Tests/SwipeMenuViewControllerTests/UIColorConversionTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -8,7 +9,10 @@ struct UIColorConversionTests { /// Extracts the RGBA components of a color for comparison. private func rgba(_ color: UIColor) -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { - var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 + var r: CGFloat = 0 + var g: CGFloat = 0 + var b: CGFloat = 0 + var a: CGFloat = 0 color.getRed(&r, green: &g, blue: &b, alpha: &a) return (r, g, b, a) } diff --git a/Tests/SwipeMenuViewControllerTests/UIEdgeInsetsExtensionTests.swift b/Tests/SwipeMenuViewControllerTests/UIEdgeInsetsExtensionTests.swift index d0af949..ff5e1ca 100644 --- a/Tests/SwipeMenuViewControllerTests/UIEdgeInsetsExtensionTests.swift +++ b/Tests/SwipeMenuViewControllerTests/UIEdgeInsetsExtensionTests.swift @@ -1,5 +1,6 @@ import Testing import UIKit + @testable import SwipeMenuViewController @MainActor @@ -20,8 +21,8 @@ struct UIEdgeInsetsExtensionTests { func pairedSums() { let insets = UIEdgeInsets(top: 1, left: 2, bottom: 3, right: 4) - #expect(insets.horizontal == 6) // left + right - #expect(insets.vertical == 4) // top + bottom + #expect(insets.horizontal == 6) // left + right + #expect(insets.vertical == 4) // top + bottom } @Test("zero insets have zero sums")