How to initialize an event handler in swift? - swift

For the given event handler attribute methods:
class AudioServer {
var didReceiveData: ((AudioBufferData) -> Void)?
func websocketCallback(event: WebSocketEvent, client: WebSocket) {
switch event {
..
}
func handleMicrophoneData(_ data: AudioBufferData) {
..
}
How can those be set up /initialized? They are not available yet in the init() method so the following most straightforward implementation does not work:
init() {
didReceiveData = { bufferData in
self.handleMicrophoneData(bufferData)
}
self.websocketClient = WebsocketClient(url: Self.WebsocketUrl, callback: self.websocketCallback)
}
We get:
'self' used in method call 'websocketCallback' before all stored properties are initialized
So what is a typical mechanism for these initializations?

Related

Weak reference implementing a (generic) protocol

I want to create an array of weak references implementing a protocol for observable functionality.
If possible this protocol should have an associated type, so I would not need to create identical ones for each type.
However in Swift 4 this does not seem to work, what I want is basically this:
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataUpdated(data: [Item])
}
protocol Delegate : DelegateBase where Item == Int {
// Will have func onDataUpdated(data: [Int])
}
// T should be a class implementing Delegate, but cannot find a way to
// define T in a way that the Swift compiler accepts it
class WeakListener<T> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class Implementation {
val listeners = [WeakListener<Delegate>]()
}
If I define everything as non-generic I can make it work, but I would like the convenience of not having to copy paste a concrete version of DelegateBase for each type I want to support.
// This works but is clunky
protocol DelegateA {
func onDataUpdated(data: [Int])
}
// DelegateB with type Double, DelegateC with type X
class WeakListenerA {
weak var listener : DelegateA?
init(listener: DelegateA) {
self.listener = listener
}
}
// WeakListenerB with type Double, WeakListenerC with type X
class ImplementationA {
val listeners = [WeakListenerA]()
}
// ImplementationB with type Double, ImplementationC with type X
EDIT: Intended usage
Basically I want to implement remote-backed repository where UIViewControllers can listen in on events happening inside the repository even though they aren't actively requesting data.
I want the listener to be generic, so I don't need to clone everything for each type. I want weak references since then no manual work is needed for managing them apart from adding listeners.
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataModified(data: [Item])
func onDataRefreshed(data: [Item])
}
protocol IntDelegate : DelegateBase where Item == Int {
// Will have
//func onDataModified(data: [Int])
//func onDataRefreshed(data: [Int])
}
// Listener should implement the delegate T, that extends DelegateBase
// with a type
class WeakListener<T : DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class IntRepository {
var listeners = [WeakListener<IntDelegate>]()
var data = [Int]()
func addListener(_ listener: IntDelegate /* UIViewController implementing IntDelegate*/) {
listeners.add(listener)
}
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in listeners {
listener.listener?.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in listeners {
listener.listener?.onDataRefreshed(data: data)
}
}
fileprivate func cleanupListeners() {
self.listeners = self.listeners.filter({$0.listener != nil})
}
// Singleton for example
fileprivate static var _instance: IntImplementation!
public class func shared() -> IntImplementation {
if _instance == nil {
_instance = IntImplementation()
}
return _instance!
}
}
class IntViewController: UIViewController, IntDelegate {
override func viewDidLoad() {
IntImplementation.shared().addListener(self)
}
func onDataModified(data: [Int]) {
// update UI
}
func onDataRefreshed(data: [Int]) {
// update UI
}
}
Because the DelegateBase (and by extension, the Delegate) protocol has an associated type (unlike DelegateA), you cannot use it as a type; you can only use some concrete type that conforms to it.
For what you're trying to do, you don't actually need the Delegate protocol. You seem to want a WeakListener generic with respect to Item type, which you can declare like so:
class WeakListener<T: DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
In other words, the above works with some concrete T type that conforms to DelegateBase.
Let's say you had such a concrete type for Int:
class ConcreteIntDelegateA: DelegateBase {
func onDataUpdated(data: [Int]) {
// ...
}
}
Then you could create a WeakListener for ConcreteIntDelegateA because it conforms to DelegateBase and further specifies that an Item is Int
let listener: WeakListener<ConcreteIntDelegateA>
So, it works for a concrete type, but you cannot do this for a protocol DelegateBase, because DelegateBase doesn't conform to DelegateBase (protocols don't conform to protocols, including themselves):
let listener: WeakListener<DelegateBase> // ERROR
This gives you the ability to create array of listeneres for a specific concrete type, e.g. [WeakListener<ConcreteIntDelegateA>] or [WeakListener<ConcreteIntDelegateB>], but not mixed, because these types are unrelated even though both ConcreteDelegateX conform to DelegateBase.
To get around it is to create a type-erased type, e.g. class AnyDelegate<Item>: DelegateBase, which takes a concrete type in its init:
class AnyDelegate<Item>: DelegateBase {
private let onDataUpdated: ([Item]) -> Void
init<C: DelegateBase>(_ c: C) where C.Item == Item {
self.sonDataUpdated = c.onDataUpdated(data:)
}
func onDataUpdated(data: [Item]) {
onDataUpdated(data)
}
}
let anyIntA = AnyDelegate(ConcreteIntDelegateA())
let anyIntB = AnyDelegate(ConcreteIntDelegateB())
let anyIntListeners: [WeakListener<AnyDelegate<Int>>] = [anyIntA, anyIntB]
What I ended up doing was just throwing away the DelegateBase. To provide some type conformance I created a generic base repository and enforce the delegate type during runtime when adding listeners
import UIKit
protocol IntDelegate : AnyObject {
func onDataModified(data: [Int])
func onDataRefreshed(data: [Int])
}
class WeakListener {
weak var listener : AnyObject?
init(listener: AnyObject) {
self.listener = listener
}
}
class RepositoryBase<T> {
private var _listeners = [WeakListener]()
var listeners: [T] {
get {
// Remove dead listeners
self._listeners = self._listeners.filter({($0.listener as? T) != nil})
return self._listeners.map({ $0.listener as! T })
}
}
func addListener(_ listener: AnyObject) {
assert(listener is T)
_listeners.append(WeakListener(listener: listener))
}
}
class IntRepository : RepositoryBase<IntDelegate> {
var data = [Int]()
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in self.listeners {
listener.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in self.listeners {
listener.onDataRefreshed(data: data)
}
}
// Singleton for example
fileprivate static var _instance: IntRepository!
public class func shared() -> IntRepository {
if _instance == nil {
_instance = IntRepository()
}
return _instance!
}
}
class IntViewController: IntDelegate {
func viewDidLoad() {
IntRepository.shared().addListener(self)
IntRepository.shared().add()
}
func onDataModified(data: [Int]) {
print("modified")
}
func onDataRefreshed(data: [Int]) {
print("refreshed")
}
}
IntViewController().viewDidLoad() // Prints "modified"

Execute closure from another method in an extension Swift

I have a class that is a delegate to a custom modal view, therefore it has a method for when the modal has been dismissed. I am extending that class and in the extension I have a method that accepts a completion closure.
I can't write in the main implementation of the class or the modal's implementation - only the extension.
I want to execute the closure when the modal is dismissed, but I can't seem to figure it out on my own. Is it even possible?
Here is an example of what I want to do:
extension MyClass {
func method(completion: (Int) -> ()) {
// showing the modal
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
// here I want to execute the completion passed to method()
}
}
Assign the completion as a variable to a MyClass's property in method and call it in modalDismissed:
class MyClass {
var classCompletion: (() -> ())?
}
extension MyClass {
func method(completion: #escaping () -> ()) {
classCompletion = completion
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
classCompletion?()
}
}
Update: If you can't "write in the main implementation of the class", here's a method using static property. This is a hack and has many limitations but does the work. Otherwise without writing to the main implementation you can't do anything.
extension MyClass {
static var classCompletion: (() -> ())?
func method(completion: #escaping () -> ()) {
MyClass.classCompletion = completion
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
MyClass.classCompletion?()
}
}

Extending target-action methods with RxSwift

class A{
func addTarget(target: Any, action: Selector)
}
Let's say I don't have class A source available (framework). How would I extend this class reactively to emit Rx events through an Observable?
I can create a class that just forwards the events through a PublishSubject, but in that case I wouldn't be creating a Reactive extension but doing it through a proxy class.
let a = A()
let del = CustomClassThatAddsItselfAsATarget(a)
del.event.subscribe( ...
instead of
let a = A()
a.rx.event.subscribe( ...
This was a fun exploration. I patterned the below off of how UIControl is set up in RxCocoa.
In answer to your followup questions:
Which object will add itself as a target(addTarget method) to base?
You have to create a class that is designed to do that. I named it ATarget.
Who retains that object?
You make the object conform to Disposable and then it will be retained until disposed of.
extension Reactive where Base: A {
var event: Observable<A> {
return Observable.create { [weak a = self.base] observer in
guard let a = a else {
observer.on(.completed)
return Disposables.create()
}
let aTarget = ATarget(a: a, callback: { a in
observer.on(.next(a))
})
return Disposables.create(with: aTarget.dispose)
}
.takeUntil(deallocated)
}
}
class ATarget: NSObject, Disposable {
typealias Callback = (A) -> Void
let selector: Selector = #selector(ATarget.eventHandler)
weak var a: A?
var callback: Callback?
init(a: A, callback: #escaping Callback) {
self.a = a
self.callback = callback
super.init()
a.addTarget(target: self, action: selector)
}
#objc func eventHandler() {
if let callback = self.callback, let a = self.a {
callback(a)
}
}
func dispose() {
self.a?.removeTarget(target: self)
self.callback = nil
}
}
RxCocoa and most other RxSwift-based frameworks take the following approach -
public extension Reactive where Base: TheOriginalClass {
See CKRecord+Rx or Bundle+Rx for an example of implementation.
Things get more complicated if you need to provide a proxy delegate, but this is out of scope of this question.

Custom protocols

Im getting this error "Class declaration cannot close over value 'viewcontainer' defined in outer scope"
I created a procotol called NetworkResponse which have two methods on sucessResponse and onErrorResponse.
Then I have a class called Callback that extends from NetworkResponse and forced to implement that methods.
Here is my function :
public func login (callback : Callback, viewController : UIViewController) {
let callbackInstance: NetworkResponse = {
class callback : Callback {
override func onSucessResponse(response : NSDictionary){
viewController.dismiss(animated: true, completion: nil)
}
override func onErrorResponse(message : String, code : Int){
print("error")
}
}
return callback()
}()
postPath(callback: callbackInstance as? Callback)
}
I want to dismiss the controller from the anonymous class.
Any recomendation ?
No need to define a protocol and Callback class. Closure is just what you need.
import UIKit
public class TestInnerClass: UIViewController {
public func login(successCallback: ((response: NSDictionary) -> Void), errorCallback: ((message: String, code: Int) -> Void)) {
let success = false
let response = NSDictionary()
//
// Make your login request here, and change the `success` value depends on your response
// let response = ...
//
// If you are making a async request to login, then put the following codes inside your request callback closure.
//
if success {
successCallback(response: response)
} else {
errorCallback(message: "error occurred", code: -1)
}
}
override public func viewDidLoad() {
super.viewDidLoad()
login({
(response) in
// Get Called when success
self.dismissViewControllerAnimated(true, completion: nil)
}, errorCallback: ({
// Get called when failed
(message, code) in
print(message)
}))
}
}
I have written some sample codes for your case in my Github repo, and this example is using Alamofire to make network request, Just for your reference.
PS: Since I still using Xcode 7.3.1, so you may need to do some changes to the above code to adopt the swift 3 syntax requirement.

Observer Pattern in Swift

I want to implement an observer pattern, but I do not find the proper programming language constructs in Swift (also 2.0). The main problems are:
protocol and extension does not allow stored properties.
In classes we could add stored properties, but we can not force a subclass to override some of its inherited methods.
This is what I want:
{class|protocol|extension|whathaveyou} Sensor {
var observers = Array<Any>() // This is not possible in protocol and extensions
// The following is does not work in classes
func switchOn()
func switchOff()
var isRunning : Bool {
get
}
}
class LightSensor : Sensor {
//...
override func switchOn() {
// turn the sensor on
}
}
// In the class C, implementing the protocol 'ObserverProtocol'
var lightSensor = LightSensor()
lightSensor.switchOn()
lightSensor.registerObserver(self) // This is what I want
And here comes what is possible to my knowledge:
class Sensor {
private var observers = Array<Observer>()
func registerObserver(observer:ObserverDelegate) {
observers.append(observer)
}
}
protocol SensorProtocol {
func switchOn()
func switchOff()
var isRunning : Bool {
get
}
}
class LightSensor : Sensor, SensorProtocol {
func switchOn() {
//
}
func switchOff() {
//
}
var isRunning : Bool {
get {
return // whatever
}
}
}
But this is not very convenient, because both Sensor and SensorProtocol should come hand in hand, and are both requirements the subclass LightSensor has to fulfill.
Any ideas?
A protocol is an abstract set of requirements shared across a number of (potentially very different) other objects. As such, it's illogical to store data in a protocol. That would be like global state. I can see that you want to define the specification for how the observers are stored though. That would also allow 'you' to remove 'someone else' from being an observer, and it's very restrictive about how the observers are stored.
So, your protocol should expose methods to add and remove 'yourself' as an observer. It's then the responsibility of the object implementing the protocol to decide how and where the observers are stored and to implement the addition and removal.
You could create a struct to work with your protocols, something like:
protocol Observer: class {
func notify(target: Any)
}
protocol Observable {
mutating func addObserver(observer: Observer)
mutating func removeObserver(observer: Observer)
}
struct Observation: Observable {
var observers = [Observer]()
mutating func addObserver(observer: Observer) {
print("adding")
observers.append(observer)
}
mutating func removeObserver(observer: Observer) {
print("removing")
for i in observers.indices {
if observers[i] === observer {
observers.removeAtIndex(i)
break
}
}
}
func notify(target: Any) {
print("notifying")
for observer in observers {
observer.notify(target)
}
}
}
struct ATarget: Observable {
var observation = Observation()
mutating func addObserver(observer: Observer) {
observation.addObserver(observer)
}
mutating func removeObserver(observer: Observer) {
observation.removeObserver(observer)
}
func notifyObservers() {
observation.notify(self)
}
}
class AnObserver: Observer {
func notify(target: Any) {
print("notified!")
}
}
let myObserver = AnObserver()
var myTarget: Observable = ATarget()
myTarget.addObserver(myObserver)
if let myTarget = myTarget as? ATarget {
myTarget.notifyObservers()
}
This is my solution in Swift 3
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var objectToObserve = ObjectToObserve()
let observer = Observer()
let observer1 = Observer()
objectToObserve.add(observer: observer, notifyOnRegister: true)
objectToObserve.add(observer: observer1, notifyOnRegister: true)
}
}
//
// MARK: Protocol
//
protocol Observing: class {
func doSomething()
func doSomethingClosure(completion: () -> Void)
}
protocol Observable {
}
extension Observable {
private var observers: [Observing] {
get {
return [Observing]()
}
set {
//Do nothing
}
}
mutating func add(observer: Observing, notifyOnRegister: Bool) {
if !observers.contains(where: { $0 === observer }) {
observers.append(observer)
if notifyOnRegister {
observer.doSomething()
observer.doSomethingClosure(completion: {
print("Completion")
})
}
}
}
mutating func remove(observer: Observing) {
observers = observers.filter({ $0 !== observer })
}
}
//
// MARK: Observing
//
class ObjectToObserve: Observable {
init() {
print("Init ObjectToObserve")
}
}
class Observer: Observing {
init() {
print("Init Observer")
}
func doSomething() {
print("Do something")
}
func doSomethingClosure(completion: () -> Void) {
print("Do something Closure")
completion()
}
}
All answers above incorrectly use an array for retaining the observers, which may create retain cycles because of the strong references.
Also in general you may not want to allow the same observer to register itself twice.
The presented solutions also are not general purpose or lack type safety. I reference my blog post here which presents a full solution in a Swifty manner:
https://www.behindmedia.com/2017/12/23/implementing-the-observer-pattern-in-swift/
Well, you can certainly overcome the restriction of not having stored properties on extensions.
Maybe that way you can complement one of the proposed solutions with an extension that helps you avoid creating the observer list in each subclass / protocol implementation.
Although extensions can't have stored properties, you can actually get them by using the Objective-C Runtime. Assuming you have a base class for your sensors (BaseSensor) and a protocol for observers (SensorObserver):
import Foundation
import ObjectiveC
private var MyObserverListKey: UInt8 = 0
extension BaseSensor {
var observers:[SensorObserver] {
get {
if let observers = objc_getAssociatedObject( self, &MyObserverListKey ) as? [SensorObserver] {
return observers
}
else {
var observers = [SensorObserver]()
objc_setAssociatedObject( self, &MyObserverListKey, observers, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC) )
return observers
}
}
set(value) {
objc_setAssociatedObject( self, &MyObserverListKey, observers, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC) )
}
}
}
To be clear, even though you would need BaseSensor and all Sensors to inherit from it in order to have this property, BaseSensor wouldn't actually implement the Sensor protocol.
It's a bit weird, but I think it would suit your needs:
class BaseSensor {
}
protocol Sensor {
func switchOn()
}
class LightSensor: BaseSensor, Sensor {
func switchOn() {
// whatever
}
}
With Swift 2.0 this would be much simpler, since you can use Protocol Extensions, so you could simply do this:
protocol Sensor {
func switchOn()
}
extension Sensor {
// Here the code from the previous implementation of the extension of BaseSensor
}
class LightSensor : Sensor {
func switchOn() {
// whatever
}
}
Way better.