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 Why using isEmpty is faster than checking count == 0 https://www.hackingwithswift.com/articles/181/why-using-isempty-is-faster-than-checking-count-0 https://www.hackingwithswift.com/articles/181/why-using-isempty-is-faster-than-checking-count-0 ...and why you can't read letters from a string using integers. Mon, 04 Mar 2019 16:04:43 +0000 If you want to check that an array, set, string, or other collection type is empty, you might write code like this:

let name = ""

if name.count == 0 {
    print("You're anonymous!")
}

However, that code is better expressed like this:

if name.isEmpty {
    print("You're anonymous!")
}

Using isEmpty is both clearer to read and faster to run.

How Swift strings are built

To understand why isEmpty is faster than count == 0 for strings, we need to dive into how strings work in Swift.

Swift strings are complex collections of characters, where multiple symbols might combine together to a form a single letter visible to users. For example, an emoji as simple as the British flag is actually made up of two distinct characters: “G” and “B”. Not those literal letters, of course, but Unicode symbols that, when put side by side, automatically become the British flag.

You can see this in action in the screenshot below: it stores regional indicator symbol letter G in one string, regional indicator symbol letter B in a second string, and merges them together in a third string. As you can see, individually they are shown as “G” and “B” with a dashed line around them, but together they automatically become the British flag.

Look at the count values for each of those strings – all three are 1. So, from the perspective of raw characters this thing is two characters, but from a user’s perspective it’s just one: the British flag - they don’t want to divide the flag in half by accident. Swift is designed to stop us from breaking up Unicode strings like this by accident, so it also considers emoji to be just one character.

To make things more confusing, behind the scenes each of those special letters “G” and “B” can be represented as two values in UTF-16, or as fo...

]]>
Interview: Antoine van der Lee https://www.hackingwithswift.com/articles/180/interview-antoine-van-der-lee https://www.hackingwithswift.com/articles/180/interview-antoine-van-der-lee We talk testing, mentoring, and the future of Swift Wed, 27 Feb 2019 16:47:02 +0000 Antoine van der Lee is perhaps best known for being one of the tallest iOS devs you’ll ever meet. After that, though, he’s also known for the talks he delivers, his excellent Swift blog, and his work at Dutch digital giant WeTransfer.

As he’s been active on the Swift scene for some years, and a programmer for much longer, I got in touch with Antoine to ask for his views on testing, mentoring, and the future of Swift…

Hacking with Swift: I want to start by asking you about WeTransfer, where you work on the Collect app. This is clearly a huge piece of software – what kind of testing and CI systems do you have in place to make sure you ship a stable app every time?

Antoine van der Lee: Yes, great to start with the thing I work most with! Collect has grown a lot since I started at WeTransfer in 2017, both in terms of users and code. The day I joined it only contained a single UITableView, no CI and no QA in place. This improved over time as I’m a person who constantly seeks for improvements – and luckily enough the whole Collect team is too. That’s also the reason why we started this year with revisiting our QA, CI and release processes.

“Apart from that, we strongly believe in unit tests. Our main app contains 500+ unit tests while our core framework is tested with 1100+ unit tests.”

We now have a so-called release train, which leaves every Monday with the latest green-light build available. We currently use a daily cron job on Travis CI to deliver a daily build using Fastlane. This will also create a draft release on GitHub including our “next version” section from our changelog.md. Our QA team tests the build and turns the draft release into a non-draft release to mark it as a “green-light build”. Our weekly cron job on Monday will pick the latest non-draft release and submits it to Apple for review. It also creates a pull request to update develop with a new changelog.md which will have a clean “...

]]>
Capture lists in Swift: what’s the difference between weak, strong, and unowned references? https://www.hackingwithswift.com/articles/179/capture-lists-in-swift-whats-the-difference-between-weak-strong-and-unowned-references https://www.hackingwithswift.com/articles/179/capture-lists-in-swift-whats-the-difference-between-weak-strong-and-unowned-references Weak vs strong vs unowned – know the difference in closures Wed, 27 Feb 2019 16:15:49 +0000 Capture lists come before a closure’s parameter list in your code, and capture values from the environment as either strong, weak, or unowned. We use them a lot, mainly to avoid strong reference cycles – aka retain cycles.

Deciding which to use isn’t easy when you’re learning, so you can spend time trying to figure out strong vs weak, or weak vs unowned, but as you progress with your learning you’ll start to realize there’s often only one right choice.

First, let’s take a look at the problem. First, here’s a simple class:

class Singer {
    func playSong() {
        print("Shake it off!")
    }
}

Second, here’s a function that creates an instance of Singer, creates a closure that uses the singer’s playSong() method, and returns that closure for us to use elsewhere:

func sing() -> () -> Void {
    let taylor = Singer()

    let singing = {
        taylor.playSong()
        return
    }

    return singing
}

Finally, we can call sing() to get back a function we can call wherever we want to have playSong() printed:

let singFunction = sing()
singFunction()

That will print “Shake it off!” thanks to the call to singFunction().

Strong capturing

Unless you ask for something special, Swift uses strong capturing. This means the closure will capture any external values that are used inside the closure, and make sure they never get destroyed.

Look again at our sing() function:

func sing() -> () -> Void {
    let taylor = Singer()

    let singing = {
        taylor.playSong()
        return
    }

    return singing
}

That taylor constant is made inside the sing() function, so normally it would be destroyed when the function ends. However, it gets used inside the closure, which means Swift will automatically make sure it stays alive for as long as the closure exists somewhere, even after the function has retu...

]]>
Super-powered string interpolation in Swift 5.0 https://www.hackingwithswift.com/articles/178/super-powered-string-interpolation-in-swift-5-0 https://www.hackingwithswift.com/articles/178/super-powered-string-interpolation-in-swift-5-0 Strings get a massive power up in Swift 5.0. Thu, 21 Feb 2019 22:46:24 +0000 String interpolation has been around since the earliest days of Swift, but in Swift 5.0 it’s getting a massive overhaul to make it faster and more powerful.

In this article I want to walk through what’s changing and how to apply it to your own code. You can also download my code for this article here.

The basics

We’re used to basic string interpolation like this:

let age = 38
print("You are \(age)")

We take it for granted these days, but it was a huge quality of life improvement over the syntax we had previously:

[NSString stringWithFormat:@"%ld", (long)unreadCount];

But it’s also an important performance improvement, because the alternative was to write string joining code like this:

let all = s1 + s2 + s3 + s4

Yes, it achieves the same end result, but Swift would have to add s1 to s2 to make s5, add s5 to s3 to make s6, and add s6 to s4 to make s7, before assigning that to all.

String interpolation hasn’t changed much since Swift 1.0, with the only real change coming in Swift 2.1 where we gained the ability to use string literals in interpolations, like this:

print("Hi, \(user ?? "Anonymous")")

Now, as you know Swift Evolution drives Swift forward constantly using ideas from the community. They get discussed, they develop, and they either get accepted or rejected. And this isn't just a once-a-year thing, either. In Swift 4.2 alone, a ton of features were introduced – this was no minor release!

As for Swift 5.0, it's fair to say that ABI stability is the star of the show – it's what developers are most keen to see. But there's so much more, not least raw strings, Result, and isMultiple(of:).

Well, after five years of ...

]]>
It’s time to stop using index(of:) https://www.hackingwithswift.com/articles/177/its-time-to-stop-using-index-of https://www.hackingwithswift.com/articles/177/its-time-to-stop-using-index-of firstIndex(of:) is here to stay. Wed, 20 Feb 2019 22:41:15 +0000 SE-0204 added the lastIndex(of:) and lastIndex(where:) methods to the Swift standard library, while also renaming index(of:) and index(where:) to be firstIndex(of:) and firstIndex(where:) to avoid confusion.

However, even though the first… and last… methods were added as planned in Swift 4.2, index(of:) seems to have snuck under the radar and was left intact and untouched – until now, that is.

As of Swift 5.0, index(of:) and index(where:) have been formally deprecated, which means they will be removed fully at some future point in time. Past experience has shown that Swift is serious about deprecation: you can expect warnings to appear as soon as you upgrade to Xcode 10.2, and for this method to go away completely in the next 12 months or so.

So, get ahead of the game: if you search for “.index” in your code to spot any places where you might be using the old method calls, and look to replace them with the equivalent “firstIndex” call. The functionality is identical, to the point where index(of:) is actually implemented like this:

public func index(of element: Element) -> Index? {
    return firstIndex(of: element)
}

I’m busy going through my original Hacking with Swift book as part of my 100 Days of Swift initiative, and I’m on the hunt for index(…) calls. With around 6000 pages of Swift tutorials it might take a little time, but I’ll get there…

]]>
Xcode tips and tricks – part four https://www.hackingwithswift.com/articles/176/xcode-tips-and-tricks-part-four https://www.hackingwithswift.com/articles/176/xcode-tips-and-tricks-part-four Learn useful Xcode features with short videos. Sat, 09 Feb 2019 21:08:15 +0000 This is part four of a series on Xcode tips and tricks, this time covering testing, debugging, colors, and more!

  1. Xcode tips and tricks – part one
  2. Xcode tips and tricks – part two
  3. Xcode tips and tricks – part three
  4. Xcode tips and tricks – part four

If you have some favorite Xcode tips of your own, let me know on Twitter!

31. Recent files

The two Xcode shortcuts I use by far the most are Ctrl+Cmd+Left and Ctrl+Cmd+Right, which move back and forward between your recently opened files. Bonus: use Ctrl+2 or Ctrl+3 to show these files as a menu you can browse through.

32. Multiple cursors

If you hold down Option and drag over a column of text, you can make edits in multiple places at the same time. Bonus: Ctrl+Shift+Click lets you place new cursors at specific points!

33. View debugging

If you have selected a view in the view debugger, you can press Shift+Cmd+D to highlight it in the debug navigator. You can also type a class name or a view’s label into the filter box to show only matching views.

34. Timing tests

Slow unit tests make it hard to run our tests frequently. Fortunately, Xcode’s Report navigator can ident...

]]>
Advanced coordinators in iOS https://www.hackingwithswift.com/articles/175/advanced-coordinator-pattern-tutorial-ios https://www.hackingwithswift.com/articles/175/advanced-coordinator-pattern-tutorial-ios Child coordinators, navigating backwards, passing data between view controllers, and more. Thu, 07 Feb 2019 12:30:49 +0000 In this article we’ll look at solutions for six common problems people face when adopting the coordinator pattern in iOS apps:

  1. How and when do you use child coordinators?

  2. How do you handle moving back from a navigation controller?

  3. How do you pass data between view controllers?

  4. How do you use tab bar controllers with coordinators?

  5. How do you handle segues?

  6. How do you use protocols or closures instead?

I'll be giving you lots of hands-on code along the way, because I want you to see real-world examples of how these problems are solved.

If you missed my earlier tutorial on the coordinator pattern, you should start there: How to use the coordinator pattern in iOS apps.

 

Prefer video? The screencast below contains everything in this tutorial and more – subscribe to my YouTube channel for more like this.

 

How and when to use child coordinators

We’re going to start off by looking at child coordinators. As I explained in the first article, if you have a larger app you can split off functionality into child coordinators: one responsible for creating an account, one responsible for buying a product, and so on.

These all report back to a parent coordinator, which can then continue the flow once the child coordinator has finished. The end result is that we can split up complicated app functionality into smaller, discrete chunks that are easier to work with and easier to re-use.

But the problem is: when do you use these things, and how is it best done?

Let’s try it out with a real project - we’re going to use the same Coordinators project we had at the end of the first video. We already have a b...

]]>
UIKonf goes all female for 2019 speakers https://www.hackingwithswift.com/articles/174/uikonf-goes-all-female-for-2019-speakers https://www.hackingwithswift.com/articles/174/uikonf-goes-all-female-for-2019-speakers The popular conference in Berlin puts its traditional CFP on hold. Wed, 06 Feb 2019 18:18:22 +0000 UIKonf, one of the largest and best-known independent iOS development conferences, has announced that all speakers in its 2019 edition will be female. This isn’t just random chance: the team have announced it’s their way “of raising awareness for the diversity problem while at the same time a celebration of all the women who follow their passion, muster up the courage to go on stage, and hold great talks despite the headwind they’re facing in our industry.”

As a regular conference speaker, I can testify to the fact that many conferences struggle to attract female speakers, despite using anonymous talk proposals or even specifically inviting particular women. So, I believe UIKonf’s move has the potential to cause serious, positive change in our community.

Although UIKonf has always had a diversity scholarship to support attendees from under-represented groups – last year offering 30 free tickets thanks to sponsorship from Mercedes Benz, for example – this year they are taking it one step further. Following a suggestion from Tobias Due Munk, the conference has opened up a special “Support Diversity Scholarship” ticket that’s helps fund diverse attendance without granting access to the conference. (Full disclosure: I bought one.)

Although the majority of responses seem to be overwhelmingly positive, some folks have argued this may be a bad move from UIKonf: