Overcoming Default Arguments in a Protocol
Overcome the main Swift limitation for protocol
Protocol extensions to the rescue!
This article contains a real example for you that is used in production Apps. Don’t say I don’t spoil you (because I don’t).
Difficulty: Beginner | Easy | Normal | Challenging
Terminology
Extensions: Extensions add new functionality to a class, struct, enum or protocol
The issue
When you use a function, or initialise a class you might well use default arguments.
This is incredibly useful, and I’ve used just such a feature when I’ve created a Network Manager, and this gives a rather handy example for the rest of this article.
Now I want this to work with REST APIs, meaning I would want this to work for GET
, POST
, PUSH
, PUT
, DELETE
and PATCH
— but for some of these you might need to provide data in the body of the request. However for the GET
request we shouldn’t add any data.
So If we create a protocol (which helps to enable good testing, and is the way we should be coding Swift applications after all) as follows:
we will only be able to access fetch if we provide data, and worse a token. But I don’t want to use a token in my reusable Network Layer!
You might try to use default arguments and this would be a good strategy to follow:
which seem a little tricky to me to read as a Gist, so here is another representation of the same code (in a code block!):
func fetch(url: URL, method: HTTPMethod, headers: [String : String], token: String? = nil, data: [String: Any]?, completionBlock: @escaping (Result<Data, Error>) -> Void)
note there is only one small change here — adding = nil
to the token parameter. This gives the following error:
Default argument not permitted in a protocol method
What a disaster! So how can we overcome this issue?
The solution is to use a protocol extension!
Here is the rub — you can add default arguments to a protocol extension!
Here is the full NetworkManagerProtocol protocol, as in the Network Manager class (which gives an example implementation of an extension to implement default arguments in a protocol):
Now this can be accessed through the protocol, where you need to provide a header and a token OR you can do so through the extension (and note that the extension calls the main protocol signature too, and just fills out those default arguments).
Here are two ways you might use these arguments — now isn’t that a little bit awesome?
nil is presented as an option here — but we can slip out those parameters completely to leave us with a very clear and easy to read code snippet:
Conclusion
Due to the way Swift works you can’t add default arguments in a protocol method. This makes quite a few issues, in that we often do want to use a default argument even when we are conforming to a protocol. But there is a way that comes to the result:
You can use them in protocol extensions.
There are quite a number of situations where this might be helpful, and this article has walked you through on of my examples.
Now I hope article has helped you out, and that you are doing OK on your coding journey.
If you’ve any questions, comments or suggestions please hit me up on Twitter