4 min read

Issue #74

Hi there, welcome to the 74th issue of iOS Code Review! Today's issue is another collaboration with J’aime Ohm @omt_conf and Kate Roberts @SaltForMySquid. Welcome back, J'aime and Kate. Enjoy! 👇

Runway: Build the perfect release train 
Release trains are not a silver bullet, but they can help you ship new versions of your app more predictably, reduce risk, get feedback from users faster, and improve collaboration and planning within your team.
Here’s how to build the perfect mobile release train

Xcode and ChatGPT Support


Hot news right now is the announcement of a direct integration between ChatGPT and Xcode (requires ChatGPT subscription).

This means less cut and paste. You can assume it will understand the file context of your question, you can highlight incorrect lines when asking it to make corrections, and you can  ask it to summarize a file. 

To use it, toggle on "Enable Works with Apps" in ChatGPT settings and then select this icon on the ChatGPT bar:

Popover showing a list of applications that can be enabled, including Xcode, TextEdit, Terminal
image source: OpenAI.com

And yes – this does give ChatGPT much deeper access into your code (all open windows) – and you should consider the personal and legal aspects of that. Although 'temporary chat' modes are available, it is nonetheless something that your employer might have an opinion on. 

Xcode + ChatGPT: Official Support is Available Now
Free read for non-members: https://medium.com/@hiandic/dc21998f3653?source=friends_link&sk=e4dfbadcc5281bd474ecd546b221877e
ChatGPT + XCode
Video’s delen met vrienden, familie en de rest van de wereld

Swift Testing: Parameters

If you want to run a single test for a range of different parameters, inject them into the test as an argument with @Test(arguments:). You can inject an array, several arrays, or even zipped arrays - for when the test parameters come in pairs. For example:

@Test(arguments: zip([18, 30, 50, 70], [77.0, 73, 65, 61]))
  func verifyNormalHeartRate(age: Int, bpm: Double) {
    let hr = HeartRate(bpm: bpm)
    let context = HeartRateContext(age: age, activity: .regular, heartRate: hr)
    #expect(context.zone == .normal)
}

If there is a failure, then the Test Navigator will highlight exactly which parameter values are responsible. 

Screenshot of Test Navigator displaying which parameter values passed and which failed
Introducing Swift Testing. Parameterized Tests.
I decided to finalize the topic of the Swift Testing framework with its unique feature called parameterized tests. In a few cases, you need to verify your functions with different inputs, and parameterized tests easily solve this by providing you with a nice overview.

Swift Testing: Traits & Tags

Trait annotation are used to conditionally skip tests based on a feature flag:

// Conditionally skip tests based on a feature flag
@Test(
    .enabled(if: FeatureFlag.addition),
    .enabled(if: FeatureFlag.anotherFlag)
)

Using tags (that you define yourself) lets you run tests by tag and visualize if all the tests in the tag pass:

// Group tests with a custom tag
@Test(.tags(.crucial, .checkout))

extension Tag {
    @Tag static var crucial: Self
Introducing Swift Testing. Traits.
The most powerful feature of the Swift Testing framework is the trait system. Traits allow us to annotate a test or test suite to customize its behavior. This week, we will learn how to use built-in trait types to modify tests.

Swift Testing: Suites

Or why not group your tests using the Suite macro applied to your test class:

// Name your Suite 
@Suite("Serial model tests") 

// Timeout your Suite
@Suite(.timeLimit(.minutes(1)))

// Serialize your Suite
@Suite(.serialized)
Introducing Swift Testing. Lifecycle.
Any function marked with the @Test macro can be a test in the world of the Swift Testing framework. But how do you handle the lifecycle of the tests? How do you define test suites and provide setup and teardown functionality? This week, we will learn how to handle the test lifecycle in Swift Testing framework.

Swift Testing: Require Macro

Let's increase the clarity of your tests by choosing #require to differentiate test pre-requisites from the feature actually being tested.

try #require(person != nil, "Person should exist")

For more examples using #require vs #expect, see SwiftLee and Danny Walls.

Improve Your Search (iOS 12+)

Let's leverage powerful and privacy-focused AI/ML tools that are shipped by Apple – like the Natural Language framework – to offer your users smarter search results.

Working with Natural Language framework
Learn how to use the Natural Language framework to analyze text in real time.

✌️
Alright, that's it for today! Let's spread the good code vibes ✨🧘🌈☀️
You can now use the comment section on the website to share your thoughts. Thank you to Runway for sponsoring this issue and thank you to J'aime and Kate for joining us today!