Swift Generics and Protocols Not Working on Uikit [Possible Bug]

Swift Generics and Protocols not working on UIKit [possible bug]

That's correct behavior from the documentation point of view, because:

Method in a generic class cannot be represented in Objective-C


Reply to @Bell App Lab comment:

Open this page and scroll down to Lightweight Generics. Here's note:

Aside from than these Foundation collection classes, Objective-C
lightweight generics are ignored by Swift. Any other types using
lightweight generics are imported into Swift as if they were
unparameterized.

It basically says that generics (ObjC -> Swift) are imported only for Foundation collection classes and rest is ignored - IOW imported as if they are unparameterized.

Maybe we can expect some improvement in this area in the future, but I doubt it.

Swift Generics and Protocol Extensions

That's an interesting problem. Your code seems like it should work; you might want to file an enhancement request.

Here's a workaround that seems to work correctly:

class SomeGenericClass<CellType: Cell> {
func someFunction() {
let reuseIdentifier = (CellType.self as Reusable.Type).reuseId()
}
}

EXC_BAD_ACCESS when creating an object with Generics, Protocols and Inheritance in Swift

Update Swift 1.2 XCode 6.3 Beta 2 (Beta 1 will not work):
Your code now runs without any problems and the expected result:

var b = creation(x: B.self); //{__lldb_expr_9.SecondBase}
var a = creation(x: A.self); //{__lldb_expr_11.FirstBase}

They conflict because FirstBase has no init but EmptyInit a required init.
This way it will work:

protocol EmptyInit {
init();
}

class FirstBase {
required init(){

}
}

class SecondBase : EmptyInit {
required init(){

}
}

class A : FirstBase, EmptyInit{
required init(){

}
}

class B : SecondBase, EmptyInit {
required init() {

}
}

A();
B();

func creation<T: EmptyInit>(x a:T.Type) -> T{
var object = T()
return object;
}

var b = creation(x: B.self); // SecondBase
var a = creation(x: A.self); // FirstBase

Is it possible to pass generic protocols into a constructor for proper Dependency Injection in Swift 3?

The answer to your question is yes it is definitely possible, just that it currently requires some PAT-related "magic". With Swift3 and Xcode 8.0 beta 4, you should be able to run the following in a playground:

protocol Persistable {
var id: Int { get set }
}
protocol RepositoryProtocol: class {
associatedtype Object: Persistable
func insert(_ object: Object) -> Void
func deleteAll()
}
protocol ZombieServiceProtocol {
associatedtype RepositoryType: RepositoryProtocol
var zombieRepository: RepositoryType { get set }
func fetchZombies()
}
public struct Zombie: Persistable {
var id: Int
let name: String?
}

// Mocks
class RepositoryMock<Object: Persistable>: RepositoryProtocol {
func insert(_ object: Object) { print("look, there's another one!")}
func deleteAll() { print("it's safe out there, all zombies have been deleted") }
}
struct ZombieServiceMock<RepositoryType: RepositoryProtocol
where RepositoryType.Object == Zombie>: ZombieServiceProtocol {
var zombieRepository: RepositoryType
init(zombieRepository: RepositoryType) {
self.zombieRepository = zombieRepository
}
func fetchZombies() {
self.zombieRepository.deleteAll()
self.createMockZombies()
}
private func createMockZombies() {
for index in 1...5 {
let zombie = Zombie(id: index, name: "Zombie \(index)")
self.zombieRepository.insert(zombie)
}
}
}

// Tests
class ZombieServiceTests<RepositoryType: RepositoryProtocol,
ServiceType: ZombieServiceProtocol
where ServiceType.RepositoryType == RepositoryType> {
private var zombieRepository: RepositoryType
private var zombieService: ServiceType

init(repository: RepositoryType, service: ServiceType) {
zombieRepository = repository
zombieService = service
}
func testExample() {
self.zombieService.fetchZombies()
}
}
let repositoryMock = RepositoryMock<Zombie>()
let repositoryService = ZombieServiceMock(zombieRepository: repositoryMock)
let zombieTest = ZombieServiceTests(repository: repositoryMock, service: repositoryService)
zombieTest.testExample()

// Prints:
// it's safe out there, all zombies have been deleted
// look, there's another one!
// look, there's another one!
// look, there's another one!
// look, there's another one!
// look, there's another one!


Related Topics



Leave a reply



Submit