ViewController does not conform to protocol xyzDelegate - swift

// QuizPopUpViewController.swift
#objc protocol QuizPopUpViewControllerDelegate {
func ApplyNowToSendBack()
}
class QuizPopUpViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
weak var delegate: QuizPopUpViewControllerDelegate?
}
// giving event from here
if isError == false {
self.delegate?.ApplyNowToSendBack() // delegate method
}
}
// Another Viewcontroller
class ShortlistViewController: ParentViewController , QuizPopUpViewControllerDelegate {
}
When i add QuizPopUpViewControllerDelegate to ShortlistViewController, i get the following error:
Type "ShortlistviewController" does not conform to protocol QuizPopUpViewControllerDelegate

The problem is exactly what the error description is suggesting. You need to make your class conforming on QuizPopUpViewControllerDelegate delegate.
To do so, you need to declare the function, what is in QuizPopUpViewControllerDelegate.
// Another Viewcontroller
class ShortlistViewController: ParentViewController , QuizPopUpViewControllerDelegate {
func ApplyNowToSendBack() {
// do something with the callback.
}
}
To avoid asking such questions in the future, i would recommend to read more about the delegate pattern in Swift.

Related

weak property conforming to protocol with generic constraint

I wrote simplified version of similar implementation I'm having problem with. Anyone knows why is that and eventually how to workaround?
NOTE: the code is just example to keep it as simple as possible
protocol Alertable {
associatedtype Alert
func show(alertOfType alertType: Alert)
}
protocol ViewControllerDelegate: class, Alertable {
}
final class MyViewController: UIViewController {
// MARK: - Types
enum AlertType {
case alert
case warning
}
}
extension MyViewController: ViewControllerDelegate {
typealias Alert = AlertType // ! here i specify the associated type !
func show(alertOfType alertType: Alert) {
// code..
}
}
So far so good. But, here I get errors:
final class ViewModel {
// ERROR: Protocol 'ViewControllerDelegate' can only be used as a generic constraint because it has Self or associated type requirements.
weak var viewController: ViewControllerDelegate?
init(viewController: ViewControllerDelegate?) {
self.viewController = viewController
}
private func someFunction() {
// ERROR: Member 'show' cannot be used on value of protocol type 'NewsFeedViewControllerInput'; use a generic constraint instead.
viewController?.show(alertOfType: .warning)
// code..
}
}
Thank you
You had a bit of a misunderstanding here. When you define:
protocol ViewControllerDelegate: class, Alertable {}
extension MyViewController: ViewControllerDelegate {
typealias Alert = AlertType // ! here i specify the associated type !
func show(alertOfType alertType: Alert) {
// code..
}
}
The typealias is defined in MyViewController but not ViewControllerDelegate. It's not clear why you need ViewControllerDelegate in this question but maybe there's something we don't see in the real app.
In ViewModel, change from ViewControllerDelegate to MyViewController:
final class ViewModel {
weak var viewController: MyViewController?
// ...
}
One more thing, though unrelated to the error: you use many final classes. Should they be structs instead?

Altering (refining) delegate type in swift

I have a (swift) class which has a weak pointer to a delegate like this:
import UIKit
#objc public protocol DRSlidingPanelViewControllerDelegate : class {
optional func didSlidePanel(panelHidden : Bool , sender : DRSlidingPanelViewController) -> Void
}
public class DRSlidingPanelViewController: UIViewController {
public weak var delegate : DRSlidingPanelViewControllerDelegate?
///other stuff...
}
Now i make a subclass with another protocol which extends the first, and i want to alter the inherited 'delegate' property
#objc public protocol DRTableViewControllerDelegate : DRSlidingPanelViewControllerDelegate {
optional func someFunction(sender : DRTableViewController) -> Void
}
public class DRTableViewController: DRSlidingPanelViewController {
// public weak var delegate : DRTableViewControllerDelegate?
}
^ this (re)declaration of delegate in the subclass gives me 3 errors when I uncomment it.
Property 'delegate' with type 'DRTableViewControllerDelegate?' (aka 'Optional') cannot override a property with type 'DRSlidingPanelViewControllerDelegate?' (aka 'Optional')
Getter for 'delegate' with Objective-C selector 'delegate' conflicts with getter for 'delegate' from superclass 'DRSlidingPanelViewController' with the same Objective-C selector
Setter for 'delegate' with Objective-C selector 'setDelegate:' conflicts with setter for 'delegate' from superclass 'DRSlidingPanelViewController' with the same Objective-C selector
Now i understand the nature of these errors, and that they are different facets of the one error (attempting to change the 'type' on the delegate pointer.) Can anybody give me a clue how to do this? It obviously can be done, look at how UITableView alters the delegate pointer which it inherits from UIScrollView. In objC I would get a warning which could be silenced with an #dynamic.
Thanks and best regards
edit / addition
Thanks Matt, I do see this previous question, but unfortunately it is closed and I would personally not accept that answer as the definitive answer because it is a compromise.
If I right click on UITableView in xCode and 'jump to definition' I see this
#available(iOS 2.0, *)
public class UITableView : UIScrollView, NSCoding {
public init(frame: CGRect, style: UITableViewStyle) // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain
public init?(coder aDecoder: NSCoder)
public var style: UITableViewStyle { get }
weak public var dataSource: UITableViewDataSource?
**weak public var delegate: UITableViewDelegate?**
//plenty other stuff..
}
So I respectfully submit that there definitely is a way to do this.
I would say that as things stand you can't do it. This is disappointing to say the least. You'll just have to call the delegate variable in the subclass something else.
So, this is legal, but of course it totally fails to meet your requirements:
#objc protocol P1 {
}
#objc protocol P2 : P1 {
}
public class VC1: UIViewController {
weak var delegate : P1?
}
public class VC2: VC1 {
weak var delegate2 : P2?
}
If you really hate the multiplication of storage you can make the delegate2 a computed variable that accesses the inherited delegate:
#objc protocol P1 {
}
#objc protocol P2 : P1 {
}
public class VC1: UIViewController {
weak var delegate : P1?
}
public class VC2: VC1 {
weak var delegate2 : P2? {
set {
super.delegate = newValue
}
get {
return super.delegate as? P2
}
}
}

Unable to implement computed property override on UIViewController

When trying to implement this:
extension UIViewController {
public var presentedViewController: UIViewController? {
return UIViewController()
}
}
I'm receiving the following error:
.../ExampleApp/ExampleAppTests/SpecExtensions.swift:41:59: Getter for 'presentedViewController' with Objective-C selector 'presentedViewController' conflicts with method 'presentedViewController()' with the same Objective-C selector
I'm using the same selector that UIViewController.h defines:
public var presentedViewController: UIViewController? { get }
Is the error misleading or am I just overlooking something? I've tried it with and without override, public, as a method, etc. No luck. However, I am able to override it if it's on a subclass of UIViewController, but not UIViewController itself.
The problem is that you have it in an extension. You can't override methods that were defined on a class from an extension. Basically an extension is not a sub-class, trying to redefine methods that exist on a class by implementing a new version in an extension will fail.
Note that this works:
class ViewController: UIViewController {
override var presentedViewController: UIViewController? {
return UIViewController()
}
}

NSViewController delegate?

I'm new to using delegates in Swift, and I can't seem to figure out how to communicate with my View Controller from a different class. Specifically, I call the custom class's functions from my App Delegate, and then from within that custom class, I call a function within my View Controller. My basic setup, following this question, is:
AppDelegate.swift:
var customClass = customClass()
func applicationDidFinishLaunching(aNotification: NSNotification) {
customClass.customFunction()
}
CustomClass.swift:
weak var delegate: ViewControllerDelegate?
func customFunction() {
delegate?.delegateMethod(data)
}
ViewController.swift:
protocol ViewControllerDelegate: class {
func customFunction(data: AnyObject)
}
class ViewController: NSViewController, ViewControllerDelegate
func customFunction(data: AnyObject){
println("called")
}
}
However, delegate is always nil. I am assuming this is either because the ViewControllerDelegate protocol never gets initialized or because I never set the delegate of the actual NSViewController? I know I'm missing something obvious/straightfoward, however I have yet to see what that is.
Your question is hard to answers because you have completely misunderstood the point of a protocol.
A protocol is a type which is used to define functionality. A class that conforms to this protocol provides the specified functionality, by implementing the required methods.
You can not initialize a protocol.
So if your CustomClass looks like this:
class CustomClass {
weak var delegate: ViewControllerDelegate?
func customFunction() {
delegate?.delegateMethod(data)
}
}
Why do you expect that delegate has suddenly a value?
Of course you have to set delegate to something first. The delegate must set delegate. If you want a ViewController instance to be the delegate, it must assign itself to delegate.
This for instance will work.
protocol ViewControllerDelegate {
func delegateMethod(data: AnyObject) //I renamed this because in
//CustomClass you are trying to call `delegateMethod` on the delegate
}
class CustomClass {
weak var delegate: ViewControllerDelegate?
func customFunction() {
delegate?.delegateMethod(data)
}
}
class ViewController: NSViewController, ViewControllerDelegate
var customClass = CustomClass()
func viewDidLoad(){
customClass.delegate = self
customClass.customFunction()
}
func delegateMethod(data: AnyObject){
println("called")
}
}
Read more about delegation here.

How to declare a swift class with a property that conforms to some protocol

Is it possible for swift to have a ViewController class, initialized from xib, has a property that is also a subclass of UIViewController and conforms to some protocol?
protocol SomeProtocol {
// Some methods
}
class ViewController: UIViewController {
// contentView is initialized from xib
#IBOutlet weak var contentView: UIView!
// I'd like to declare anotherViewController both conforms to 'SomeProtocol'
// and a subclass of UIViewController
var anotherViewController: UIViewController!
...
}
When I declare ViewController as an generic class, say class ViewController<T: UIViewController, SomeProtocol>, I get an error :
"Variable in a generic class cannot be presented in Objective-C"
So how can I fulfil it if I cannot use generic class?
Please forgive me if I misunderstood your problem, but I think what you want to do is declare a new type that inherits from UIViewController and conforms to SomeProtocol, like so:
protocol SomeProtocol { }
class VCWithSomeProtocol: UIViewController, SomeProtocol {
}
class ViewController: UIViewController {
var anotherViewController: VCWithSomeProtocol!
}
So I hope I am not misunderstanding the question as well, but it sounds like you may want a multiple-inheritance object level mixin such as:
let myVC: ViewController, SomeProtocol
Unfortunately, Swift does not support this. However, there is a somewhat awkward work-around that may serve your purposes.
struct VCWithSomeProtocol {
let protocol: SomeProtocol
let viewController: UIViewController
init<T: UIViewController>(vc: T) where T: SomeProtocol {
self.protocol = vc
self.viewController = vc
}
}
Then, anywhere you need to do anything that UIViewController has, you would access the .viewController aspect of the struct and anything you need the protocol aspect, you would reference the .protocol.
For Instance:
class SomeClass {
let mySpecialViewController: VCWithSomeProtocol
init<T: UIViewController>(injectedViewController: T) where T: SomeProtocol {
self.mySpecialViewController = VCWithSomeProtocol(vc: injectedViewController)
}
}
Now anytime you need mySpecialViewController to do anything UIViewController related, you just reference mySpecialViewController.viewController and whenever you need it to do some protocol function, you reference mySpecialViewController.protocol.
Hopefully Swift 4 will allow us to declare an object with protocols attached to it in the future. But for now, this works.
Hope this helps!