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
Related
How can I define a variable in a protocol in Swift4 that at least needs to conform to a protocol, but can also conform to other protocols as well?
For example I now get an error if the protocol declares that a variable should conform to protocol B and I want the variable in the implementation to conform to a composite of different protocols (B + C).
// For example: Presenter can conform to default stuff
protocol A {
var viewController: C? { get set }
func presentDefaultStuff()
}
extension protocol A {
func presentDefaultStuff() {
viewController?.displayDefaultStuff()
}
// Presenter can conform to custom stuff
protocol B {
func presentCustomStuff()
}
// viewController can conform to default stuff
protocol C {
func displayDefaultStuff()
}
// viewController can conform to custom stuff
protocol D {
func displayCustomStuff()
}
class SomeClass: A & B {
// Gives an error: Type 'SomeClass' does not conform to protocol 'A'
// because protocol A defines that viewController needs to be of
// type C?
var viewController: (C & D)?
}
Edited:
I edited my original post to make the question more clear
I also found a solution to do the thing that I wanted to achieve:
I can split the class and make an extension on the implementation that conforms to one of the protocols like this:
class someClass: B {
customViewController: (C & D)?
}
extension someClass: A {
var viewController: C? {
return customViewController
}
}
The compiler does a type check that customViewController conforms to C?.
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 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>
}
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!
}
I am not sure, it looks to me that it is some kind of bug or bad implementation with protocol extensions in Swift 2.0.
I have protocolA, protocolB extending protocolA and implementing methods in protocolB extension.
I have conformed an class instance to conform to protocolB, however when inspected by respondsToSelector for protocolA/B methods the results is false.
import Cocoa
import XCPlayground
protocol ProtocolA : NSObjectProtocol {
func functionA()
}
protocol ProtocolB : ProtocolA {
func functionB()
}
extension ProtocolB {
func functionA() {
print("Passed functionA")
}
func functionB() {
print("Passed functionB")
}
}
class TestClass : NSObject, ProtocolB {
override init () {
}
}
var instance:TestClass = TestClass()
instance.functionA() // Calls code OK..
if instance.respondsToSelector("functionA") {
print("Responds to functionA") // **False, never passing here**
}
if instance.respondsToSelector("functionB") {
print("Responds to functionB") // **False, never passing here**
}
Should be reported as a bug?
Interesting. Looks like a bug to me. It does recognize functions on a class, but not on extension. No matter what type Instance has. Moreover without an extension code would not be compilable, since protocol methods are non optional. So really looks like a bug/feature? in responds to selector implementation.