Why would we use extensions? - swift

I've just learned about extensions and I was wondering, there was an example about extending a protocol. For example, let's say we have the protocol:
protocol CanFly {
func canFly()
}
which allows all the classes who can fly to basiclly to fly. Now lets say that we use extension to extend the protocol, and we do:
extension CanFly {
func canEat() {
print("I can eat")
}
}
What is the purpose of that if we can just add that func canEat to our protocol? More of those protocols are like an abstract struct so why would we add a func with a body to it?
just wanna say if I've made a mess im sorry for that lol, just want to clear out few things about extension <3

Per Swift documentation on Protocol Extensions:
Protocols can be extended to provide method, initializer, subscript,
and computed property implementations to conforming types. This allows
you to define behavior on protocols themselves, rather than in each
type’s individual conformance or in a global function.
This means you can run logic within the protocol extension function so you don't have to do it in each class that conforms to the protocol.
Personally, I also find extensions useful to extend the functionality of built-in classes like String or UIViewController since extensions can be called from anywhere in an app. I have some open-source extension snippets you can take a look at if you'd like.

Extending a protocol is just one of the possible use cases for extensions, really powerful and useful, but might be confusing at the start.
I suggest you looking through this article, as it dives deeper into more mundane, so to speak, ways to use it.

Related

Why we use Extension? [duplicate]

This question already has answers here:
Swift extension example
(8 answers)
Closed 5 years ago.
As we have Object Oriented Programming, so we can make parent class which have all the functions those are needed for all child classes. so what is the purpose of extensions? I'm little bit confused in that question, please anyone help me.
Extensions
Adds functions to your class without subclassing, is very useful in cases where you don´t have the implementation of the class you are trying to extend, example classes that are inside an Framework or library
as is defined in https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html
Extensions add new functionality to an existing class, structure,
enumeration, or protocol type. This includes the ability to extend
types for which you do not have access to the original source code
(known as retroactive modeling). Extensions are similar to categories
in Objective-C. (Unlike Objective-C categories, Swift extensions do
not have names.)
Extensions in Swift can:
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 In Swift, you can even extend a protocol to
provide implementations of its requirements or add additional
functionality that conforming types can take advantage of. For more
details, see Protocol Extensions.
NOTE
Extensions can add new functionality to a type, but they cannot
override existing functionality.
Extension Syntax
Declare extensions with the extension keyword:
extension SomeType {
// new functionality to add to SomeType goes here
}
An extension can extend an existing type to make it adopt one or more protocols. To
add protocol conformance, you write the protocol names the same way as
you write them for a class or structure:
extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}
Adding protocol conformance in this way is described in Adding
Protocol Conformance with an Extension.
An extension can be used to extend an existing generic type, as
described in Extending a Generic Type. You can also extend a generic
type to conditionally add functionality, as described in Extensions
with a Generic Where Clause.
Hope this help to clarify you

Best practice for using same functions between classes

In swift, what is best practice for having several functions common to more than one class, where inheritance between those classes isn't feasible?
I'm new to programming so please don't condescend. Its just when I first started learning a few months ago I was told its terrible practice to repeat code, and at the time I was coding in Ruby where I could create a module in which all the functions resided, and then just include module in any class where I wanted to use those functions. As long as all variables in the module's functions were declared in the classes the code worked.
Is there a similar practice in swift, or should I be doing something else like making a bunch of global functions and passing the instance variables to those functions? Please be as specific as possible as I'm gonna follow your advice for all code I write in swift going forward, thanks!
simple answer to your question is protocol
define protocol
protocol ProtocolName {
/* common functions */
func echoTestString()
}
extension ProtocolName {
/* default implementation */
func echoTestString() {
print("default string")
}
}
class conforming to protocol with default implementation
class ClassName: ProtocolName {
}
ClassName().echoTestString() // default string
class conforming to protocol with overriden implementation
class AnotherClass: ProtocolName {
func echoTestString() {
print("my string")
}
}
AnotherClass().echoTestString() // my string
While an opinion, I think this is the right route - use a Framework target. Protocols work too. But with a Framework, you can:
Share across projects
Keep everything local in scope what you need or not
Be agnostic in many ways
If you want to use the "include" Swift verb (and all that comes with it), you pretty much need to use a Framework target. If you want complete splitting of code too. Protocols are used when you are within a single project, do not want to "repeat" code pieces, and know you will always be local.
If what you want is to (a) use protocols across projects, (b) include true separate code, (c) have global functions, while (d) passing instance variables... consider a separate target.
EDIT: Looking at your question title ("using same functions") and thinking about OOP versus functional programming, I thought I'd add something that doesn't change my solution but enhances it - functional programming means you can "pass" a function as a parameter. I don't think that's what you were saying, but it's another piece of being Swifty in your coding.

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)
}
}

Is there a difference between Swift 2.0 protocol extensions and Java/C# abstract classes?

With the addition of protocol extensions in Swift 2.0, it seems like protocols have basically become Java/C# abstract classes. The only difference that I can see is that abstract classes limit to single inheritance, whereas a Swift type can conform to any number of protocols.
Is this a correct understanding of protocols in Swift 2.0, or are there other differences?
There are several important differences...
Protocol extensions can work with value types as well as classes.
Value types are structs and enums. For example, you could extend IntegerArithmeticType to add an isPrime property to all integer types (UInt8, Int32, etc). Or you can combine protocol extensions with struct extensions to add the same functionality to multiple existing types — say, adding vector arithmetic support to both CGPoint and CGVector.
Java and C# don't really have user-creatable/extensible "plain old data" types at a language level, so there's not really an analogue here. Swift uses value types a lot — unlike ObjC, C#, and Java, in Swift even collections are copy-on-write value types. This helps to solve a lot of problems about mutability and thread-safety, so making your own value types instead of always using classes can help you write better code. (See Building Better Apps with Value Types in Swift from WWDC15.)
Protocol extensions can be constrained.
For example, you can have an extension that adds methods to CollectionType only when the collection's underlying element type meets some criteria. Here's one that finds the maximum element of a collection — on a collection of numbers or strings, this property shows up, but on a collection of, say, UIViews (which aren't Comparable), this property doesn't exist.
extension CollectionType where Self.Generator.Element: Comparable {
var max: Self.Generator.Element {
var best = self[self.startIndex]
for elt in self {
if elt > best {
best = elt
}
}
return best
}
}
(Hat tip: this example showed up on the excellent NSBlog just today.)
There's some more good examples of constrained protocol extensions in these WWDC15 talks (and probably more, too, but I'm not caught up on videos yet):
Protocol-Oriented Programming in Swift
Swift in Practice
Abstract classes—in whatever language, including ObjC or Swift where they're a coding convention rather than a language feature—work along class inheritance lines, so all subclasses inherit the abstract class functionality whether it makes sense or not.
Protocols can choose static or dynamic dispatch.
This one's more of a head-scratcher, but can be really powerful if used well. Here's a basic example (again from NSBlog):
protocol P {
func a()
}
extension P {
func a() { print("default implementation of A") }
func b() { print("default implementation of B") }
}
struct S: P {
func a() { print("specialized implementation of A") }
func b() { print("specialized implementation of B") }
}
let p: P = S()
p.a() // -> "specialized implementation of A"
p.b() // -> "default implementation of B"
As Apple notes in Protocol-Oriented Programming in Swift, you can use this to choose which functions should be override points that can be customized by clients that adopt a protocol, and which functions should always be standard functionality provided by the protocol.
A type can gain extension functionality from multiple protocols.
As you've noted already, protocol conformance is a form of multiple inheritance. If your type conforms to multiple protocols, and those protocols have extensions, your type gains the features of all extensions whose constraints it meets.
You might be aware of other languages that offer multiple inheritance for classes, where that opens an ugly can of worms because you don't know what can happen if you inherit from multiple classes that have the same members or functions. Swift 2 is a bit better in this regard:
Conflicts between protocol extensions are always resolved in favor of the most constrained extension. So, for example, a method on collections of views always wins over the same-named method on arbitrary collections (which in turn wins over the same-named methods on arbitrary sequences, because CollectionType is a subtype of SequenceType).
Calling an API that's otherwise conflicting is a compile error, not a runtime ambiguity.
Protocols (and extensions) can't create storage.
A protocol definition can require that types adopting the protocol must implement a property:
protocol Named {
var name: String { get } // or { get set } for readwrite
}
A type adopting the protocol can choose whether to implement that as a stored property or a computed property, but either way, the adopting type must declare its implementation the property.
An extension can implement a computed property, but an extension cannot add a stored property. This is true whether it's a protocol extension or an extension of a specific type (class, struct, or enum).
By contrast, a class can add stored properties to be used by a subclass. And while there are no language features in Swift to enforce that a superclass be abstract (that is, you can't make the compiler forbid instance creation), you can always create "abstract" superclasses informally if you want to make use of this ability.

Can I declare functions in Swift and later define their implementation?

Coming from Objective-C, I am very fond of header files which expose the interface of a piece of code. Swift has always bothered me a bit because even the most organized code still tends to bury the public/private API's among the rest of the code, making you dig for details.
Are there any practices or tricks where I can define the public interface of a class or module external to the implementation? Right now I'm just making comments at the top of the Swift file and it feels arcane.
As far as I know you can not just declare a method in a class and implement it at other places in Swift.
I feel you want that for clarity and organizing your methods into class. To achieve that in Swift I follow some techniques that I would be happy to share with you:
Organize methods in groups based on access i.e. public, private and internal. Public methods on top as you want your client to look at them first, then internal and last private.
You may sub organize related methods together for making it easy to understand, maintain and navigate through.
Some time it is good to break above rules to group public and private method if they are related and has heavy dependancies.
You may group related methods that do a specific task in to extensions. I generally follow this pattern for implementing specific protocol or delegate in a class. This you could do in a separate file as well.
This is not direct answer to your question but I have tried to address the core of it by targeting organization of methods in a class.
So I've been exploring the options here and it looks like you can define an interface using a protocol, and having your class conform to that protocol. Kind of out of the way, but if a public interface is the goal, this achieves that.
// Foo.swift
protocol PublicFoo {
func publiclyExposedMethod(arg:AnyObject) -> AnyObject
var publiclyExposedVariable:AnyObject
}
class Foo : PublicFoo {
var publiclyExposedVariable:AnyObject = // something
func publiclyExposedMethod(arg:AnyObject) -> AnyObject {
// do stuff...
}
}