Hello there 👋🏻

Welcome to my blog about mobile applications development (mainly for Apple platforms).

➡️ Expect to read here about automated tests (unit, snapshot, UI), FRP, SwiftUI and many other topics that will improve your day to day coding. 🧑‍💻

➡️ I’m here not only to share, but also to learn. If you have any suggestion how I can improve my writting, feel free to reach me! 🤙

➡️ My name is Maciej and I’m going to be your guide through the world of mobile applications development. 🚀

📚 Enjoy the reading! 📚

Will enter foreground or won't?

Will enter foreground or won't?

Intro All across iOS dev blogs and posts you read about AppDelegate being deprecated in the next major iOS release. AppDelegate has been a go-to for app lifecycle handling since iOS 2. From iOS 13, SceneDelegate lives alongside AppDelegate handling per-scene lifecycle. Do the methods applicationWillEnterForeground and sceneWillEnterForeground actually behave the same? Difference 1 - App-wide vs per-scene calls AppDelegate’s will enter foreground Fires once when the entire app moves from background to foreground SceneDelegate’s will enter foreground Fires once per scene as each one enters foreground This behaviour is reflected in each method’s signature (look on arguments) ⤵️ ...

June 3, 2025 Â· 2 min Â· Maciej Gomolka
Turning Singleton Usage into Testable Code

Turning Singleton Usage into Testable Code

See how you can wrap any singleton behind a protocol to make it injectable and your code fully testable 💯 The blog post shows how to deal with URLSession.shared usage. The same strategy can be applied to all other singletons in your code! The problem Service uses URLSession.shared directly. Tight coupling makes unit testing impossible without real network calls. struct PostsAPISerivce { func fetchPosts() async throws -> [Post] { let url = URL(string: ".../posts")! let (data, _) = try await URLSession.shared.data(from: url) return try JSONDecoder().decode([Post].self, from: data) } } In the sections, you’ll get step-by-step guide of making this service testable. These same steps can be applied to all other singletons found in your code. ...

May 27, 2025 Â· 2 min Â· Maciej Gomolka
Swift Concurrency Riddle - TaskLocal

Swift Concurrency Riddle - TaskLocal

Intro If you’re able to solve this, it means you understand TaskLocal really well. Riddle Look at the attached code snippet and guess: What will be printed at each step? Is the order of prints always the same? class Riddler { @TaskLocal static var message = "Hello" static func riddleMe() { Self.$message .withValue("Bye", operation: { print("Print 1: \(Self.message)") // ??? Task { print("Print 2: \(Self.message)") // ??? } Task.detached { print("Print 3: \(Self.message)") // ??? } }) print("Print 4: \(Self.message)") // ??? } } Riddler.riddleMe() Hint Do you want to learn more about TaskLocal and Test Scoping in Swift 6.1 first? - Check out my blog post on “Concurrency-Safe Testing in Swift 6.1 with TaskLocal and Test Scoping” HERE. ...

May 17, 2025 Â· 2 min Â· Maciej Gomolka
Concurrency-Safe Testing in Swift 6.1 with @TaskLocal and Test Scoping

Concurrency-Safe Testing in Swift 6.1 with @TaskLocal and Test Scoping

Today’s example shows a static property providing the current date. Perfect mechanism when we don’t want to inject it everywhere where it’s used. How to test it? Check it out ⤵️ Initial setup let currentDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .none return formatter }() var currentDateFormatted: String { currentDateFormatter.string(from: DateEnvironment.currentDate()) } enum DateEnvironment { static var currentDate: () -> Date = Date.init } extension Date { // 16.04.2025 static let sixteenthOfApril = Date(timeIntervalSince1970: 1744840515) } Old way - XCTest Override the static property in tests. Works, but not concurrency-safe (Ok, for XCTest because test ran serially). class CurrentDateFormatterTests: XCTestCase { func test_dateFormatting() { // ✅ DateEnvironment.currentDate = { .sixteenthOfApril } XCTAssertEqual(currentDateFormatted, "16.04.2025") } } Swift Testing before Swift 6.1 enum DateEnvironment { @TaskLocal static var currentDate: () -> Date = Date.init } struct CurrentDateFormatterTests { @Test func dateFormatting() { // ✅ DateEnvironment.$currentDate .withValue({ .sixteenthOfApril }) { #expect(currentDateFormatted == "16.04.2025") } } } Why @TaskLocal? ...

May 7, 2025 Â· 2 min Â· Maciej Gomolka
3 Ways to Name Parameters in Swift Parametrised Tests

3 Ways to Name Parameters in Swift Parametrised Tests

Mind your argument names in Swift Testing’s parametrised tests! As a follow up to my recent post on refactoring to use Swift Testing’s parametrised tests, I’m diving into the crucial - yet often overlooked topic of how to name your parametrised test inputs. Option 1: First Named Tuples Only the first tuple is named, all others rely on positional matching to (a, b, result). ✅ Minimal boilerplate for small input sets ❌ Readability drops after adding more cases ❌ Easy to mix up arguments position ❌ Hard to scan or extend func add(_ a: Int, _ b: Int) -> Int { a + b } ... @Test(arguments: [ (a: 1, b: 2, result: 3), (10, 15, 25), (1, -5, -4), (-1, -5, -6), (0, 0, 0), (1000, 1000, 2000), (10000, 50000, 60000), (-10, -3, -13) ]) func add_returnsCorrectSum(a: Int, b: Int, result: Int) { #expect(add(a, b) == result) } Option 2: Named Tuples Every tuple entry explicitly names all its fields (a: …, b: …, result: …) for all cases. ...

April 24, 2025 Â· 3 min Â· Maciej Gomolka