i want to ask that how the protocols and delegation patterns functions in Swift.
I have an application that let me try the google ad sdk on iOS platform. But i'm missing something and confused about how the methods works.
I have some codes like these;
import UIKit
import GoogleMobileAds
class ViewController: UIViewController, GADInterstitialDelegate {
#IBOutlet weak var bannerView: GADBannerView!
let request = GADRequest()
var interstitial: GADInterstitial!
#IBOutlet weak var mylbl: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
bannerView.adUnitID = "xxx"
bannerView.rootViewController = self
bannerView.loadRequest(self.request)
interstitial = createAndLoadInterstitial()
}
func createAndLoadInterstitial() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "xxx")
interstitial.delegate = self
interstitial.loadRequest(self.request)
return interstitial
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
interstitial = createAndLoadInterstitial()
mylbl.text = "No ad"
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
mylbl.text = "received ad"
}
#IBAction func touched(sender: AnyObject) {
if interstitial.isReady
{
interstitial.presentFromRootViewController(self)
}
else
{
mylbl.text = "Not Ready!"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
For the code above, i'm aware of that the protocols blueprints of methods and properties to adopt a class or struct or enum. The methods or properties defined in the protocol should be implemented on the class that adopted by the related delegate.
I want to ask that and cofused point: OK the method which is named "interstitialDidDismissScreen" inherited from the delegate "GADInsterstitialDelegate" but how the method handled by pressing the close button of the interstitial ad. Where the engineers of Google implemented and how they succeed this behavior. Thanks for your help.
Good hacks,
The button handling is taking place inside the GADInterstitial class. When they setup the class they probably have some internal methods that handle all the ad interaction, and then using the delegate methods they send back to your class the info you need to know to keep your UI managed. By implementing the delegate and its methods you've said I want to use something that your class does, and then I want to also handle all the feedback from that class. If you were to make your own class and implement a protocol and delegate you could do whatever you want inside your class and then pass back just a sliver of info to the class' delegate. An example would be a barcode reading class. I don't care how the barcode gets read, I just want to know the code, so I could set my calling class to be the delegate of the barcode reading class, and when the barcode is read I would receive the barcode back inside of a barcode delegate method.
The wording of your question is garbled and hard to figure out.
A protocol is basically a contract. It says that objets that conform to the protocol promise to provide the properties, and respond to the methods that the protocol defines.
When you say
someObject.delegate = self
You are passing a pointer to yourself to the other object. This is like giving somebody your phone number and saying "Please run these errands for me. If you have any questions, call me at this number. Also please call me when the errands are done."
Since the other object knows that it's delegate conforms to a specific protocol, it knows what messages it can send over the phone (what messages it can send to the delegate)
I suspect the methods interstitialDidReceiveAd(ad: GADInterstitial!) and interstitialDidDismissScreen(ad: GADInterstitial!) are delegate methods.
When the interstitial object needs to send messages to it's delegate, it calls these methods.
Related
I'm trying to implement CVCalendar with my project. I have everything in, but at the end it asks for me to connect outlets. Here is an image of the instructions:
Click here for image
I have no idea what to do as I am new to swift and xcode development. Here is the link to the github page: https://github.com/CVCalendar/CVCalendar
Any help would be appreciated, thanks!
I assume you've extended CVCalendarMenuViewDelegate and CVCalendarViewDelegate on your ViewController and implemented the delegate methods required for CVCalendar such as presentationMode and firstWeekday.
class ViewController: UIViewController {
...
}
extension ViewController: CVCalendarMenuViewDelegate {
...
}
extension ViewController: CVCalendarViewDelegate {
func presentationMode() -> CalendarMode {
return CalendarMode.monthView
}
func firstWeekday() -> Weekday {
return Weekday.monday
}
}
The last thing to do is to connect CVCalendar's menuView and calendarView objects to this class. This means that whenever an action occurs with a calendarView or menuView object the action knows to be routed to the delegate methods of your ViewController because you've attached it as an outlet.
This can be done in InterfaceBuilder by holding the control key and dragging from the menuView and calendarView to the top of the scene and then choosing the delegate to connect to, as shown in this image.
Connecting an outlet
This can also be done programmatically in your ViewController's viewDidLoad method.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
calendarView.delegate = self
menuView.delegate = self
}
I've researched this 100 times, and still can't find the answer to my problem. I have a very simple protocol, but it's always nil. I've tried to add periodDelegate = self but get the error Cannot assign value of type 'ScoreClockPopoverViewController' to type 'PeriodDelegate!' I have other Protocol, using the same setup and work fine.
What am I missing?
Thanks in advance!
import UIKit
protocol PeriodDelegate {
func changePeriodButtonImage(selectedPeriod: Period)
}
class ScoreClockPopoverViewController: UIViewController {
//delegate
var periodDelegate: PeriodDelegate!
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad / periodDelegate \(String(describing: periodDelegate!))")
}
}
Function I need to call is in a UICollectionViewCell`
class HeaderCollectionViewCell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
...
}
extension HeaderCollectionViewCell: PeriodDelegate {
func changePeriodButtonImage(selectedPeriod: Period) {
print("blah")
switch selectedPeriod {
case .first:
print("first")
case .second:
print("second")
case .third:
print("third")
case .overtime:
print("overtime")
case .shootout:
print("shootout")
}
}
}
First of all, it is very uncommon to have cell as delegate for view controller. Usualy, it is other way round. But anyways, in your case you have to set periodDelegate as this cell, not self. Cause your cell implements delegate protocol not the VC. But better rethink what do you want to do because it smells like bad design.
Your statement "I have a very simple protocol, but it's always nil." does not make sense.
A protocol is a specialized language. It can't be nil or non-nil.
Your ScoreClockPopoverViewController has a delegate property periodDelegate that conforms to the PeriodDelegate protocol, and that delegate property is nil.
A delegate is a property like any other. It will be nil unless you assign a value to it. It's nil because you never assigned an object as your ScoreClockPopoverViewController's delegate.
Who creates instances of ScoreClockPopoverViewController, and what object is supposed to be the delegate of your ScoreClockPopoverViewController?
Post your code that creates a ScoreClockPopoverViewController. That's likely where you need to assign your delegate. That code might look something like this:
let myScoreClockPopoverViewController = storyboard.instantiateViewControllerWithIdentifier("ScoreClockPopoverViewController")
myScoreClockPopoverViewController.periodDelegate = self
present(myScoreClockPopoverViewController,
animated: true,
completion: nil)
(That code is meant as a guide and you will need to modify it to make it work in your app. You will not be able to paste it into your app without modification.)
If you're displaying your myScoreClockPopoverViewController as a popover, as the name suggests, you'll need to adjust the code above.
I had the same problem and I fixed it following Fangming's answer by just changing
var periodDelegate: PeriodDelegate!
to
weak var periodDelegate: PeriodDelegate? = nil
and changing the call to
periodDelegate?.blablabla()
Swift - Error passing data between protocols / delegates (found nil)
For some reason the delegate method is not being called in the main View Controller. I was looking for another answers here, but non of them were helpful for me. Am I missing something here? (I shortened my original code for simplicity sake)
Main View Controller:
class VC: ParserDelegate {
var dataSource = Parser()
override func viewDidLoad() {
super.viewDidLoad()
dataSource.delegate = self
dataSourse.loadAndParse()
}
func didReceiveDataUpdates(store: [WeatherModel]) {
print("Delegate method triggered.")
}
}
Protocol:
protocol ParserDelegate: class {
func didReceiveDataUpdates(store: [WeatherModel])
}
My delegate class:
class Parser {
weak var delegate: ParserDelegate?
func loadAndParse() {
var store = [WeatherModel]()
// Doing something
delegate?.didReceiveDataUpdates(store: store)
}
}
The delegate pattern is being applied correctly here, but one thing that might go wrong here: In your main View Controller you are instantiating a new Parser object and store it in „dataSource“:
var dataSource = Parser()
And when setting your main View Controller as its delegate
dataSource.delegate = self
your main View Controller gets notified as the delegate of this new instance you just created. That means: If an instance of your Parser() class jumps into (assure with debugger, if it actually does)
loadAndParse()
it might be another object and so this parser object has no actual delegate. If this is the issue here, you might consider and outlet in order to be able to talk to this specific Parser() class directly. Hope this helps.
You can also edit this line:
from:
dataSource.delegate = self
dataSourse.loadAndParse()
to:
dataSource.delegate = self
dataSource.loadAndParse()
I read a lot about the delegates but in practice I cannot use it properly.
Description: I have A: UIViewController, B: UIView, C: UIViewController. I want to run segue from A: UIViewController to the C: UIViewController from the inside of B: UIView.
I've tried:
protocol SegueDelegate {
func runSegue(identifier: String)
}
class B: UIView { ... }
where in my A: UIViewController:
override func viewDidLoad() {
B().delegate = self
}
func runSegue(identifier: String) {
self.performSegueWithIdentifier(identifier, sender: self)
}
and trying to call it via:
#IBAction func send(sender: AnyObject) {
let a: SegueDelegate? = nil
a!.runSegue("goToMainPage")
}
but I'm sure that I do not use it properly. Can anyone help me with it? I do not want just an answer. Please describe me it concept shortly
Delegates are just a Design Pattern that you can use in a number of ways. You can look at the Apple Frameworks to see how and where to use delegates as examples. A table view delegate is probably the best known delegate in UIKit.
Delegates serve as a callback mechanism for code to communicate with an instance of an unknown class without knowing more than that that instance will respond to the methods of the delegate protocol.
An alternative to a delegate is to use a closure (what we used to call a block in Objective-C). When to use one vs. the other is a matter of taste. There are a couple of rules of thumb, like for instance outlined here.
What you are doing is, IMO, the proper way to use delegates. You separate the view functionality from the View Controller's functionalities via a delegate, and so the contract for your view is clear: the user needs to respond to the delegate method.
Your code works and is correct. I made a quick implementation here: https://github.com/kristofvanlandschoot/DelegateUsage/tree/master
The main difference from your example, and maybe that's the place where you made a mistake is the third part of your code where you should write something like:
#IBAction func send(sender: AnyObject) {
delegate?.runSegue("segueAB")
}
There are multiple errors in your code, for example:
Here you are creating a new B, and setting A as a delegate of that new instance, no the one you actually want
override func viewDidLoad() {
«B()».delegate = self
}
And here you are creating force unwrapping a nil value
#IBAction func send(sender: AnyObject) {
let a: SegueDelegate? = «nil»
«a!».runSegue("goToMainPage")
}
If what you want to do is tell A to perform a segue to C, from inside B, all you need to do is to call performSegueWithIdentifier on A
For example:
class B: UIView {
weak var referenceToA: UIViewController? = nil // set this somewhere
#IBAction func send(sender: AnyObject) {
guard let a = referenceToA else {
fatalError("you didn't set the reference to a view controller of class A")
}
a.performSegueWithIdentifier("goToMainPage", sender: self)
}
}
Delegates an important concept in ObjC/SWIFT or any other coding language. I know that delegates are used to pass messages from one class to another class especially when we want to pass message back to a view controller from where we have just moved to some other view controller.
I was searching for more technical answer and searched a lot about this, and here is what I got what I feel might be the exact answer -
By the rules of MVC, we need a method to return a value. Where in a
called instance can we go back to the class calling it? With an
encapsulated class we can’t. There is no way to send that revised
model back to the original controller without breaking encapsulation
or MVC. The new view controller does not know anything about the class
that called it. We look stuck. If we try to make a reference directly
to the calling controller, we may cause a reference loop that will
kill our memory. Simply put, we can’t send things backwards.
But the explanation says something about
Where in a
called instance can we go back to the class calling it? With an
encapsulated class we can’t. There is no way to send that revised
model back to the original controller without breaking encapsulation
or MVC.
So exactly what does this para mean. Can any one please explain this in a more simple way taking the following code as reference -
VC2 -
import UIKit
protocol myDelegate : class
{
func sendItems(name:NSString)
}
class EnterViewController: UIViewController
{
weak var delegate: myDelegate?
#IBOutlet weak var nameTextfield: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func sendData(sender: AnyObject)
{
delegate?.sendItems(nameTextfield.text!)
self.navigationController?.popViewControllerAnimated(true)
}
VC2
import UIKit
class DisplayViewController: UIViewController,myDelegate
{
#IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func sendItems(name: NSString) {
self.nameLabel.text = name as String
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
let destinationVC = segue.destinationViewController as! EnterViewController
if segue.identifier == "enterDetail"
{
destinationVC.delegate = self
}
}
}
Thanks.
In simple terms, Delegate is a representative of Class which works on behalf of class. If we compare in real world, delegates to foreign countries go to represent their government and have all controls and powers. Similarly, here delegates has all the control that an object of class will have and working on behalf of Class.
Now delegate in specific is an object assigned by class to notify the event. This can be acheived by NSNotification too. But the difference is Delegates can intercept the event but NSNotification cant.
Here in your code:
You have assigned DestinationVC's delegate to DisplayViewController.
Now DisplayviewController will notify all the event whatever you want to notify to Class DestinationVC and also intercept in between event.
In your case you are calling sendItems of DestinationVC.
I am sorry for my bad explanation but I guess you would have get the basic idea.