use of extensions in Swift - swift

I am looking at some sample code from some Apple Developer sample projects and I see this pattern repeating quite a few times.
So there is a view controller...
class CameraViewController: UIViewController {
}
and then there is always some extension to that as something like:
extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
...
}
I am wondering why it is done like this? Is this to allow reusability of the initial defined classes or is there some other reason?

If it's in the same file, it's just for code organization purposes. It's convenient to keep methods together that relate to a specific protocol. It's a good reminder not to change the names of those methods, and it makes clear why a method might seem never to be called (since it's called from Apple code, for example).
If it's in another file, it's sometimes to simplify code-reuse, particularly if a very general-purpose type is conformed to a very app-specific protocol. But even in that case, it may just be for organizational purposes, to make files smaller, or just to express that you consider this to be non-core functionality.
But broadly, extensions are a very common and general-purpose tool that you can use whenever you find them convenient and meaningful.

Contributing to the answer, this is to better organize your projects, and not having such a ViewController:
extension CameraViewController: AVCaptureVideoDataOutputSampleBufferDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, CLLocationManagerDelegate, ... {
...
}
Not only making use of Apple protocols but also organizing your methods into extensions.
For example, I organized my main ViewController with view creation methods to code, something like this:
extension MainViewController {
private func createView() {
...
}
private func configureConstraints() {
...
}
}

Related

When and why would i use Protocols in Swift?

So I came across the subject of protocols and I have searched the internet a bunch for an answer but I couldn't find one, atleast one that solved my problem.
So I understand that Protocols are a "blueprint" of methods, properties and such and that it can be implemented in a class or struct and that it needs to conform to its requirements and such, but why would one use one?
I mean you could also just create a function inside a struct itself. It seems a bit of a hassle to write a protocol and then for the implementation of said protocol you would have to write all the requirements again with more code this time.
Is there a particular reason why one would use a protocol? Is it for safety of your code or some other reason?
For example:
In swift you have the CustomStringConvertible protocol which has a required computed property to control how custom types are represented as a printable String value, but you could also create a function inside your class which could solve this issue aswel. You could even have computed property which does the same as this protocol without even implementing this protocol.
So if someone could please shed some light onto this subject, that would be great.
Thank you in advance!
but why would one use one?
Protocols in swift are similar to Abstractions in some other languages.
before answering your question, we have to clear things out, Protocols declaration could be various but considering you have already read tons of it,
It will also be great to mention this answer here.
Now lets get into the real use case here.
Consider you have this protocol.
protocol Printable {
var name: String { get }
}
Now we need some type of structs or classes to confirm to it, or Multiple ones.
And here where it lays one of the biggest benefit of it.
Consider you have to print the name propriety of an objects.
For example those.
struct Human {
var name: String
}
struct Animal {
var name: String
}
You would simply type this without Protocols
func printOut(human: Human){
human.name
}
func printOut(animal: Animal){
animal.name
}
Which is correct, now observe the code below using protocol Printable.
struct Human: Printable {
var name: String
}
struct Animal: Printable {
var name: String
}
func printOut(object: Printable){
print(object.name)
}
It only takes us one func and so on using the Protocols.
Conclusion
Protocols used to minimize the unnecessary chunks of code.
It's name represent the effect applied on the confirm party.
Protocols can be injected as parameters types.
You can also read more about them here.
And more about the use cases here.
Protocol in swift is a pattern for allowing your classes to confirm to particular set of rules.
In other words a protocol is a blueprint of methods and properties that are necessary for a particular task.
You implement a protocol by confirming to it. If your class miss implementation of any method defined in the protocol, swift compiler tells you.
As an example lets consider that you want to make a Car class. Now there are particular requirements for a car. Like it has wheels, a trunk, etc. Each requirement can be defined as a protocol that is then implemented by the Car class. If your class don't have a trunk, you just drop the implementation.
Protocol oriented programming is a new programming paradigm. That solves some problems incurred by object oriented programming. Like multiple inheritance. Swift doesn't allow multiple inheritance but it allows confirmation to multiple protocols.
It's very easy to remove some functionality from a class in Protocol oriented programming. You just stop conforming to it. Comparative to OOP its very easy to do such things in POP.
The concept of the protocol is very simple: it's nothing more than a promise that specific methods and/or properties will exist in whatever object has taken on that protocol. And so we use them for typing and type safety.
Imagine creating a custom control, like an action sheet:
class CustomActionSheet: UIControl {
func userTappedOnSomething() {
// user tapped on something
}
}
...and you implemented it in one of your view controllers.
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
}
}
This isn't much use without allowing the action sheet to communicate with the view controller when the user taps on a button. So we use a delegate:
class CustomActionSheet: UIControl {
weak var delegate: UIViewController?
func userTappedOnSomething() {
delegate?.userTookAction()
}
}
class SomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
actionSheet.delegate = self
}
func userTookAction() {
// update the UI
}
}
Now when the user taps on a button in the action sheet, the view controller underneath can update its UI. But this actually won't compile. You will get an error that UIViewController has no member userTookAction. That is because the UIViewController class doesn't have a method called userTookAction, only this instance of the view controller does. So we use a protocol:
protocol ActionSheetProtocol: AnyObject {
func userTookAction()
}
This protocol says that whatever object that conforms to it must include this method. So we change the action sheet's delegate to be of that protocol type and we conform the view controller to that protocol since it has such method:
class CustomActionSheet: UIControl {
weak var delegate: ActionSheetProtocol?
func userTappedOnSomething() {
delegate?.userTookAction()
}
}
class SomeViewController: UIViewController, ActionSheetProtocol {
override func viewDidLoad() {
super.viewDidLoad()
let actionSheet = CustomActionSheet()
actionSheet.delegate = self
}
func userTookAction() {
// update the UI
}
}
This is a classic example of protocol use in Swift and once you understand it, you will learn how to get crafty with protocols and use them in very clever ways. But no matter how you use them, the concept remains: promises that things will exist.
Note: In this example, I named the protocol ActionSheetProtocol, because to someone learning protocols, it makes the most sense. However, in the Swift world, in today's practice, most programmers (including the guys at Apple) would name it ActionSheetDelegate. This can be confusing for someone learning protocols so in this example I tried to make it as clear as possible. I personally don't like naming protocols delegates but there’s a lot of things I don’t like.
Note 2: I also made the protocol of type AnyObject which is Swift's syntax for making the protocol a class protocol. Not all protocols need to be of type AnyObject.

Non-'#objc' method does not satisfy optional requirement of '#objc' protocol

Overview:
I have a protocol P1 which provides a default implementation of one of the Objective-C optional functions.
When I provide a default implementation of the optional function there is a warning
Compiler Warning:
Non-'#objc' method 'presentationController(_:viewControllerForAdaptivePresentationStyle:)' does not satisfy optional requirement of '#objc' protocol 'UIAdaptivePresentationControllerDelegate'
Version:
Swift: 3
Xcode: 8 (public release)
Attempts made:
Tried adding #objc but doesn't help
Question:
How do I resolved this ?
Is there a work around ?
Code:
#objc protocol P1 : UIAdaptivePresentationControllerDelegate {
}
extension P1 where Self : UIViewController {
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return UIViewController()
}
}
class A : UIViewController, P1 {
}
While I think I can answer your question, it's not an answer you will like.
TL;DR: #objc functions may not currently be in protocol extensions. You could create a base class instead, though that's not an ideal solution.
Protocol Extensions and Objective-C
First, this question/answer (Can Swift Method Defined on Extensions on Protocols Accessed in Objective-c) seems to suggest that because of the way protocol extensions are dispatched under the hood, methods declared in protocol extensions are not visible to the objc_msgSend() function, and therefore are not visible to Objective-C code. Since the method you are trying to define in your extension needs to be visible to Objective-C (so UIKit can use it), it yells at you for not including #objc, but once you do include it, it yells at you because #objc is not allowed in protocol extensions. This is probably because protocol extensions are not currently able to be visible to Objective-C.
We can also see that the error message once we add #objc states "#objc can only be used with members of classes, #objc protocols, and concrete extensions of classes." This is not a class; an extension to an #objc protocol is not the same as being in the protocol definition itself (i.e. in requirements), and the word "concrete" would suggest that a protocol extension does not count as a concrete class extension.
Workaround
Unfortunately, this pretty much completely prevents you from using protocol extensions when the default implementations must be visible to Objective-C frameworks. At first, I thought perhaps #objc was not allowed in your protocol extension because the Swift Compiler could not guarantee that conforming types would be classes (even though you have specifically specified UIViewController). So I put a class requirement on P1. This did not work.
Perhaps the only workaround is to simply use a base class instead of a protocol here, but this is obviously not completely ideal because a class may only have a single base class but conform to multiple protocols.
If you choose to go this route, please take this question (Swift 3 ObjC Optional Protocol Method Not Called in Subclass) into account. It appears that another current issue in Swift 3 is that subclasses do not automatically inherit the optional protocol requirement implementations of their superclass. The answer to that questions uses a special adaption of #objc to get around it.
Reporting the Issue
I think this is being discussed already among those working on the Swift open source projects, but you could be sure they are aware by either using Apple's Bug Reporter, which would likely eventually make its way to the Swift Core Team, or Swift's bug reporter. Either of these may find your bug too broad or already known, however. The Swift team may also consider what you are looking for to be a new language feature, in which case you should first check out the mailing lists.
Update
In December 2016, this issue was reported to the Swift community. The issue is still marked as open with a medium priority, but the following comment was added:
This is intended. There is no way to add the implementation of the method to every adopter, since the extension could be added after the conformance to the protocol. I suppose we could allow it if the extension is in the same module as the protocol, though.
Since your protocol is in the same module as your extension, however, you may be able to do this in a future version of Swift.
Update 2
In February 2017, this issue was officially closed as "Won't Do" by one of the Swift Core Team members with the following message:
This is intentional: protocol extensions cannot introduce #objc entry points due to limitations of the Objective-C runtime. If you want to add #objc entry points to NSObject, extend NSObject.
Extending NSObject or even UIViewController will not accomplish exactly what you want, but it unfortunately does not look like it will become possible.
In the (very) long-term future, we may be able to eliminate reliance on #objc methods entirely, but that time will likely not come anytime soon since Cocoa frameworks are not currently written in Swift (and cannot be until it has a stable ABI).
Update 3
As of Fall 2019, this is becoming less of a problem because more and more Apple frameworks are being written in Swift. For example, if you use SwiftUI instead of UIKit, you sidestep the problem entirely because #objc would never be necessary when referring to a SwiftUI method.
Apple frameworks written in Swift include:
SwiftUI
RealityKit
Combine
CryptoKit
One would expect this pattern to continue over time now that Swift is officially ABI and module stable as of Swift 5.0 and 5.1, respectively.
I just ran into this after enabling 'module stability' (turning on 'Build libraries for distribution') in a swift framework I use.
What I had was something like this:
class AwesomeClass: LessAwesomeClass {
...
}
extension AwesomeClass: GreatDelegate {
func niceDelegateFunc() {
}
}
The function in the extension had these errors:
'#objc' instance method in extension of subclass of 'LessAwesomeClass' requires iOS 13.0.0
Non-'#objc' method 'niceDelegateFunc' does not satisfy requirement of '#objc' protocol 'GreatDelegate'
Moving the functions into the class rather than in an extension resolved the issue.
Here's another workaround. I ran into this issue as well, and cannot switch from UIKit to SwiftUI yet. Moving the default implementations into a common base class was not an option for me either. My default implementations were quite extensive so I really did not want to have all that code duplicated. The workaround I ended up using was to use wrapper functions in the protocol, and then simply call those functions from each class. Not pretty, but may be better than the alternative, depending on the situation. Your code would then look something like this:
#objc protocol P1 : UIAdaptivePresentationControllerDelegate {
}
extension P1 where Self : UIViewController {
func wrapPresentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return UIViewController()
}
}
class A : UIViewController, P1 {
func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
return wrapPresentationController(controller, viewControllerForAdaptivePresentationStyle: style)
}
}

Understanding Swift extension usage in your API design [duplicate]

This question already has an answer here:
Extensions in my own custom class
(1 answer)
Closed 6 years ago.
The Alamofire API has extensions such as extension Request in ResponseSerialization.swift. When designing a Swift API why would you take this approach as opposed to just adding these methods to the Request class (Request.swift)?
I understand the use of extensions to extend API's when you don't control the source. This question is about using them to extend your own API.
For cleanliness or adding functionality to other classes you didn't create (i.e. extension UIColor). You can create separate extensions to add in separate bits of functionality.
For example, if you have a UIViewController and you add a table view to it's view, instead of making the declaration of ViewController look like this:
class ViewController : UIViewController, UITableViewDataSource, UITableViewDelegate
you could separate it all with extensions so you don't clutter your ViewController file.
Like so:
extension ViewController : UITableViewDataSource, UITableViewDelegate
which you could separate from the main body of the ViewController class or extract into a new file.
Extensions are one of the best features of Swift programming language and there are several use cases for them. Once you hold a grip of them you can come up with some really good and understandable code. Some of the use cases are:
1. Extending system types
With Swift you can any system type like Int or String to make some code more readable and to get some more functionality you would otherwise have to write on your own. For example, check out following code that repeats some task a number of times:
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
}
Instead of creating separate function for task repetition and managing several parameters you can just extend Int and make it more readable:
3.repetitions({
print("Hello!")
})
// Hello!
// Hello!
// Hello!
Everybody can agree that this is the simplest and cleanest code you can ever create.
2. Make messy code readable
Check the following definition:
class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, CLLocationManagerDelegate {
// a lot of functions
}
If you put everything inside one class or structure, code will get messy at one point and it'll be hard to track which method belongs to which protocol or class. Instead you should be using this:
class MyTableViewController: UIViewController {
}
extension MyTableViewController: UITableViewDelegate {
}
extension MyTableViewController: UITableViewDataSource {
}
// etc...
3. Protocol extensions
Protocol extension are one of the coolest features of Swift. They enable adding methods to any class that adopts the protocol you are extending. For example let's extend CollectionType protocol.
extension CollectionType {
func printAll() {
print(self)
}
}
Now you can use method printAll() on any structure that adopt this protocol! Some of them are native Swift types like Array, Dictionary or Set.
These are just some of the main usages of extensions and they can do a lot more:
Add computed instance properties and computed type properties
Define instance methods and type methods
Provide new initializers
Define subscripts
Define and use new nested types
Make an existing type conform to a protocol

Using extensions for protocol conformance when superclass also conforms

In Swift, a general best practice has come about to place protocol conformance for a class into a separate extension. This helps separate out code into logical sections:
class SuperClass: UIViewController {
...
}
extension SuperClass: UITableViewDelegate {
...
}
However, in an app I am currently working on, a base superclass and subclass both need to provide methods for UITableViewDelegate.
To logically separate the code, one would think to do:
class Subclass: SuperClass {
...
}
extension Subclass: UITableViewDelegate {
...
}
However, Swift complains that the class already conforms to the protocol. At the moment, I have simply removed the : UITableViewDelegate part of the extension.
This seems to be a bit of a caveat of using this best practice. Are there any better ways of organising code in this case?

Swift and using class extension

I don't understand why programmers use the extension keyword in their class implementation. You can read in other topics that code is then more semantically separated and etc. But when I work with my own code, it feels clearer to me to use // MARK - Something. Then when you use methods list (ctrl+6) in Xcode, everything is seen at first look.
In Apple documentation you can read:
“Extensions add new functionality to an existing class, structure, or enumeration type.”
So why not write my own code directly inside my own class? Unlike when I want to extend functionality of some foreign class, like NSURLSession or Dictionary, where you have to use extensions.
Mattt Thompson use extension in his Alamofire library, maybe he can give me little explanation, why he chose this approach.
For me it seems completely reasonable since you can use extensions to expose different parts of logic to different extensions. This can also be used to make class conformance to protocols more readable, for instance
class ViewController: UIViewController {
...
}
extension ViewController: UITableViewDelegate {
...
}
extension ViewController: UITableViewDataSource {
...
}
extension ViewController: UITextFieldDelegate {
...
}
Protocol methods are separated in different extensions for clarity, this seems to be far better to read than lets say:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}
So, I'd say there's no harm in using extensions to make your own code more readable, not just to extend already existing classes from SDK. Using extensions you can avoid having huge chunks of code in your controllers and split functionality into easily readable parts, so there's no disadvantage of using those.
Using extensions allows you to keep your declaration of protocol conformance next to the methods that implement that protocol.
If there were no extensions, imagine declaring your type as:
struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {
// lotsa code...
// and here we find the implementation of ArrayLiteralConvertible
/// Create an instance containing `elements`.
init(arrayLiteral elements: T…) {
etc
}
}
Contrast this with using extensions, where you bundle together the implementation of the protocols with those specific methods that implement it:
struct Queue<T> {
// here go the basics of queue - the essential member variables,
// maybe the enqueue and dequeue methods
}
extension SequenceType {
// here go just the specifics of what you need for a sequence type
typealias Generator = GeneratorOf<T>
func generate() -> Generator {
return GeneratorOf {
// etc.
}
}
}
extension Queue: ArrayLiteralConvertible {
init(arrayLiteral elements: T...) {
// etc.
}
}
Yes, you can mark your protocol implementations with // MARK (and bear in mind, you can combine both techniques), but you would still be split across the top of the file, where the declaration of protocol support would be, and the body of the file, where your implementation is.
Also, bear in mind if you’re implementing a protocol, you will get helpful (if slightly verbose) feedback from the IDE as you go, telling you what you’ve got left to implement. Using extensions to do each protocol one by one makes it (for me) far easier than doing it all in one go (or hopping back and forth from top to bottom as you add them).
Given this, it’s then natural to group other, non-protocol but related methods into extensions as well.
I actually find it frustrating occasionally when you can’t do this. For example,
extension Queue: CollectionType {
// amongst other things, subscript get:
subscript(idx: Index) -> T {
// etc
}
}
// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
// this is not valid - you’re redeclaring subscript(Index)
subscript(idx: Int) -> T {
// and this is not valid - you must declare
// a get when you declare a set
set(val) {
// etc
}
}
}
So you have to implement both within the same extension.