Swift: Demystifying Parameter Names In Functions

UPDATE: Read a more in-depth look at Swift functions in my objc.io article – The Many Faces of Swift Functions.

One of the frustrating things I’ve encountered with Swift is how to work with parameter names in functions. Sometimes the parameter name is required and sometimes it’s not. As an Objective-C developer, I LOVE having parameter names very explicitly present – I like how readable it makes the code.

Here is an example I’m talking about:

Swift TableView

Notice how the UITableView initialization requires the frame parameter name, and the CGRect initialization requires the x, y, width, and height parameter names. But the dequeueReusableCellWithIdentifier method does NOT require the identifier parameter. In fact, if I tried to include the identifier parameter name, I would get an error prompting me to delete the parameter name:

And, of course, sometimes methods require one parameter name but not the other:

TableviewInsert swift

Notice that the inserRowsAtIndexPaths:withRowAnimation: method does NOT require the first parameter name (indexPaths), but does require the second one (withRowAnimation:).

So I decided to investigate a bit to make sure I got the rules down for when I write my own classes and methods. Here is what I found:

Init

When you create a Swift class, you have to implement the init() function, where you can pass in as many parameters as you want. All the parameter names you include in the init function will require the parameter name labels when instantiating the function:

Init Function Swift

This holds true for initializing your favorite Objective-C and C objects as well:

Objective-C in Swift Init

Notice how CGRectMake and CGPointMake C functions are no longer required to instantiate a CGRect and CGPoint! Of course, you can still use these, but they’re definitely not as readable:

Just like with CGRectMake and CGPointMake, your favorite Objective-C class can still be initialized with the old initializers in some cases…

However, most of the old-style initializers are being deprecated, so I recommend using the new initializer syntax to be Swifty 🙂

Your Functions

If you write your own function similar to how you wrote the init function, you will end up with something like this:

Swift Function

Well, you may or may not be surprised and / or frustrated to find out that when you call your function, the parameter label is not required:

legolandgreeting swift function

In fact, you’ll get an error if you try to include the name parameter label, and a pop up will prompt you to “fix it” by deleting the name label:

Name

As an Objective-C developer, I’m pretty annoyed that requiring the parameter label is not the default. From working with the iOS APIs in Swift for the past month, this seems to be some kind of relic from the Objective-C way of naming methods…

Objective-C Functions

Notice, that according to the Objective-C naming convention, the parameter name is part of the function name, so it’s repetitive to require a parameter label so that, for example, mutableArray.objectAtIndex(0) will actually be mutableArray.objectAtIndex(index: 0).

In Swift, we can separate the function name from the parameter name very smoothly. But if we do that, we need to require the parameter label. There are two ways of doing this:

Rename Your Param

You can add a different name for your param internally to the function:

Swift Param Second Name

As you can see, the parameter name label is now required when calling this function.

I’m not sure about you, but I can’t think of one use case where I’d want to have a different name for my parameter internally in my function than the one I use to pass in the parameter value. I also find this syntax pretty confusing to read. If you have a good use case for this, I’d love to hear about it in the comments!

Otherwise, I highly recommend following the other way of doing this:

Hashtag It

Just add a hashtag in front of you parameter name, and it’ll be required!

Swift Param Name

Make sure to add the hashtag to every single parameter name in your function, or otherwise some parameter names will not be required!

Swift Multiple Params

As you can see, when I didn’t put a hashtag in front of the wiseOne parameter name, it was not required when calling the function. I personally think that’s a bad way of doing things, so hopefully Swift will change to accommodate an easier way to include parameter names by default. Meanwhile, make sure to always use hashtags in your function parameter names!

Default Values

One of the cool things I’m personally excited about in Swift is the ability to set default values in your function. To set the default value, simple set the parameter equal to your default value:

To use a default value, you have to make sure that all other parameter names are required – put a hashtag in front of all of them! Oh yeah, and it’ll give you a warning about the hashtag in front of the parameter with the default value – so remove the hashtag from it… (yes, it’s that complicated!).

Swift Default Values

Now, when calling this method, you can choose to skip the parameter with the default value:

As you can see, naming your function in Swift while keeping the parameter names required can get pretty complicated. Keep in mind that this post is written as of beta 3, so there might be changes in the future (hopefully!).

Have you noticed anything cool about functions and parameter in Swift? I’d love to hear about it in the comments!

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • Excellent post. The ability to rename parameters appears to be largely to get around differences in naming and syntax between Swift methods and Objective-C ones, e.g.

    SWIFT

    init(string aString: String!)

    OBJECTIVE-C

    – (instancetype)initWithString:(NSString *)aString

    which will mean that the method internals won’t change in terms of what they are referencing, but I agree that when writing Swift from scratch that there won’t be much use for it.

    Mainly it’s part of the criss-crossing of the two languages.

    For example, as I’m sure you know, @objc() enables a method to have a different name when called from Objective-C files. And further when you write:

    init(string:String) {

    }

    This is automatically translated into initWithString in Objective-C without even using @objc().

    • Not a fan of the underscore syntax – find it super confusing, so didn’t include it. Maybe I’ll get used to it if everyone adopts it?

      • I can understand why, although there is a logic that underscore always means an omission.

        for value in array { }
        // value is the value of each value in the array, worked through successively

        for _ in array { }
        // _ is the omission of each value in the array, worked through successively

        init (integer int:Int) {}
        // integer is used in place of int when called

        init (_ int:Int) {}

        // _ is the omission of a name in place of int

        • Getting around to the underscore as I’m seeing it more 🙂 Will write a separate post about it.

  • Awesome post. I was thoroughly confused with the sometimes required and sometimes not. And it didn’t help that autocomplete was not letting me write what I wanted and kept insert garbage.

    I think we should submit a bug on it, because it’s not obvious and different API’s work differently, which makes it super confusing to learn.

    • I just posted rdar://17735653 “Swift Method Parameter Names are Not Required, Illegal, and Inconsistent”

  • That’s a really amazing assortments of dos and donts, doables and not-dobables with Swift Function Parameters.
    I also wrote two articles on Swift Function Parameters. Would be glad if you check them out: http://uvassociates.in/ios-dev/swift-functions-default-inout-external-shorthand-variable-parameters

  • Andreas

    The Swift rules for the default behavior for named parameters are unnecessarily complex. Making the rules consistent (or even the same) for procedural functions and method functions would be a good start.

  • Avalon

    Parameter names are what I don’t get in Swift. I thought they were an old relic in Objective-C. Why have to provide extra names when there are already params that HAVE names? … And just showing these in API Doc help instead?!

  • Craig Grummitt

    It gets even more complicated. Class methods have a different rule again regarding parameter name labels being required or not.
    And the converse of the hashtag # to require a parameter name, is underscore _ to specify NO parameter name. (I see you go into this on another post)
    I’ve summarised the differences here: http://craiggrummitt.wordpress.com/2014/07/28/func-parameters-in-swift/

  • pukeanddie

    I was just writing a protocol method for a delegate and remembered your comment regarding why someone would ever need a public parameter name to be different from what was used internally. I think there are times when it’s great to have a descriptive method signature, without having to use unwieldy variable names internally. So.. for example in my loadService delegate protocol I have the following:

    func loadService(service:SomeLoadService, didEncounterNonFatalErrorWithDescription description:String)

    • Drew Cover

      Exactly. It is most important that the parameters make sense to the client classes. But this allows the method writer to name it something that makes sense to the implementation, which should be hidden from the client.

  • António Pinho

    Any updates for Swift 2.0 :D?

  • Adam Waite

    Swift 2 got rid of the hashtag thing, just duplicate the first parameter name from now e.g `func random(min min: Int, max: Int)`

  • Hashing is illegal in Swift 2. You may think to update article. Anyway thank you.

    • Thank you! I was confused why the hash does not work when I tried it.

  • Nicolas Manzini

    seems the problem is still there as of today and yes it is a problem not a proper way to do things…

  • Ian Warburton

    “I’m not sure about you, but I can’t think of one use case where I’d want to have a different name for my parameter internally in my function than the one I use to pass in the parameter value.”

    So why did add this wierdness to the language? Can it be used to give consumers of an API a more verbose description of what a parameter is for?