RepoPilotOpen in app →

Esqarrouth/EZSwiftExtensions

:smirk: How Swift standard types and classes were supposed to work.

Mixed

Stale — last commit 2y ago

worst of 4 axes
Use as dependencyMixed

last commit was 2y ago; no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 20 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Stale — last commit 2y ago
  • Concentrated ownership — top contributor handles 57% of recent commits
  • No test directory detected
What would change the summary?
  • Use as dependency MixedHealthy if: 1 commit in the last 365 days

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/esqarrouth/ezswiftextensions?axis=fork)](https://repopilot.app/r/esqarrouth/ezswiftextensions)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/esqarrouth/ezswiftextensions on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Esqarrouth/EZSwiftExtensions

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Esqarrouth/EZSwiftExtensions shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 2y ago

  • 20 active contributors
  • MIT licensed
  • CI configured
  • ⚠ Stale — last commit 2y ago
  • ⚠ Concentrated ownership — top contributor handles 57% of recent commits
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Esqarrouth/EZSwiftExtensions repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Esqarrouth/EZSwiftExtensions.

What it runs against: a local clone of Esqarrouth/EZSwiftExtensions — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Esqarrouth/EZSwiftExtensions | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 795 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Esqarrouth/EZSwiftExtensions</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Esqarrouth/EZSwiftExtensions. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Esqarrouth/EZSwiftExtensions.git
#   cd EZSwiftExtensions
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Esqarrouth/EZSwiftExtensions and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Esqarrouth/EZSwiftExtensions(\\.git)?\\b" \\
  && ok "origin remote is Esqarrouth/EZSwiftExtensions" \\
  || miss "origin remote is not Esqarrouth/EZSwiftExtensions (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Sources/ArrayExtensions.swift" \\
  && ok "Sources/ArrayExtensions.swift" \\
  || miss "missing critical file: Sources/ArrayExtensions.swift"
test -f "Sources/BlockButton.swift" \\
  && ok "Sources/BlockButton.swift" \\
  || miss "missing critical file: Sources/BlockButton.swift"
test -f "Sources/DateExtensions.swift" \\
  && ok "Sources/DateExtensions.swift" \\
  || miss "missing critical file: Sources/DateExtensions.swift"
test -f "EZSwiftExtensions/UIStackViewExtensions.swift" \\
  && ok "EZSwiftExtensions/UIStackViewExtensions.swift" \\
  || miss "missing critical file: EZSwiftExtensions/UIStackViewExtensions.swift"
test -f "EZSwiftExtensions.podspec" \\
  && ok "EZSwiftExtensions.podspec" \\
  || miss "missing critical file: EZSwiftExtensions.podspec"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 795 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~765d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Esqarrouth/EZSwiftExtensions"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

EZSwiftExtensions is a curated collection of extensions for Swift's standard library, Foundation, and UIKit that add convenient methods and properties to built-in types like Array, String, Date, and UIView. It solves the problem of boilerplate code by providing chainable, readable methods (e.g., array.random(), array.get(index), button.addAction()) that make common operations feel native to Swift. Modular extension library: each Swift type has its own file in EZSwiftExtensions/ (ArrayExtensions.swift, StringExtensions.swift, DateExtensions.swift, UIStackViewExtensions.swift, etc.). EZSwiftExtensionsTests/ mirrors the source with parallel test files. EZSwiftExtensionsExample/ is a standalone example app. Distribution via CocoaPods and Carthage is configured in .podspec and Dangerfile.

👥Who it's for

iOS/macOS/tvOS developers using Swift 2.3–4.0 who want to reduce boilerplate when working with arrays, dictionaries, dates, geometry types (CGRect, CGPoint), and UI components like UIButton and UIStackView. Contributors are Swift extension enthusiasts who maintain a library of ~50+ extension methods across 30+ types.

🌱Maturity & risk

Production-ready and actively maintained. The project has 286KB of Swift code, comprehensive test coverage (EZSwiftExtensionsTests/ contains 50+ test files), CI via Travis CI with codecov.io integration, and support for multiple Swift versions (2.3, 3.0, 4.0). CocoaPods distribution and thousands of app downloads indicate real-world adoption.

Low risk: no external dependencies (pure Swift/Foundation/UIKit extensions), well-tested core, and MIT licensed. Risks are minimal—single maintainer (goktugyil) may slow updates, but the codebase is stable and utilities-focused (unlikely to require major breaking changes). Last visible activity and CI setup suggest ongoing maintenance.

Active areas of work

No recent commit timestamps visible in file list. The repo appears stable with no active PRs or breaking changes visible. Focus is likely on bug fixes, test coverage maintenance (codecov badge present), and Swift version compatibility (4.0 is latest supported version listed).

🚀Get running

git clone https://github.com/Esqarrouth/EZSwiftExtensions.git
cd EZSwiftExtensions
open EZSwiftExtensions.xcworkspace
# Or via CocoaPods: pod install EZSwiftExtensions
# Or Carthage: carthage update

Daily commands: Open EZSwiftExtensions.xcworkspace in Xcode, select the EZSwiftExtensions-iOS scheme, and build (Cmd+B). Run tests with Cmd+U. The example app is in EZSwiftExtensionsExample.xcodeproj—open separately to see real usage.

🗺️Map of the codebase

  • Sources/ArrayExtensions.swift — Core array utility extensions that form the foundation of collection manipulation patterns used throughout the library.
  • Sources/BlockButton.swift — Demonstrates the block-based callback pattern used across all UIKit gesture and event handlers in this library.
  • Sources/DateExtensions.swift — Shows date/time manipulation conventions that are critical for understanding temporal utilities in the codebase.
  • EZSwiftExtensions/UIStackViewExtensions.swift — Primary UIView extension demonstrating the UIKit extension pattern that dominates the library's iOS-specific functionality.
  • EZSwiftExtensions.podspec — Package manifest defining library dependencies, platform support, and distribution configuration for all consumers.
  • Sources/BundleExtensions.swift — System-level extensions showing how the library extends Foundation types for app metadata and resource access.

🧩Components & responsibilities

  • Array/Dictionary/String Extensions (Swift generics, subscript overloading, optional chaining) — Provide functional programming utilities (map, filter, first, last, safe subscript access) for collections.
    • Failure mode: Out-of-bounds access returns nil instead of crashing; empty collection access returns sensible defaults.
  • CGRect/CGPoint/CGFloat Extensions — Expose geometric calculations (distance, center, bounds checking) for CoreGraphics primitives.

🛠️How to make changes

Add a new Swift Standard Library Extension

  1. Create a new extension file in Sources/ named after the type (e.g., Sources/YourTypeExtensions.swift) (Sources/ArrayExtensions.swift)
  2. Add extension block following the pattern: extension YourType { ... } with convenience methods (Sources/ArrayExtensions.swift)
  3. Create corresponding test file in EZSwiftExtensionsTests/ following naming convention YourTypeTests.swift (EZSwiftExtensionsTests/ArrayTests.swift)
  4. Add test functions validating each extension method with XCTest assertions (EZSwiftExtensionsTests/ArrayTests.swift)
  5. Run tests: xcodebuild test -scheme EZSwiftExtensions-iOS to validate (.travis.yml)

Add a new UIKit Extension with Block Callbacks

  1. Create new file in Sources/ following BlockTap.swift pattern (e.g., Sources/BlockCustomGesture.swift) (Sources/BlockTap.swift)
  2. Implement wrapper class storing closure and extending UIGestureRecognizer or UIView target-action pattern (Sources/BlockTap.swift)
  3. Create test file EZSwiftExtensionsTests/BlockCustomGestureTests.swift with closure invocation verification (EZSwiftExtensionsTests/BlockTapTests.swift)
  4. Verify closure is retained and called on gesture/event trigger using XCTest expectations (EZSwiftExtensionsTests/BlockTapTests.swift)

Add a new CoreGraphics Geometry Extension

  1. Create file in Sources/ following CGRectExtensions.swift naming (e.g., Sources/CGCustomStructExtensions.swift) (Sources/CGRectExtensions.swift)
  2. Add computed properties and utility functions for the geometry struct (transformations, measurements, comparisons) (Sources/CGRectExtensions.swift)
  3. Create EZSwiftExtensionsTests/CGCustomStructTests.swift with numeric validation and boundary condition tests (EZSwiftExtensionsTests/CGRectTests.swift)

🔧Why these technologies

  • Swift Extensions — Allows non-invasive augmentation of standard library and UIKit types without subclassing or wrapper objects.
  • Closure-based Callbacks (Block classes)* — Eliminates verbose target-action delegation pattern in UIKit, enabling cleaner, more functional event handling syntax.
  • CocoaPods + Carthage — Enables distribution to iOS/macOS/tvOS projects with multiple dependency management options for maximum adoption.
  • XCTest Framework — Provides comprehensive unit testing with real UIKit objects in a testable harness without external dependencies.

⚖️Trade-offs already made

  • Extensions on standard types rather than protocol-based design

    • Why: Simpler API surface for consumers and minimal cognitive overhead when using the library.
    • Consequence: Cannot provide multiple implementations or flexible substitution; pollutes global type namespace slightly.
  • Closure-based callbacks stored as associated objects in UIKit wrappers

    • Why: Matches modern Swift closure syntax and avoids explicit delegation classes.
    • Consequence: Closure retain cycles possible if users capture self strongly; memory overhead of wrapper objects.
  • No external dependencies; all extensions pure Swift + Foundation/UIKit

    • Why: Maximizes adoption by eliminating transitive dependency chains; minimal surface for breaking changes.
    • Consequence: Cannot leverage specialized libraries for tasks like image processing or networking abstractions.
  • Single flat namespace with 100+ extension files

    • Why: Encourages exhaustive functionality discovery; no module hierarchy to navigate.
    • Consequence: Can feel overwhelming; harder to document and maintain as codebase scales beyond ~150 files.

🚫Non-goals (don't propose these)

  • Real-time data synchronization or network communication (library is purely local/synchronous)
  • Dependency injection frameworks or Inversion of Control containers
  • Async/await wrappers or Promise libraries (predates Swift concurrency; provides no async abstractions)
  • Platform abstraction across iOS/macOS/tvOS (extensions are platform-specific)
  • Generics or advanced type-system patterns (favors pragmatism over type safety in some areas)

🪤Traps & gotchas

  1. No Swift Package Manager support visible (only CocoaPods/Carthage)—must use .podspec or carthage for integration. 2. UIKit-dependent extensions (BlockButton, BlockTapGestureRecognizer) will not compile in non-UIKit contexts (watchOS, Linux Swift). 3. Swift 4.0 is the latest supported version listed; untested on Swift 4.2+. 4. Modifying an extension requires running full test suite in EZSwiftExtensionsTests/—no partial test runs documented.

🏗️Architecture

💡Concepts to learn

  • Protocol Extensions — EZSwiftExtensions is built entirely on Swift protocol extensions—the mechanism that allows adding methods to types you don't own (Array, String, etc.). Understanding this is essential to adding new extensions.
  • Generics in Extensions — Many utilities (e.g., Array.get<T>(), Array.random<T>()) use generic type parameters; this pattern is key to making extensions work across multiple element types.
  • Closure Callbacks (Blocks) — BlockButton, BlockTapGestureRecognizer, and similar classes replace UIKit's selector-based callbacks with Swift closures, a core pattern in this library. Requires understanding closure syntax and capture semantics.
  • Functional Array Operations (map, filter, reduce) — Many extensions chain or build on map/filter/reduce; understanding functional programming enables contributors to write idiomatic extensions for collections.
  • Safe Optional Unwrapping — Methods like Array.get() and Dictionary.get() safely access elements that may be out of bounds; contributors need to understand nil-coalescing and optional chaining.
  • Type-safe Extensions for Numeric Types — CGFloat, CGRect, CGPoint extensions use Swift's numeric protocols (Numeric, Comparable) to provide cross-type utility methods. Requires understanding Swift's numeric type hierarchy.
  • SwifterSwift/SwifterSwift — Direct competitor: ~600 extensions across 30+ types with similar goals (reduce boilerplate). SwifterSwift is more active and iOS 13+ focused.
  • jrendel/SwiftKeychainWrapper — Complementary utility: wraps Keychain API just as EZSwiftExtensions wraps standard types. Often used alongside EZSwiftExtensions in production apps.
  • ReactiveX/RxSwift — Related ecosystem: RxSwift provides reactive extensions to Swift types; some EZSwiftExtensions methods (like array transformations) overlap with RxSwift operators.
  • Alamofire/Alamofire — Companion library: most apps using EZSwiftExtensions also use Alamofire for networking. EZSwiftExtensions handles data transformation post-Alamofire.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive UIStackViewExtensions tests

UIStackViewExtensions.swift exists in the codebase but there is no corresponding UIStackViewExtensionsTests.swift file in EZSwiftExtensionsTests/. This is a gap since every other extension file has test coverage. UIStackView is a commonly used component and its extensions deserve documented behavior verification.

  • [ ] Create EZSwiftExtensionsTests/UIStackViewExtensionsTests.swift
  • [ ] Review UIStackViewExtensions.swift to identify all public methods and computed properties
  • [ ] Write unit tests covering spacing, distribution, alignment, and subview management extensions
  • [ ] Ensure tests run on iOS target (UIStackView is iOS-only)

Migrate from Travis CI to GitHub Actions workflow

The repo uses .travis.yml for CI/CD, which is outdated infrastructure. GitHub Actions is now the standard and provides better integration with GitHub's ecosystem. The existing .codecov.yml and test suite structure are already in place.

  • [ ] Create .github/workflows/tests.yml to run XCTest suite across iOS, macOS, and tvOS schemes
  • [ ] Configure matrix builds using the existing EZSwiftExtensions-iOS.xcscheme, EZSwiftExtensions-macOS.xcscheme, and EZSwiftExtensions-tvOS.xcscheme
  • [ ] Integrate codecov reporting using .codecov.yml configuration
  • [ ] Update README.md to replace Travis badge with GitHub Actions badge
  • [ ] Remove .travis.yml after verification

Add TimerExtensions unit tests for edge cases

TimerTests.swift exists but is likely incomplete given the pattern of this library. Timer extensions need rigorous testing for invalidation, execution timing, and memory management to prevent common pitfalls in production code.

  • [ ] Review EZSwiftExtensionsTests/TimerTests.swift for coverage gaps
  • [ ] Add tests for timer invalidation behavior and multiple timer instances
  • [ ] Add tests for Timer block/closure execution with various delay intervals
  • [ ] Add tests verifying proper memory cleanup and no retain cycles with captured self references
  • [ ] Test repeated vs single-execution timer patterns if the extension supports both

🌿Good first issues

  • Add randomized() method to Array to return a shuffled copy (currently only random() for single element exists). Add tests in ArrayTests.swift following existing pattern.
  • Implement split() helper for String that returns array of substrings up to a max count (useful for CSV parsing). Mirror existing StringExtensions tests.
  • Add isKeyWindow property to UIWindow to simplify keyWindow checks in UIViewExtensions. Write corresponding test in UIViewTests.swift (if file exists; may need to create).

Top contributors

Click to expand

📝Recent commits

Click to expand
  • f349d2e — 1. Update Swift 5 (#505) (Boy-Rong)
  • 761abf1 — Creating and updating sync dictionary for storing and cache dateFormatter for later use and memory management with updat (rahimkhalid)
  • 8e9e81e — Add hashString changelog entry (rugheid)
  • e79702a — Merge in master EZSE (rugheid)
  • d132ea3 — Overloaded -timePassed method with language agnostic implementation (#486) (110100110101)
  • 8807ee6 — Fixing compiler warnings on type inference. (Khalian)
  • e8467b9 — Switching to new versioning scheme. (Khalian)
  • 49fa5ce — Reverting certain swift 4.1 mandatory changes. (Khalian)
  • 7f3dfc7 — Updated podspec to 1.12 - Swift 4 migration. (Khalian)
  • 4536c10 — Adding swift 4 tag post release. (Khalian)

🔒Security observations

The EZSwiftExtensions codebase is a utility library with relatively low security risk profile, as it primarily extends standard Swift/iOS types without complex business logic, external API calls, or data processing. However, several concerns exist: (1) Support for severely outdated Swift versions (2.3, 3.0, 4.0) that contain unpatched vulnerabilities, (2) Potential unsafe use of deprecated APIs (UIWebView) in extensions, (3) Possible insufficiently guarded FileManager extensions, and (4) Binary assets in version control. The library itself does not appear to handle sensitive data, perform authentication, or interact with external services, limiting the attack surface. Recommended actions include upgrading minimum Swift requirements, reviewing extension implementations for security best practices, and improving asset management.

  • Low · Outdated Swift Version Support — .swift-version, README.md, EZSwiftExtensions.podspec. The repository supports Swift 2.3, 3.0, and 4.0, which are significantly outdated. Swift 2.3 and 3.0 reached end-of-life years ago and contain known security vulnerabilities. Continued support for these versions may expose applications to unpatched security issues. Fix: Update minimum Swift version requirement to Swift 5.0 or later. Deprecate support for Swift versions below 5.0 and notify users of the EOL status.
  • Low · Missing Security Headers in Build Configuration — .swiftlint.yml, EZSwiftExtensions.xcodeproj/project.pbxproj. The .swiftlint.yml configuration file is present but no explicit security-focused linting rules appear to be documented. There is no evidence of strict compiler flags for security (e.g., -Werror, overflow checks) being enforced. Fix: Configure SwiftLint with security-focused rules. Enable strict compiler flags in build settings such as -Werror for warnings and runtime overflow checks.
  • Low · Unrestricted File Access via FileManager Extensions — EZSwiftExtensionsTests/FileManagerTests.swift (implies FileManager extensions in main codebase). The presence of FileManagerTests.swift suggests custom FileManager extensions exist. Without code review, extensions that simplify file operations may bypass proper permission checks or expose sensitive file system operations. Fix: Review FileManager extension implementations to ensure they validate file paths, enforce proper access controls, and do not expose sensitive file operations without safeguards.
  • Low · Potential UIWebView Usage — EZSwiftExtensionsTests/BlockWebViewTests.swift (implies WebView extensions in main codebase). BlockWebViewTests.swift suggests custom WebView extensions. UIWebView is deprecated and known to have security vulnerabilities. If UIWebView is used instead of WKWebView, this poses a security risk. Fix: Ensure all WebView extensions use WKWebView instead of the deprecated UIWebView. Validate that content loading uses secure configurations and proper URL validation.
  • Low · Sensitive Image Asset in Repository — EZSwiftExtensions/charizard.jpg. A binary image file (charizard.jpg) is committed to the repository. While this appears to be a test/example asset, storing large binary files in version control can lead to repository bloat and potential exposure if sensitive images are accidentally included. Fix: Move binary assets to a separate asset management system or CDN. Use .gitignore to prevent accidental commits of large binary files. Consider using Git LFS for necessary assets.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · Esqarrouth/EZSwiftExtensions — RepoPilot