Swift Delegate from Singleton not working - ios

I'm trying to implement SharedInstanceDelegate in App class. I have no idea why the functions under the protocol are not being called.
This is my Protocol and class.
class App {
let sharedInstance = SharedInstance.shared
init() {
self.sharedInstance.delegate = self
}
}
extension App: SharedInstanceDelegate {
func1() { } // this is not executed
func2() { }
}
protocol SharedInstanceDelegate: class {
func1()
func2()
}
class SharedInstance {
static let shared = SharedInstance()
weak var delegate: SharedInstanceDelegate?
private init() { }
func method1() {
self.delegate?.func1() // this is executed
}
}

I believe you meant to make SharedInstanceDelegate a protocol, but you've made it a class. In either case, App does not conform/inherit SharedInstanceDelegate, so it's not clear how this would even compile.

Here is how I would implement your code to work with the delegate:
class App {
let sharedInstance = SharedInstance.shared
init() {
self.sharedInstance.delegate = self
}
}
extension App: SharedInstanceDelegate {
func func1() { } // this will run now
func func2() { }
}
protocol SharedInstanceDelegate {
func func1()
func func2()
}
class SharedInstance {
static let shared = SharedInstance()
var delegate: SharedInstanceDelegate?
private init() { }
func method1() {
self.delegate?.func1() // this is executed
}
}

Still no idea why this was happening, but cleaning the project fixed this. This is very strange. I have other delegates that call successfully.

Your code could work but it depends on how you are calling func1(). Calling it like this:
let testinstance = App().sharedInstance
testinstance.delegate?.func1()
will not work because you are not holding on to the App object. In this case the App object is the delegate, but because its a weak member and no one is retaining it, it gets released right away.
If you call it like this:
let testapp = App()
testapp.sharedInstance.delegate?.func1()
it works. In this case the App object is being retained and is still around when func1() is called.
Either way the way these classes are related is confusing to me. Why have a separate SharedInstance class at all?

Related

Subscribing to a property

I have a singleton service class which maintains a value of heading it gets from the compass. I have a UIView which draws some custom graphics based on this. I'm trying to do something like an Observable in javascript, where my code gets executed when there's a change in the value.
final class LocationService: NSObject {
static let shared = LocationService()
public var heading:Int
public func getHeading() -> Int {
return self.heading
}
Then in my UIView subclass:
var ls:LocationService = LocationService.shared
var heading: Int = ls.getHeading() {
didSet {
setNeedsDisplay()
}
}
I tried also just directly accessing the property via ls.heading but this doesn't get accepted either. It's telling me I cannot use the instance member within the property initialiser. What's a proper swift method of doing this?
Edit:
I've been working with Christian's answer below and some other documentation and now got to here where it all compiles nicely, but doesn't actually work. Here's my delegator and protocol:
final class LocationService: NSObject {
static let shared = LocationService()
weak var delegate: CompassView?
var heading:Int
func headingUpdate(request:HeadingRequest, updateHeading:CLHeading) {
print ("New heading found: \(updateHeading)")
self.heading = Int(updateHeading.magneticHeading)
self.delegate?.setHeading(newHeading: Int(updateHeading.magneticHeading))
}
public func getHeading() -> Int {
return self.heading
}
}
protocol LSDelegate: class {
func setHeading(newHeading:Int)
}
Then in the delegate:
class CompassView: UIView, LSDelegate {
func setHeading(newHeading:Int) {
self.heading = newHeading
print("heading updated in compass view to \(self.heading)")
setNeedsDisplay()
}
}
So I get the print message that the heading has been updated in the headingUpdate function. The print message in the setHeading function in the delegate CompassView never gets displayed.
You can use the delegation pattern and have that class that wants to consume your events implement the functions in your protocol.
protocol MyDelegate {
func setNeedsDisplay()
}
class LocationService: NSObject {
var myDelegate : MyDelegate?
var heading: Int = ls.getHeading() {
didSet {
myDelegate?.setNeedsDisplay()
}
}
...
func assignDelegate() {
self.myDelegate = MyConsumer()
}
}
class MyConsumer : MyDelegate {
func setNeedsDisplay()
{
}
}

How do i make singleton class as delegator in swift3

I have a singleton class as shown in below code snippet .
protocol EmpLoginDelegate {
func empLoginSuccess()
func empLoginFailed()
}
class CommunicationModule {
static let sharedInstance = CommunicationModule()
private init() {
}
var empLoginDelegate:EmpLoginDelegate?
func test(){
self.empLoginDelegate?.empLoginSuccess()
}
}
My delegate class is shown in below code snippet.
extension LoginViewController: EmpLoginDelegate{
func empLoginSuccess(){
wrongAttempts = 0
loginSuccess = true
print("EmpLoginIsSuccess")
performSegue(withIdentifier: "attendanceView", sender: self)
}
func empLoginFailed(){
wrongAttempts = wrongAttempts + 1
userNameTextField.shake(count: 3, for: 0.3, withTranslation: 10)
passwordTextField.shake(count: 3, for: 0.3, withTranslation: 10)
loginSuccess = false
loginAlert(alertTitle: "Invalid Credentials", alertMsg: "Your employee id or password is not correct")
}
}
When i call test function emploginSuccess() method does not get called. Test function is executed successfully with out any error.
I thought that problem is empLoginDelegate is not initialised in my code, so i had tried possible ways to initialise it as self but nothing worked for me. Is there any other way to use delegation pattern in singleton class in swift3(iOS 10.3.1).
Make sure you are communicating with the singleton properly. To set your instance of LoginViewController as the empLoginDelegate, call:
CommunicationModule.sharedInstance.empLoginDelegate = self
from a method inside of LoginViewController.
I think This method is good, for me that is best way
final class Singleton {
// Can't init is singleton
private init() { }
//MARK: Shared Instance
static let shared: Singleton = Singleton()
}

Empty vars when calling method from singleton class

So I have a singleton class in which I have implemented the delegate of my module. However when that delegate method gets executed in this singleton I call a method in another class of the App and it crashes because all the variables previously set in that class are empty.
class Player: Jukebox, JukeboxDelegate {
static let sharedInstance = Player()
func setDelegate(){
jukebox = Jukebox(delegate: self)
}
func play(Link: String) {
jukebox.setIT([JukeboxItem(URL: NSURL(string: Link)!)])
jukebox.setImage(currentImage)
jukebox?.play()
}
func audioPlayerDidFinishPlaying(player: Jukebox, successfully flag: Bool) {
if pltype == PlayerType.Playlist {
MyMusicVC.continuePlaying() { () -> () in
}
}
}
func jukeboxStateDidChange(state: Jukebox) {
}
func jukeboxPlaybackProgressDidChange(jukebox: Jukebox) {
}
func jukeboxDidLoadItem(jukebox: Jukebox, item: JukeboxItem) {
}
func jukeboxDidUpdateMetadata(jukebox: Jukebox, forItem: JukeboxItem) {
}
}
Any ideas on why could this be happening?
Its hard to understand what is going on. But you are subclassing a Jukebox class. Then making this subclass a delegate of the Jukebox itself. Then I also notice you're setting a Jukebox property that appears to be optional but not.
For example. Why in the play() function is jukebox. used twice but the last line is jukebox?. Is jukebox optional? Or implicitly unwrapped? And if thats the case, why are you using it unwrapped twice and then optionally the third time.
Have you tried not making this singleton a subclass of jukebox. Instead just make it conform to the JukeBoxDelegate protocol and see if that accomplishes the same goal?

Override function error in swift

I got a struct :
struct ErrorResultType: ErrorType {
var description: String
var code: Int
}
and a protocol:
protocol XProtocol {
func dealError(error: ErrorResultType)
}
Now I want to make an extention of UIViewController:
extension UIViewController: XProtocol {
func dealError(error: ErrorResultType) {
// do something
}
}
So I can subclass from this and override the function like:
class ABCViewController: UIViewController {
--->override func dealError(error: ErrorResultType) {
super.dealError(error)
// do something custom
}
}
But it goes wrong with: Declarations from extensions cannot be overridden yet
It doesn't make any sense to me. When I replace all ErrorResultType with AnyObject, the error won't appear any more.
Anything I missed?
For now the method in the extension must be marked with #objc to allow overriding it in subclasses.
extension UIViewController: XProtocol {
#objc
func dealError(error: ErrorResultType) {
// do something
}
}
But that requires all types in the method signature to be Objective-C compatible which your ErrorResultType is not.
Making your ErrorResultType a class instead of a struct should work though.
If i am not making mistake this is connected with Swift official extension mechanism for adding methods to classes.
Conclusion :
At the moment, it's not possible to override entities declared in
extension by subclassing, like so:
class Base { }
extension Base {
var foo: String { return "foo" }
}
class Sub: Base {
override var foo: String { return "FOO" } // This is an error
}
Please check this resource for more information : https://github.com/ksm/SwiftInFlux/blob/master/README.md#overriding-declarations-from-extensions

iOS Swift How to create a Protocol instance

I am a Android developer, and I'm very new to Swift so please bear with me. I am trying to implement callback functions with Protocol in Swift. In Java I can create an Interface and make it an instance without linking it to any implementing class so that I can pass it around, for example:
public interface SomeListener {
void done();
}
SomeListener listener = new SomeListener() {
#Override
public void done() {
// do something
}
}
listener.done();
How can I do it with Protocol in Swift? Or can it actually be done?
That`s a way you can implement a protocol. Its like the delegate pattern in ObjC
protocol DoneProtocol {
func done()
}
class SomeClass {
var delegate:DoneProtocol?
func someFunction() {
let a = 5 + 3
delegate?.done()
}
}
class Listener : DoneProtocol {
let someClass = SomeClass()
init() {
someClass.delegate = self
someClass.someFunction()
}
// will be called after someFunction() is ready
func done() {
println("Done")
}
}

Resources