Swift generics method in EXC_BAD_ACCESS - swift

I'm stuck about generics, and generic methods in swift.
Why this code that uses Swift generics method, gives EXC_BAD_ACCESS when invoking method1?
You can test it using Playground.
import UIKit
import Foundation
protocol SomeProtocol {
func printMe()
}
class SomeClass : SomeProtocol {
let value : String
init(value: String) {
self.value = value
}
func printMe() {
print("\(value)")
}
}
class BaseClass {
func method1<T>(_ param: T) {
print("passing into method 1 with param: \(param)")
method2(param)
}
func method2<T>(_ param: T) {
}
}
class ConcreteClass : BaseClass {
override func method2<T>(_ param: T) where T : SomeProtocol {
print("passing into method 2 with param: \(param.printMe())")
}
}
let someClass = SomeClass(value: "Hi")
let obj = ConcreteClass()
obj.method1(someClass)

The fact that you've managed to override the method with where closure without a compilation error really looks like a bug.
But there is a workaround for your use case:
class ConcreteClass : BaseClass {
override func method2<T>(_ param: T) {
print("Base param \(param)")
if let printable = param as? SomeProtocol {
printable.printMe()
}else {
super.method2(param)
}
}
}

Related

Implement Decorator Pattern with generics in Swift

I am new to Swift, but I have plenty of experience in other languages like Java, Kotlin, Javascript, etc. It's possible that what I want to do is not supported by the language, and I've poured over the Swift Language Guide looking for the answer.
I want to implement the decorator pattern, using generics. I easily did this in Kotlin, and I'm porting the library to Swift.
class Result<T> {
let result: T?
let error: NSError?
init(result: T?, error: NSError?) {
self.result = result
self.error = error
}
}
protocol DoSomething {
associatedtype T
func doSomething() -> Result<T>
}
protocol StoreSomething {
associatedtype T
func storeSomething(thing: Result<T>)
}
/*
* DOES NOT COMPILE
*/
class StoringSomething<T> {
private let delegate: DoSomething
private let store: StoreSomething
init(delegate: DoSomething, store: StoreSomething) {
self.delegate = delegate
self.store = store
}
func doSomething() -> Result<T> {
let result = delegate.doSomething()
store.storeSomething(thing: result)
return result
}
}
I get a Protocol 'DoSomething' can only be used as a generic constraint because it has Self or associated type requirements error from the compiler. I've tried using a typealias and other ideas from SO and the Swift manual.
Thanks to #Sweeper's suggestion on associatedtype erasure you can implement the Decorator pattern with generics like so:
class AnyDoSomething<T>: DoSomething {
func doSomething() -> Result<T> {
fatalError("Must implement")
}
}
class AnyStoreSomething<T>: StoreSomething {
func storeSomething(thing: Result<T>) {
fatalError("Must implement")
}
}
class StoringSomething<T>: DoSomething {
private let delegate: AnyDoSomething<T>
private let store: AnyStoreSomething<T>
init(delegate: AnyDoSomething<T>, store: AnyStoreSomething<T>) {
self.delegate = delegate
self.store = store
}
func doSomething() -> Result<T> {
let result = delegate.doSomething()
store.storeSomething(thing: result)
return result
}
}
class DoSomethingNice<T>: AnyDoSomething<T> {
override func doSomething() -> Result<T> {
}
}

Apple way in Swift instead of an override?

what approach does Apple use in Swift instead of override, how can I write this without using the #objc marker
import Foundation
class A {
init() {}
}
extension A {
#objc func foo() {
print("foo")
}
}
class B: A {
override func foo() {
print("yes2")
}
}
A().foo()
B().foo()
maybe protocols? but how?
You can define a protocol and provide a default method implementation. Then all you need is to comform to that protocol and provide its own foo method if necessary:
protocol Fooable {
func foo()
}
extension Fooable {
func foo() {
print("default implementation")
}
}
class A: Fooable { }
class B: A {
func foo() {
print("B implementationn")
}
}
let a = A()
let b = B()
a.foo()
b.foo()
This will print
default implementation
B implementationn

Using swift Generic Types with protocols

I've tried to use generic type with protocol:
class Weak<T: AnyObject> {
weak var value: AnyObject?
init (value: AnyObject) {
self.value = value
}
}
protocol SomeProtocol: AnyObject {
func doSomething()
}
func createWeak(object: SomeProtocol) -> Weak<SomeProtocol> {
return Weak<SomeProtocol>(value: object)
}
class SomeClass: SomeProtocol {
func doSomething() {
print("Some 2")
}
}
let temp = SomeClass()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()
And got the compiler error:
error: 'SomeProtocol' is not convertible to 'AnyObject'
return Weak(value: object)
But without AnyObject constraint it works fine
class Weak<T> {
var value: T?
init (value: T) {
self.value = value
}
}
protocol Protocol {
func doSomething()
}
class Class: Protocol {
func doSomething() {
print("This is class")
}
}
func createWeak(object: Protocol) -> Weak<Protocol> {
return Weak(value: object)
}
let temp = Class()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()
Why I can't use protocols inherited form AnyObject in generic classes?
Swift protocols are incomplete types, which means that you can't use them in places like generic arguments, as the compiler needs to know the whole type details so it can allocate the proper memory layout.
Your createWeak function can still be used if you make it generic:
func createWeak<T: SomeProtocol>(object: T) -> Weak<T> {
return Weak<T>(value: object)
}
The above code works because the compiler will generate at compile time a function mapped to the concrete type you pass.
Even better, you can make the initializer generic, and convert Weak to a struct (value types are preferred Swift over reference ones):
struct Weak<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
which you can use it instead of the free function:
let weakRef = Weak(temp)

Pass class as param into function which returns an object of this type in swift?

I need to write something like this:
func createInstanceOfClass(someClass: Class) -> UIViewController {
var vc = someClass()
//some initialization
...
//
return
}
I found some similar questions but some of them are not appropriate for this task, some about param T which seems to be extra.
Here is an example of how you might do this. Use T.Type to reference the metatype of T, and T.self to reference the type T.
protocol DefaultConstructible {
init()
}
class A: DefaultConstructible {
required init() {}
}
struct B: DefaultConstructible {
init() {}
}
func makeAnInstance<T: DefaultConstructible>(of c: T.Type) -> T {
return c.init()
}
let a = makeAnInstance(of: A.self)
let b = makeAnInstance(of: B.self)

Generic Observer Pattern in Swift using Protocols gives Segmentation Fault

import Foundation
class IProtocol {
func meth1(arg: Int){}
}
class IObserver: IProtocol {
private var className: String
init(name: String) {
className = name
}
override func meth1(arg: Int) {
print(className, ":", arg)
}
}
class Notifier<T> {
private var listOfObservers = NSMutableArray()
func addObserver(observer: T) {
listOfObservers.add(observer)
}
func callObservers<ARG, RET>(function: (T)->(ARG)->RET, arg: ARG) {
for obj in listOfObservers {
let observer = obj as! T
_ = function(observer)(arg)
}
}
}
let a = IObserver(name: "First I Observer")
let b = IObserver(name: "Second I Observer")
let n = Notifier<IProtocol>()
n.addObserver(observer: a)
n.addObserver(observer: b)
n.callObservers(function: IProtocol.meth1, arg: Int(1))
OUTPUT
First I Observer: 1
Second I Observer: 1
The above example fails and does not build giving Command failed due to signal: Segmentation Fault: 11, when I change IProtocol to protocol from class. I have different protocols and different observer classes confirming those protocols. I am trying to implement a Notifier class that notifies the observers by taking the method from the protocol and arguments to be passed for that method.It will be great, if someone can explain what am I doing wrong!
I am using Swift 3 and Xcode 8.2
As of today, Swift does not handle direct references to protocol methods:
protocol IProtocol {
func meth1()
}
class IObserver: IProtocol {
func meth1() { print("success") }
}
let x = IProtocol.meth1 // This causes the compiler crash
x(IObserver())()
And coming to the solution for my problem was to pass a closure instead of the method. This is how it looks:
import Foundation
protocol IProtocol {
func meth1(arg: Int)
}
class IObserver: IProtocol {
private var className: String
init(name: String) {
className = name
}
func meth1(arg: Int) {
print(className, ":", arg)
}
}
class Notifier<T> {
private var listOfObservers = NSMutableArray()
func addObserver(observer: T) {
listOfObservers.add(observer)
}
func callObservers<ARG>(function: (T, ARG) -> (), arg: ARG) {
for obj in listOfObservers {
let observer = obj as! T
function(observer, arg)
}
}
}
let a = IObserver(name: "First I Observer")
let b = IObserver(name: "Second I Observer")
let n = Notifier<IProtocol>()
n.addObserver(observer: a)
n.addObserver(observer: b)
n.callObservers(function: {obs, ar in
obs.meth1(arg: ar)
}, arg: Int(1))