I have this protocol:
protocol TestProtocol {
func doSomething
}
I would like to use this protocol to ensure some properties are conforming to it like:
class MyClass {
var detailVC : UIViewController <TestProtocol>
}
like good old ObjC to ensure the detailVC conforms to TestProtocol
protocol MyViewControllerProtocol {
func protoFunc()
}
class MyClass {
var prop: MyViewControllerProtocol?
}
It's as simple as that. But if you want a pre-defined class to conform to a protocol, you then need to make an extension (but then this applies to the class as a whole) or you subclass it.
So...
As an extension to the class as a whole:
extension UIViewController: MyProtocol {
func protoFunc() {
print("do whatever")
}
}
In this case, when extended, you can just set the property as:
var myProperty: UIViewController?
As after being extended, it'll conform as required.
Or just subclass it with:
class MyConformingViewController: UIViewController, MyProtocol {
override func protoFunc() {
print("do whatever")
}
}
In this case, you just set the property as:
var myProp: MyConformingViewController?
And that'll automatically confirm to MyProtocol due to the class being set to conform to it.
You can't force a predesignated class to conform to a protocol which wasn't already designated to conform to it in the first place.
e.g. UIViewController wasn't originally set to confirm to MyOtherProtocol for example
That would defeat the object of protocols in the first place. This is why you either extend it to conform, or subclass it to conform.
So you can implement the method like following:
class detailVC : UIViewController, TestProtocol {
func doSomething() {}
}
In Swift you can't have a variable of one type and also declared as a protocol type.
What you can have is a variable that needs conform more than one protocol.
class MyClass {
var detailVC : TestProtocol
}
class MyClass {
var detailVC : protocol<TestProtocol,SecondProtocol>
}
Related
I'm trying to achieve type constraint on protocols. In my current project I have a following base controller. I examined this answer too but I don't understand why it isn't working.
class BaseViewController: UIViewController {
}
I declared two protocol based on my requirements.
protocol A: AnyObject {
func execute()
}
extension A {
func execute() {
print("Execute")
}
}
protocol B {
func confirm()
}
extension B where Self: BaseViewController & A {
func confirm() {
}
}
What I'm trying to achieve is to prevent all classes which doesn't conform protocol A and BaseViewController also can't conform protocol B also.
However, when I try to conform protocol B in another UIViewController which doesn't conform protocol A there is no error.
class AnotherVC: UIViewController {
}
extension AnotherVC: B {
func confirm() {
}
}
How can I restrict other view controllers to conform protocol B if they don't conform protocol A and inherit from BaseViewController
I am not sure if below code is what you need, do let me know if that’s what you were looking for, else I will be happy to remove my answer.
protocol A:BaseViewController {
func execute()
}
protocol B:A {
func confirm()
}
class BaseViewController: UIViewController {
}
class AnotherVC: B {
}
In above code compiler will give error saying-:
'A' requires that 'AnotherVC' inherit from ‘BaseViewController'
Once you inherit AnotherVC from BaseViewController, it will give another error saying-:
Type 'AnotherVC' does not conform to protocol ‘A'
Once you confirm the implementations errors will be resolved-:
class AnotherVC:BaseViewController, B {
func confirm() {
}
func execute() {
}
}
Basically I want to know the difference between this
protocol ViewDelegate: class {
func someFunc()
}
and this
protocol ViewDelegate: NSObjectProtocol {
func someFunc()
}
Is there any difference ??
Only Object or Instance type can conform to both type of protocol, where Structure and Enum can't conform to both the type
But the major difference is:
If one declares a protocol like below means it is inheriting NSObjectProtocol
protocol ViewDelegate: NSObjectProtocol {
func someFunc()
}
if the conforming class is not a child class of NSObject then that class need to have the NSObjectProtocol methods implementation inside it. (Generally, NSObject does conform to NSObjectProtocol)
ex:
class Test1: NSObject, ViewDelegate {
func someFunc() {
}
//no need to have NSObjectProtocol methods here as Test1 is a child class of NSObject
}
class Test2: ViewDelegate {
func someFunc() {
}
//Have to implement NSObjectProtocol methods here
}
If one declare like below, it means only object type can conform to it by implementing its methods. nothing extra.
protocol ViewDelegate: class {
func someFunc()
}
when confirming with class it means we only making in object type. So we can declare it as weak or strong
But when confirming with NSObjectProtocol, we make it object type and also we can implement NSObjectProtocol method. which is already define in NSObjectProtocol delegate.
So its up to you which way you want confirm your delegate
I have setup a protocol to send some information back to the previous VC.
I define it like this:
protocol FilterViewControllerDelegate: class {
func didSearch(Parameters:[String: String]?)
}
But what is the difference when using:
protocol FilterViewControllerDelegate {
func didSearch(Parameters:[String: String]?)
}
And when should I use a : class protocol?
Swift 4 version
AnyObject added to a protocol definition like this
protocol FilterViewControllerDelegate: AnyObject {
func didSearch(parameters:[String: String]?)
}
means that only a class will be able to conform to that protocol.
So given this
protocol FilterViewControllerDelegate: AnyObject {
func didSearch(parameters:[String: String]?)
}
You will be able to write this
class Foo: FilterViewControllerDelegate {
func didSearch(parameters:[String: String]?) { }
}
but NOT this
struct Foo: FilterViewControllerDelegate {
func didSearch(parameters:[String: String]?) { }
}
Swift 3 version
:class added to a protocol definition like this
protocol FilterViewControllerDelegate: class {
func didSearch(Parameters:[String: String]?)
}
means that only a class will be able to conform to that protocol.
So given this
protocol FilterViewControllerDelegate: class {
func didSearch(Parameters:[String: String]?)
}
You will be able to write this
class Foo: FilterViewControllerDelegate {
func didSearch(Parameters:[String: String]?) { }
}
but NOT this
struct Foo: FilterViewControllerDelegate {
func didSearch(Parameters:[String: String]?) { }
}
There's also another thing about marking protocols with the class/AnyObject keyword.
Given a protocol like this:
Swift 4 and above (according to docs):
protocol FilterViewControllerDelegate: AnyObject {
func didSearch(with parameters: [String: String]?)
}
Pre-Swift 4 syntax:
protocol FilterViewControllerDelegate: class {
func didSearch(with parameters: [String: String]?)
}
For example, let's assume that you're creating a DetailViewController with delegate property of FilterViewControllerDelegate type:
class DetailViewController: UIViewController {
weak var delegate: FilterViewControllerDelegate
}
If you didn't mark that protocol with class keyword, you wouldn't be able to mark that delegate property as a weak one.
Why?
It's simple - only class based properties can have weak relationships.
If you're trying to avoid a reference cycle, that's the way to go 😁
Swift 5.1, Xcode 11 syntax:
protocol FilterViewControllerDelegate: AnyObject {
func didSearch(Parameters:[String: String]?)
}
this protocol can be adopted by only classes.
To answer your first question -
But what is the difference when using:
the difference from this:
protocol FilterViewControllerDelegate {
func didSearch(Parameters:[String: String]?)
}
is that this protocol can adopt value types, such enums and structs as well.
To answer your second question -
And when should I use a : class protocal?
when you should use class protocol I would like to describe next example from delegate pattern:
Imagine that you have delegate protocol.
protocol PopupDelegate: AnyObject {
func popupValueSelected(value: String)
}
and in another class you want to create a property
var delegate: PopupDelegate?
But this has strong reference that could bring you to problems with memory leaks. One way to fix memory leak is to make delegate property - weak. Until we will not make our protocol only available to apply for classes, Swift thinks we could apply our protocol also to value types.
weak var delegate: PopupDelegate?
If you try to declare your delegate like weak you will see next error:
'weak' var only be applied to class and class-bound protocol types,
not 'PopupDelegate'
But we cant apply weak to value types. So we need to restrict our protocol to a reference type, so swift knows that its a reference type.
To make you available to declare this delegate as weak you need to restrict your protocol to be used by classes only:
protocol PopupDelegate: AnyObject {
func popupValueSelected(value: String)
}
It means that the protocol you define can be adopted only by classes, not structures or enums.
From Official Swift book:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// class-only protocol definition goes here }
In the example above, SomeClassOnlyProtocol can only be adopted by class types. It is
a compile-time error to write a structure or enumeration definition
that tries to adopt SomeClassOnlyProtocol.
Swift 3.2 Update:
To declare class only protocol now write:
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
instead of
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// class-only protocol definition goes here
}
The second snippet still seems to work for now.
Reference: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
I have a custom protocol I'm using to define some behavior for some of my view controllers:
protocol MyProtocol {
...
}
I want to be able to declare the type of parameter in my function as UIViewControllers which implement this protocol. For example, in Objective C I could do this:
-(void)doSomethingWithController:(UIViewController<MyProtocol>*)controller;
How do I do this in Swift?
protocol MyProtocol {
// ...
}
func doSomethingWithController<T: UIViewController where T: MyProtocol> (controller: T) {
// ...
}
/* Example */
class MyControllerA : UIViewController, MyProtocol {}
class MyControllerB : UIViewController {}
var a = MyControllerA()
var b = MyControllerB()
doSomethingWithController(a) // ok
doSomethingWithController(b) // compile time error
I believe you can do that simply by typing the protocol name in place of the type:
protocol MyProtocol {
func doSomething(viewController: MyProtocol)
}
I need to declare a variable of type UIView which also conforms to MyProtocol:
protocol MyProtocol: class {
func foobar()
}
class MyClass {
var myView: UIView<MyProtocol>! // Error: Cannot specialize non-generic type 'UIView'
}
However I get the compiler error: Cannot specialize non-generic type 'UIView'.
I need to access methods on the variable from UIView and MyProtocol.
What is the correct variable declaration to support these requirements?
If it makes any difference, only UIView subclasses will implement the protocol. Currently I add protocol conformance via extensions.
I found this answer: https://stackoverflow.com/a/25771265/233602 but it's not clear if that answer is still the best option going in when writing in Swift 2.
Make your class a generic class as follows,
protocol MyProtocol: class {
func foobar()
}
class MyClass<T:MyProtocol where T:UIView> {
var myView: T!
}
The error above says that UIView cannot specialise to protocol MyProtocol, so, the solution here would be to make your class a generic class which takes generic parameter which conforms to MyProtocol and is subclass of UIView.
Probably the best way to solve this is to use a protocol where all UIViews conform to:
protocol UIViewType {
var view: UIView { get }
}
extension UIView: UIViewType {
var view: UIView { return self }
}
// the variable
var myView: protocol<UIViewType, MyProtocol>
Use the view property to access UIView specific functionality.
Late to the party here, but SE-0156 (adopted by Swift 4) enables class and protocol composition in type declarations without requiring (resorting to?) generics.
protocol MyProtocol: class {
func foobar()
}
class MyClass {
var myView: (UIView & MyProtocol)!
}
If it makes any difference, only UIView subclasses will implement the
protocol.
It makes all the difference! Just do this:
protocol MyProtocol: UIView {
func foobar()
}
class MyClass {
var myView: MyProtocol!
}