In Swift, what does it mean for protocol to inherit from class keyword? - swift

In Swift, what does it mean for protocol to inherit from class keyword?
e.g.
protocol MyDelegate: class {
}

The gist of Starscream's answer is correct, but it misses the why which I think is important here. It comes down to ARC and memory management.
Swift is a language of reference types and value types. Classes are reference types, while everything else is a value type. Effectively, we're not really specifying that the protocol inherits from class... it's more like we're specifying that the protocol can only be implemented by reference types.
And why is that important?
It's important, because without it, we can't use the weak keyword with the protocol.
protocol ExampleProtocol {}
class DelegatedClass {
weak var delegate: ExampleProtocol?
}
This generates the error:
'weak' cannot be applied to non-class type 'ExampleProtocol'
And why not? Because the weak keyword only makes sense with reference types to which ARC applies. ARC does not apply to value types. And without specifying our protocol with class, we cannot guarantee that our delegate property is set to a reference-type. (And if we don't use weak, we're most likely creating a retain cycle.)

From the Apple docs:
You can limit protocol adoption to class types (and not structures or
enumerations) by adding the class keyword to a protocol’s inheritance
list.
Example:
protocol AProtocol: class {
}
//Following line will produce error: Non-class type 'aStruct' cannot conform to class protocol 'AProtocol'
struct aStruct: AProtocol {
}
The line declaring the structure will spit an error. Following line will produce error:
Non-class type 'aStruct' cannot conform to class protocol 'AProtocol'

Related

How can I get conditional protocol conformance with a protocol's parent?

I have the following setup:
protocol Resource : Codable {}
class A<T> {}
extension A where T : Codable {
func doThingWithCodable() {}
}
let a = A<Resource>()
a.doThingWithCodable()
//Error: Protocol type 'Resource' cannot conform to Codable because
//only concrete types can conform to protocols.
I understand the error message, and I've read numerous Q&A's on generics, protocols and conditional conformance. I have a number of classes that conform to the Resource protocol, so it'd be really convenient if there was a way to let A<Resource> know that it will always be working with concrete types that conform to Codable, so I could still have one instance of A<Resource>, and that instance could have access to its conditional Codable methods. I did think about just making an instance like A<Codable>, but I need some of the properties that are inside the Resource protocol too.
Is there a swifty way to resolve this besides creating a new instance of A for each concrete type that conforms to Resource?
The question as posed, "How can I get conditional protocol conformance with a protocol's parent?" is meaningless, because a protocol always conforms with its parent; there is no "conditional" about it.
As for your actual code, the problem is the phrase A<Resource>. Saying A<Resource> is not a correct resolution of A's T. You need to resolve T as a class, struct, or enum — not as a protocol.
For example, if you have a class B that conforms to Resource, you can declare
let a = A<B>()
and all is well.
if there was a way to let A<Resource> know that it will always be working with concrete types that conform to Codable
Well, as I said, your code compiles fine as soon as A is working with a concrete type that does conform to Codable. So if that's what A will always be working with, there's nothing more to do. You could of course tell A that its T will always conform to Resource (which by definition will always conform to Codable):
class A<T:Resource> {}
Just think about this:
let a = A<Resource>()
This statement is trying to create an instance of class A and assigning it to a. The compiler doesn't know what this resource exactly is and how much memory it should allocate and what optimization it should run; because here Resource can be anything.
To resolve that, you need to provide little more information i.e. which you are already aware of.
struct CoffeeResouce: Resource {
let isWarm: Bool
}
Now when you write this:
let a: A<CoffeeResource> = A()
The compiler is well about the type and it's memory requirements. This is one way of resolving.
Or permanently tell the class that T conform to the protocol by declaring the class.
class A<T: Resource> {}

Why Doesn't The Swift Compiler Detect Properties of Protocols

I am using an NSOperation that conforms to SomeProtocol that has a results property
let op : NSOperation, SomeProtocol = ...
op.completionBlock = {
print(op.results)
}
I get the following error:
Value of type 'NSOperation' has no member 'results'
I know that I can subclass NSOperation to get the intended behaviour, but can I achieve what I want using protocols?
That code shouldn't even get that far... unlike Objective-C, Swift does not allow specifying a variable as a combination of both a concrete type AND a protocol. You can only declare a variable to be of a specific type, a specific protocol, or a composition of protocols, e.g.
let op : protocol<SomeProtocol, AnotherProtocol> = ...
But there is currently no way to declare a variable as being of the specific type NSOperation AND conforming to the protocol SomeProtocol

Array of structs conforming to protocol not recognized

I'm trying to create a method that takes an array of structs that conform to a protocol in Swift.
For the simplest example of this, I define an empty protocol and a method that takes an array of objects conforming to that protocol and just prints them
protocol SomeProtocol {}
func methodTakingProtocol(objects: [SomeProtocol]) {
// do something with the array of objects
print(objects)
}
When I try to feed this method an array of structs that conform to SomeProtocol, however, I get an error
struct SomeStruct: SomeProtocol {}
let arrayOfStructs = [ SomeStruct(), SomeStruct() ]
methodTakingProtocol(arrayOfStructs)
// ^ "Cannot convert value of type '[SomeStruct]' to expected argument type '[SomeProtocol]'"
Poking around a little, I've found that I can get around this problem by explicitly calling out SomeStruct's adoption of SomeProtocol
let arrayOfStructs: [SomeProtocol] = [ SomeStruct(), SomeStruct() ]
// This will work
methodTakingProtocol(arrayOfStructs)
Can someone tell me what's going on here? Is this a bug that I should file a radar for, or is there some reasoning as to why the compiler doesn't recognize this array of structs as conforming to the protocol they have been marked as adopting?
This is actually working as intended. In order to pass the array to the method you have to either cast it or explicitly declare it as the protocol:
protocol SomeProtocol {}
struct SomeStruct: SomeProtocol {}
// explicitly typed
let arrayOfStructs:[SomeProtocol] = [ SomeStruct(), SomeStruct() ]
func foo(bar:[SomeProtocol]) { }
foo(arrayOfStructs) // Works!
Here is an excellent article on this topic: Generic Protocols & Their Shortcomings
But that begs the question; Why can't we use generic protocols outside
of generic constraints?
The short answer is: Swift wants to be type-safe. Couple that with the
fact that it's an ahead-of-time compiled language, and you have a
language that NEEDS to be able to infer a concrete type at anytime
during compilation. I can't stress that enough. At compile time, every
one of your types that aren't function/class constraints need to be
concrete. Associated types within a protocol are abstract. Which means
they aren't concrete. They're fake. And no one likes a fake.
edit: It's still a great article but upon re-reading I realized that it doesn't exactly apply here since we're discussing "concrete protocols" and not "generic protocols".

Define an object to be `Type` of a Class and to implement a protocol [duplicate]

This question already has answers here:
In Swift, how can I declare a variable of a specific type that conforms to one or more protocols?
(5 answers)
Closed 7 years ago.
I need to define a property of a Class to be of Type UIViewController and to implement protocol MyProtocol. In objective-C I can write something like
UIViewController<MyProtocol> myProperty;
I can't find anything on the documentation and so I suppose that this is not possible :/ can you confirm... here is the example code to add some more info
class SignInPresenter {
var myProperty:UIViewController and MyProtocol <--- here is the problem.
You have two choices. You can either use a Generic with type constraints or use protocol extension with type constraints.
In the case of Generics it looks like:
protocol P1 {
}
class X {
}
class Y : X, P1 {
}
class Z<T: X,P1> {
var myProp : T?
}
In the case of protocol extensions, you can use the protocol to provide the required methods and properties and use the extension to implement them for the specific case when the protocol is implemented by the class (e.g. UIViewController). This may be a better option if you don't really need to require UIViewController, but it will be used in practice. I prefer this kind of design as it allows for looser coupling.
First, multiple protocols are defined with a comma. For example,
class SearchResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, APIControllerProtocol
Secondly, variables do not conform to protocols. From Apple's documentation, "A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol."

Use of a Structure instead of a Class in Swift [duplicate]

This question already has answers here:
Why Choose Struct Over Class?
(17 answers)
Closed 7 years ago.
I learn Swift from some time, I know the differences between structure and class. The main difference is structure is of value type and class is of reference type but didn't understand when to use structure instead of a class. Please explain it.
For example, In case of Protocols:
First, We have just a protocol of struct type:
protocol SomeProtocol{
func doSomeStuff()
}
Second, We make protocol of class type like this:
protocol SomeProtocol: class{
func doSomeStuff()
}
So, Please explain me, when we have to use protocol of struct type or of class type.
Firstly structs are passed by value (copied), and a class is passed by reference (copied just the memory address to the object).You may want to use structs for simpler types, because you get a free init for all the properties your struct has.And with protocols, the first one you can use it on class,struct and enum, the second you say that you only use that on classes,and you may want to put class if your protocol is a delegate or a data source,because you want the property(of the type of your protocol) weak to avoid the memory cycle. IMHO use classes for multi-scene apps because you don't need to take care to update value when you edited something in an another scene.
The protocol is not "of struct type" or "of class type", that is wrong terminology.
If you write SomeProtocol: class you make sure only classes can conform to that protocol, structs cannot. If you don't include the class both classes and structs can conform.
The docs (scroll down to "Class-Only Protocols") tell you that
You can limit protocol adoption to class types (and not structures or enumerations) by adding the class keyword to a protocol’s inheritance list. The class keyword must always appear first in a protocol’s inheritance list, before any inherited protocols.
Use a class-only protocol when the behavior defined by that protocol’s requirements assumes or requires that a conforming type has reference semantics rather than value semantics. For more on reference and value semantics, see Structures and Enumerations Are Value Types and Classes Are Reference Types.