Swift class with only class methods and a delegate? - ios

I want a class with all class methods. I would like to use a delegate so my view controllers (conforming to the protocol) can call AlertFactory.passwordResetSucess() and display the alert.
Is there a way to make this this work? A way to use the delegate from this class?
Is this bad practice? Bad form? Why?
What's a good way to make this happen? There will be other class methods used in several views.
Thanks!
protocol AlertFactoryDelegate
{
func showAlert(alert: UIAlertController)
}
class AlertFactory: NSObject {
let delegate: AlertFactoryDelegate!
class func passwordResetSuccess()
{
var alert = UIAlertController(title: "Success!", message: "Yay", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Continue", style: UIAlertActionStyle.Default, handler: nil))
delegate.showAlert(alert)
}
}

You can set delegate to be static, and access it with AlertFactory.delegate
class AlertFactory: NSObject {
static weak var delegate: AlertFactoryDelegate?
class func passwordResetSuccess() {
...
self.delegate?.showAlert(alert)
}
}
To create a delegate:
class SomeClass: AlertFactoryDelegate {
... // Implement everything the protocol requires
}
// Asssing a delegate
AlertFactory.delegate = SomeClass()

You cannot set an instance variable on a class without instantiating the class first. Is there a reason you don't want to instantiate the class, and just want to use class methods instead? If you feel that you have good reason to use class methods over instance methods, then you have two potential options:
Pass a delegate as a parameter to the class method.
Use Completion Blocks instead of Delegation. Here's a decent example in swift.
In my personal experience I find blocks to be preferable.
EDIT: I haven't used Swift that much lately, but as #Skrundz pointed out you can indeed use a static variable on a class in Swift.

You could use the SINGLETON command pattern, its a very common practice. You should read up on it, but basically means there is only 1 ever instance of it and you can call methods off of it when needed (or send things to it as needed). Common examples are EventSystem objects or GlobalObserver objects, Factories, and ContextManagers.
Here is information on it:
https://sourcemaking.com/design_patterns/singleton
Using a SINGLETON has tradeoffs, but can be very useful in many situations. This seems like a good pattern for your problem.
You need to initialize your delegate when your app starts. From then on, when another view controller needs to set that delegate you can assign it: (this assumes you made delegate public and its a SINGLETON)
_myViewController.actionThatRequiresDelegate = AlertFactory.delegate
As mentioned in one of the other answers, using Swifts trailing syntax closure system is a great way to use anonymous functions and you could do your logic in there, or communicate with your delegate in there.
update
Initialize in the AppDelegate.swift:
override init()
{
AlertFactory.init()
}
Then in your AlertFactory
public static AlertFactoryDelegate myDelegate
public static func init()
{
myDelegate = new AlertFactoryDelegate()
}

Related

How do you set the delegate for an SFSpeechRecognitionTask?

In most cases, setting a delegate is as simple as implementing the delegate protocol in a class and declaring an instance of that class as the delegate for an instance of whatever you're using.
I actually used this same basic concept for the SFSpeechRecognizer which belongs to the same speech framework in my code. (Pseudocode example):
class myViewControllerClass: SFSpeechRecognizerDelegate{
let mySpeechRecognizer = SFSpeechRecognizer(...)
viewDidLoad(){
mySpeechRecognizer.delegate = self
}
...
//SFSpeechRecognizerDelegate Functions here
...
}
//This works as expected, woo!
However, it seems that SFSpeechRecognitionTask has no delegate property which can be set. I tried implementing the 'SFSpeechRecognitionTaskDelegate' protocol in my class in hopes that it would just magically work. However the delegate functions don't seem to ever be called. Which kind of makes sense, because it has no way of knowing that my view controller should be the delegate so why would it!?
The apple documentation covers the protocol itself and how to use it:
https://developer.apple.com/reference/speech/sfspeechrecognitiontaskdelegate
But the documentation for the task itself doesn't identify any delegate property:
https://developer.apple.com/reference/speech/sfspeechrecognitiontask
Also for reference here's the SFSpeechRecognizer documentation which has the protocol AND identifies a delegate property as you'd expect:
https://developer.apple.com/reference/speech/sfspeechrecognizer
Is there some alternative way I'm supposed to be setting the delegate for an SFSpeechRecognitionTask? Or is it handled in some completely different way?
In SFSpeechRecognizer there is a method
func recognitionTask(with request: SFSpeechRecognitionRequest,
delegate: SFSpeechRecognitionTaskDelegate) -> SFSpeechRecognizerTask
Where you can pass on the delegate for the SFSpeechRecognizerTask.
I did it like this in ViewController:
recognitionTask = speechRecognizer?.recognitionTask(with: speechRecognitionRequest, delegate: self)

Protocol Oriented Programming, implicitly calling extension method

Having my first crack at POP. In this case I want to decorate some UIViewControllers so that any that they automatically raise a 'Page viewed' analytics event.
So I created a protocol, and and extension for that protocol:
protocol ReportPageViewedEvent {
func reportPageViewed()
var pageName : String? { get set }
}
extension ReportPageViewedEvent where Self: UIViewController
{
func reportPageViewed()
{
guard let pageName = self.pageName else
{
fatalError("UIViewController implements ReportPageViewEvent protocol but did not set pageName property")
}
let eventBusiness = EventBusiness.sharedInstance
eventBusiness.logUserViewedPage(pageName)
}
}
This works as I want, if I decorate a UIViewController with ReportPageViewedEvent like this:
class HomeView: UIViewController, ReportPageViewedEvent {
I get a compiler error unless I set 'pageName' which is exactly what I want.
Where I am getting unstuck is where and how to call the actual reportPageViewed() method. I really want it to be called from viewDidLoad which means I either have to modify every 'viewDidLoad' in every controller that uses it, or subclass and call the method in the super class which defies the point of using POP in the first place.
Is there a nice way to achieve this. I can't find an example like this in any tutorial/blog.
Basically, there is always some behaviour shared by all the screens of your app. So it is appropriate to create a class called (for example) BaseViewController so all the other view controllers will inherit from it.
In BaseViewController's viewDidLoad you can call the reportPageViewed() method.
However, this approach makes the Protocol Oriented Programming not needed. Protocols are useful when you need to assign some same behaviour to objects that have nothing in common (which is not the case for app screens).

Why Can Singleton classes be used as regular classes

I was under the impression that the main reason for using singletons was to make sure that only one instance could be created in a program. I thought that the compiler wouldn't let you create instances of a singleton as if it would be a regular class.
In the following code I have a singleton where I'm creating multiple instances of it and it behaves as a regular class, but for some reason I was expecting an error.
What makes a singleton different than a regular class if it lets you create multiple instances?
// singleton class
class Car {
static let sharedCar = Car()
func run(){
print("Running")
}
}
// use
Car.sharedCar.run()
// other instances- I was expecting an error here
var jetta = Car()
jetta.run()
var cobalt = Car()
cobalt.run()
What am I missing here, can someone explain singletons?
I thought that the compiler wouldn't let you create instances of a singleton as if it would be a regular class.
There is no language feature called "singleton", it is an idiomatic pattern. If you leave your implementation of singleton open for instantiations from outside, there is nothing the compiler can do about that.
In the following code I have a singleton where I'm creating multiple instances of it and it behaves as a regular class, but for some reason I was expecting an error.
You should add a private init to make sure there are no external instantiations:
class Car {
static let sharedCar = Car()
func run(){
print("Running")
}
private init() {
}
}
Now you are the only one who can instantiate your class. Users of Car class outside of your code are forced to rely on sharedCar instance that you create for them.

Is all overridable methods are lifecycle methods

My concern is the following,
If I create a Class with some method and inherit it then which methods are called lifecycle methods.
Are all overridable methods lifecycle methods? And in which category does it fall e.g OOPS ,OOAD
Example:- In iOS viewDidLoad is a lifecycle method but didReceiveMemoryWarning is not.
If it is not called a lifecycle method , is it called a overridable method?
Methods don't have type like life cycle method or overridable method etc.
UIViewController have it's own life cycle as per it's behavior that it is load or it appear etc.
And overriding is concept of inheritance. So there is no standard type like life cycle or overridable. Methods which are called from initialization of viewController to Disappearance, comes under lifecycle of viewcontroller.
We use override when we want to add some features to our method from super class.
If you create a class and implement UIViewcontroller as superclass.UIViewController has predefine method such as viewDidload, viewWillAppear,viewDidDisapear and others. If you want to add some features to superclass methods you should use override prefix. Override is used when you implement method of superclass and add your code.
For example
class Student{
func address(){
var add1 = "drn"
}
func phoneNumber(){
var no = 9806569690
}
}
//create another class and add student as superclass
class Classroom: Student{
//here address is method from superclass student so i am using override prefix
override func address(){
var add2 = "ktm"
}
}
Actuctually i am typing from mobile phone. So i could not give you good example.

iOS: Subclass singleton in swift

I have a framework where I have a singleton class, let's say Singleton. This class is used by other classes in the framework.
In the app project I want to subclass this singleton class, e.g. AppSingleton: Singleton. Is it possible? What is the right solution?
I provide a solution but it may be a little hacky.
Class A {
open class var shared: A {
return A.privateShared
}
private static let privateShared = A()
}
Class B {
open class var shared: B {
return A.privateShared
}
private static let privateShared = B()
}
I must clarify, this ways isn't perfect since it actually create 2 instance! So, it will technically not a singleton any more.
However, you can override the class B's property or method to call A.shared method or property instead. You must know what you are doing and consider use the other way to fix the problem you want to solve.

Resources