Swift Developer News - Hacking with Swift News, tips, and tutorials from Hacking with Swift https://www.hackingwithswift.com/articles/rss (c)2017 Paul Hudson https://www.hackingwithswift.com/favicon-96x96.png Swift Developer News - Hacking with Swift https://www.hackingwithswift.com/articles/rss Improving your Swift code using value objects https://www.hackingwithswift.com/articles/188/improving-your-swift-code-using-value-objects https://www.hackingwithswift.com/articles/188/improving-your-swift-code-using-value-objects They’re like super-charged value types. Thu, 23 May 2019 19:46:21 +0000 What if I told you that you can write Swift code that’s easier to understand, easier to test, has fewer bugs, and is more secure, all with one simple change?

No, this isn’t a scam, and in fact it’s using a time-tested technique called value objects. These have some similarities with value types but aren’t the same thing as you’ll see. Even better, you’ve already used at least one common type of value object, so hopefully the advantages will be clear pretty quickly.

What is a username?

Take a look at the following example Swift code and see if you spot a commonality:

func authenticate(user: String) { }
func purchase(product: String, quantity: Int) { }
func sendEmail(to recipients: [String]) { }

Yes, one obvious commonality is that all three are functions without any code inside, but there’s something else: all three use primitive types for their parameters.

Primitive types are things like strings, integers, and Booleans. In Swift they are all value types, which means they always have one unique owner rather than being shared, which itself is a great way to reduce complexity in our code. However, does an integer accurately represent the number of products in a purchase? Does a string accurately represent usernames?

The answer is almost certainly no. There’s a good joke by Bill Sempf that goes: “A QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers. Orders a sfdeljknesv.” The point here is that quantities of a product need to fall within a certain range:

  • Negative values don’t make sense.
  • A zero quantity isn’t a purchase.
  • Very large quantities are likely to be invalid – unless you’re a store that sells individual peas!

As for usernames, you can imagine how the start of the authenticate(user:) method might look:

func authenticate(user: String) {
    // make sure usernames are at least three characters
    guard user.trimmingCharacters(in: .whitesp...
]]>
How to use opaque return types in Swift 5.1 https://www.hackingwithswift.com/articles/187/how-to-use-opaque-return-types-in-swift-5-1 https://www.hackingwithswift.com/articles/187/how-to-use-opaque-return-types-in-swift-5-1 Power, flexibility, and encapsulation all rolled into one Fri, 10 May 2019 10:11:53 +0000 Swift 5.1 introduces an important new feature into the language called opaque types – types where we’re told about the capabilities of an object without knowing specifically what kind of object it is. This has come about through SE-0244, which is part of a larger roadmap to improve generic functionality in Swift.

At first glance opaque types sound a lot like protocols, but they take the concept of protocols significantly further because they are able to work with associated types, they require the same type to be used internally each time, and they allow us to hide implementation details.

As an example, if we wanted to launch different kinds of fighters from a Rebel base we might write code like this:

protocol Fighter { }
struct XWing: Fighter { }

func launchFighter() -> Fighter {
    XWing()
}

let red5 = launchFighter()

Note: Swift 5.1 no longer requires the return keyword in single-expression functions, so XWing() is the same as return XWing() – you can read more about that here.

Whoever calls that launchFighter() function knows it will return some sort of Fighter but doesn’t know precisely what. As a result, we could add struct YWing: Fighter { } or other types, and have any of them be returned.

But there’s a problem: what if we wanted to check whether a specific fighter was Red 5? You might think the solution is to make Fighter conform to the Equatable protocol so we can use ==. However, as soon as you do that Swift will throw up a particularly dreaded error for the launchFighter function: “Protocol 'Fighter' can only be used as a generic constraint because it has Self or associated type requirements.”

The “Self” part of that error is what is hitting us here. The Equatable protocol has to compare two instances of itself (“Self”) to see whether they are the same, ...

]]>
Take the Hacking with Swift WWDC19 Quiz https://www.hackingwithswift.com/articles/186/wwdc-quiz https://www.hackingwithswift.com/articles/186/wwdc-quiz Think you know WWDC? Prove it! Thu, 18 Apr 2019 14:20:38 +0000 I'm supposed to be busy working on my 100 Days of Swift, but now that all tickets and scholars have been announced for this year's WWDC I thought it was time to do something special.

Below you'll find a range of questions that test your knowledge of Apple's Worldwide Developer Conference. Share your result on Twitter and see if you beat your friends!