Create a protocol using two classes - swift

I have two classes, something like that
class FirstClass {
func returnInt() -> Int {
return (42)
}
}
class SecondClass {
func printInt(myInt: Int) {
print(myInt)
}
}
I would like to know if it is possible to create a Protocol when the function "returnInt() -> Int" of the FirstClass is call so the function of the second Class "printInt(Int)" is call.
In reality, I'm working on the serialization / deserialization of packet from different classes.
I think is the best way for that, that's why I need your help.
Thank you

Closures
I don't know your exact usage, but one way is using closures instead of protocols. Create closure variable inside first class and then call it after value is returned
class FirstClass {
var valueReturned: ((Int)->Void)?
func returnInt() -> Int {
let value = 42
valueReturned?(value)
return value
}
}
then somewhere where you have references for both instances of both classes set first's valueReturned and inside closure say that when this will be called, you want to call printInt(myInt:) of second's and as parameter pass value from closure
firstClass.valueReturned = { value in // assign parameter of closure
self.secondClass.printInt(myInt: value)
// self.printInt(myInt: value)
}
Delegate Patern
Anyway, if you want to use protocols, you'll need delegate patern.
Start with declaring protocol
protocol FirstClassDelegate: class {
func printInt(myInt: Int)
}
and then create delegate variable inside first class and call method on delegate after value should be returned
class FirstClass {
weak var delegate: FirstClassDelegate?
func returnInt() -> Int {
let value = 42
delegate?.printInt(myInt: value)
return value
}
}
Now implement this delegate protocol to second class and set delegate property of some first class instance as self
class SecondClass {
var firstClass = FirstClass()
init() {
firstClass.delegate = self
}
}
extension SecondClass: FirstClassDelegate {
func printInt(myInt: Int) {
print(myInt)
}
}

This should do it:
class FirstClass {
weak var firstClassToSecondClassCommunicatorDelegate: FirstClassToSecondClassCommunicator?
func returnInt() -> Int {
let myInt = 42
if firstClassToSecondClassCommunicatorDelegate != nil {
firstClassToSecondClassCommunicatorDelegate?.printInt(myInt: myInt)
}
return myInt
}
}
class SecondClass: FirstClassToSecondClassCommunicator {
func printInt(myInt: Int) {
print(myInt)
}
}
class myVC: UIViewController {
override func viewDidLoad() {
let firstClass = FirstClass()
let secondClass = SecondClass()
firstClass.firstClassToSecondClassCommunicatorDelegate = secondClass
}
}
protocol FirstClassToSecondClassCommunicator {
func printInt(myInt: Int)
}

In secondClass initialize your class with:
init(fromFirstClass returnInt: Int) {
....
}

Related

How to return subclass objects from its base class static method?

In Swift, I want to make my base class static method return its subclass objects when the static method is called from a subclass.
When returning one subclass object, I can make it possible by using init().
But when returning multiple subclass objects, init() can not be used.
And I want to not only just return subclass objects from the parent static method, but also to implement some logic other than instantiation in the parent static method, and make the static method of each subclass inherit the parent's static method behavior.
I have 3 sub-classes. So, I don't want to write the same code in the static methods of 3 sub-classes.
How should I do?
If possible, I want to use the static method instead of init() to return a single subclass object, too.
class Base {
func f() {
print("base class")
}
// this does not works. it creates a base class object.
static func createSubclassObject() -> Base {
return Base()
}
// this works. it creates a subclass object.
init() {
}
// this does not work. base class objects are created.
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
objects.append(Base())
}
return objects
}
/* probably I need something like this. but this code generates a compile error
static func createSubclassObjects(count: Int) -> [Self] {
var objects = [Self]()
for _ in 0 ..< count {
objects.append(Self())
}
return objects
}
*/
// generic also does not work. this returns a base class object.
static func createSubclassObjectByGeneric<T: Base>() -> T {
return T()
}
}
class Sub: Base {
override func f() {
print("sub class")
}
}
print(Sub().f())
// sub class・
print(Sub.createSubclassObject().f())
// base class
Sub.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
print(Sub.createSubclassObjectByGeneric().f())
// base class
You need to return Self, not Base.
static func createSubclassObject() -> Self {
.init()
}
required init() { }
Also, don't use a for loop. There is an array initializer premade for what you're doing.
static func createSubclassObjects(count: Int) -> [Base] {
.init(repeating: createSubclassObject(), count: count)
}
The following code works. But I think there should be better solutions because I don't want to define class func sub() in the parent class and override class func sub() in each sub class.
EDIT: See the Jessy's answer, which is the better solution.
class Base {
func f() {
print("base class")
}
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
//objects.append(Base())
objects.append(Self.sub())
}
return objects
}
class func sub() -> Base {
Base()
// or use fatalError() if you don't need to call createSubclassObjects(count: Int) from the base class
}
}
class Sub1: Base {
override func f() {
print("sub1 class")
}
override class func sub() -> Base {
Sub1()
}
}
class Sub2: Base {
override func f() {
print("sub2 class")
}
override class func sub() -> Base {
Sub2()
}
}
Base.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
Sub1.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub1 class
// sub1 class
Sub2.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub2 class
// sub2 class

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"

Writing a common subject-observer implementation in Swift

Let's say I have a class that implements a beautiful subject-observer pattern thus. (This is Swift 3; Swift 2 would be no different in essence.)
protocol Delegate : class
{
func method()
}
class Subject
{
private typealias WeakDelegate = WeakReference< Delegate >
private var nextAvailableDelegateId = 0
private var delegates = [ Int : WeakDelegate ]()
#discardableResult
public func addDelegate( _ delegate: Delegate ) -> Int
{
let id = nextAvailableDelegateId
nextAvailableDelegateId += 1
delegates[ id ] = WeakDelegate( value: delegate )
return id
}
public func removeDelegate( _ idForDelegate: Int )
{
delegates.removeValue( forKey: idForDelegate )
}
fileprivate func eachDelegate( fn: (Delegate) -> Void )
{
for (key, weakDelegate) in delegates
{
// Has this weak delegate reference become nil?
//
guard let delegate = weakDelegate.value else
{
// Yes. Remove it.
delegates.removeValue( forKey: key )
continue
}
fn( delegate )
}
}
private func exampleNotifier()
{
eachDelegate{ $0.method() }
}
}
(I'm taking the idiomatic Swift term "delegate" as roughly equivalent to the design pattern concept "observer".)
The WeakReference type above isn't strictly speaking part of this question, but in case you're curious:
public class WeakReference< T >
{
public var value: T?
{
return abstractValue as? T
}
public init( value: T )
{
abstractValue = value as AnyObject
}
private weak var abstractValue: AnyObject?
}
Now I want to create another class analogous to Subject with another delegate protocol analogous to Delegate. How do I use the implementation I've already written for Subject in the new class?
One answer is to copy and paste the code. Not a good answer.
In C++ we could create a true mixin, a class that contains all the code and data necessary to implement the Subject, templated on a generic Delegate type, and inherit from it wherever we want to make some other class act as a Subject. Quite trivial.
Protocols, protocol extensions, and generics seem to have some of the machinery necessary for this kind of code reuse, but I can't work out how to accomplish it.
Help?
You can use protocol inheritance and generics to derive from some basic protocol.
Each new delegate will inherit from a parent class:
protocol Delegate: class {
func method()
}
protocol DelegateA: Delegate { }
protocol DelegateB: Delegate { }
Your parent subject class can be implemented using a generic conforming to your parent protocol.
class Subject<T: Delegate> {
private typealias WeakDelegate = WeakReference<T>
private var nextAvailableDelegateId = 0
private var delegates = [Int: WeakDelegate]()
#discardableResult
public func addDelegate(_ delegate: T) -> Int {
let id = nextAvailableDelegateId
nextAvailableDelegateId += 1
delegates[id] = WeakDelegate( value: delegate )
return id
}
public func removeDelegate(_ idForDelegate: Int) {
delegates.removeValue(forKey: idForDelegate)
}
fileprivate func eachDelegate( fn: (T) -> Void ) {
for (key, weakDelegate) in delegates {
// Has this weak delegate reference become nil?
guard let delegate = weakDelegate.value else {
// Yes. Remove it.
delegates.removeValue( forKey: key )
continue
}
fn( delegate )
}
}
private func exampleNotifier() {
eachDelegate{ $0.method() }
}
}
Each new subject can be instantiated as a generic conforming to your child delegates.
class SubjectA<T: DelegateA>: Subject<T> { }
class SubjectB<T: DelegateB>: Subject<T> { }

Swift: overriding typealias inside subclass

So I was thinking about a custom pattern in my project, but I can't get it to work. The main idea is to change the typealias on every subclass to get access to the subclass specific interface.
protocol InstanceInterface: class {
typealias Interface
var interface: Interface { get }
}
// Baseclass
protocol FirstClassInterface: class { /* nothing here for the example */ }
class FirstClass: InstanceInterface, FirstClassInterface {
typealias Interface = FirstClassInterface
var interface: Interface { return self }
}
// Subclass
protocol SecondClassInterface: FirstClassInterface {
func foo()
}
class SecondClass: FirstClass, SecondClassInterface {
typealias Interface = SecondClassInterface // <--- This does nothing :(
func foo() { print("hello world") } // Swift 2.0 here
}
// Lets say I want to call foo trough the interface
let test = SecondClass()
test.interface.foo() // 'Interface' does not have a member named 'foo'
Is there something I'm doing wrong or do I misunderstand some Swift concepts here?! I do need to subclass here to not to implement everything from super class' protocols over and over again. Is my little pattern even possible? I'd appreciate any help. :)
Would something like this work for your purposes?
class MyClass<T> {
}
class MySubclass1: MyClass<String> {
}
class MySubclass2: MyClass<Int> {
}
Unfortunately there is no good workaround for this problem.
The main idea to override the typealias would work in this case but consider the following:
protocol TakeAndGet {
typealias T
func take(value: T)
func get() -> T
}
class FirstClass: TakeAndGet {
typealias T = FirstClass
var property = 0
func take(value: T) {
value.property = 4
}
func get() -> T {
return FirstClass()
}
}
class SecondClass: FirstClass {
typealias T = SecondClass
var property2 = "hello"
}
If the typealias of the SecondClass overrides the other one the take method would work since it takes a subclass which can be treated as the superclass. But the get method cannot implicitly convert FirstClass to SecondClass. Therefore it is not possible to override a typealias.
Now if we want to override the get function with get() -> SecondClass it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get method which results in an ambiguous use:
SecondClass().get() // which type gets returned? SecondClass or FirstClass
So you have to try a different approach.

Swift delegate for a generic class

I have a class that needs to call out to a delegate when one of its properties changes. Here are the simplified class and protocol for the delegate:
protocol MyClassDelegate: class {
func valueChanged(myClass: MyClass)
}
class MyClass {
weak var delegate: MyClassDelegate?
var currentValue: Int {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: Int) {
currentValue = initialValue
}
}
This all works just fine. But, I want to make this class generic. So, I tried this:
protocol MyClassDelegate: class {
func valueChanged(genericClass: MyClass)
}
class MyClass<T> {
weak var delegate: MyClassDelegate?
var currentValue: T {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: T) {
currentValue = initialValue
}
}
This throws two compiler errors. First, the line declaring valueChanged in the protocol gives: Reference to generic type 'MyClass' requires arguments in <...>. Second, the call to valueChanged in the didSet watcher throws: 'MyClassDelegate' does not have a member named 'valueChanged'.
I thought using a typealias would solve the problem:
protocol MyClassDelegate: class {
typealias MyClassValueType
func valueChanged(genericClass: MyClass<MyClassValueType>)
}
class MyClass<T> {
weak var delegate: MyClassDelegate?
var currentValue: T {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: T) {
currentValue = initialValue
}
}
I seem to be on the right path, but I still have two compiler errors. The second error from above remains, as well as a new one on the line declaring the delegate property of MyClass: Protocol 'MyClassDelegate' can only be used as a generic constraint because it has Self or associated type requirements.
Is there any way to accomplish this?
It is hard to know what the best solution is to your problem without having more information, but one possible solution is to change your protocol declaration to this:
protocol MyClassDelegate: class {
func valueChanged<T>(genericClass: MyClass<T>)
}
That removes the need for a typealias in the protocol and should resolve the error messages that you've been getting.
Part of the reason why I'm not sure if this is the best solution for you is because I don't know how or where the valueChanged function is called, and so I don't know if it is practical to add a generic parameter to that function. If this solution doesn't work, post a comment.
You can use templates methods with type erasure...
protocol HeavyDelegate : class {
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R
}
class Heavy<P, R> {
typealias Param = P
typealias Return = R
weak var delegate : HeavyDelegate?
func inject(p : P) -> R? {
if delegate != nil {
return delegate?.heavy(self, shouldReturn: p)
}
return nil
}
func callMe(r : Return) {
}
}
class Delegate : HeavyDelegate {
typealias H = Heavy<(Int, String), String>
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R {
let h = heavy as! H // Compile gives warning but still works!
h.callMe("Hello")
print("Invoked")
return "Hello" as! R
}
}
let heavy = Heavy<(Int, String), String>()
let delegate = Delegate()
heavy.delegate = delegate
heavy.inject((5, "alive"))
Protocols can have type requirements but cannot be generic; and protocols with type requirements can be used as generic constraints, but they cannot be used to type values. Because of this, you won't be able to reference your protocol type from your generic class if you go this path.
If your delegation protocol is very simple (like one or two methods), you can accept closures instead of a protocol object:
class MyClass<T> {
var valueChanged: (MyClass<T>) -> Void
}
class Delegate {
func valueChanged(obj: MyClass<Int>) {
print("object changed")
}
}
let d = Delegate()
let x = MyClass<Int>()
x.valueChanged = d.valueChanged
You can extend the concept to a struct holding a bunch of closures:
class MyClass<T> {
var delegate: PseudoProtocol<T>
}
struct PseudoProtocol<T> {
var valueWillChange: (MyClass<T>) -> Bool
var valueDidChange: (MyClass<T>) -> Void
}
Be extra careful with memory management, though, because blocks have a strong reference to the object that they refer to. In contrast, delegates are typically weak references to avoid cycles.