Генератор общего вида не может определить тип swift - PullRequest
0 голосов
/ 29 апреля 2018

нужно немного потрудиться, чтобы мой генератор общего вида работал.

Идея состоит в том, чтобы иметь множество различных конкретных настроек вида. чтобы сгенерировать результирующие представления, я сделал функцию в приведенной ниже таблице.

но он не может определить правильный тип ячейки. Кто-нибудь может дать мне подсказку?

//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport

// Protocols
protocol SettingType {
    var color: UIColor { get }
}
protocol CellType {
    func configure(with setting: SettingType)
}

//  Concrete Settings
final class Concrete1Setting: SettingType {
    var color: UIColor = .blue
}

final class Concrete2Setting: SettingType {
    var color: UIColor = .green
}

//  Concrete Cells
final class Concrete1Cell: UIView, CellType {
    func configure(with setting: SettingType) {
        print("Configured Cell 1")
        self.backgroundColor = setting.color
    }
}

final class Concrete2Cell: UIView, CellType {
    func configure(with setting: SettingType) {
        print("Configured Cell 2")
        self.backgroundColor = setting.color
    }
}

//  Generic generator
func makeConcreteCell<S: SettingType, T: CellType>(_ setting: S) -> T {
    switch setting {
    case is Concrete1Setting:
        return Concrete1Cell() as! T
    case is Concrete2Setting:
        return Concrete2Cell() as! T
    default: fatalError()
    }
}

// Test
var cells: [CellType] = [Concrete1Cell(), Concrete2Cell()]
let settings: [SettingType] = [Concrete1Setting(), Concrete2Setting()]
for setting in settings {
    cells.append(makeConcreteCell(setting))         // CompileError: Generic parameter 'S' could not be inferred
}
// expect array equal to [Concrete1Cell, Concrete2Cell]

1 Ответ

0 голосов
/ 29 апреля 2018

Вам не нужна универсальная функция для makeConcreteCell. Просто возьми и верни прототипы:

func makeConcreteCell(_ setting: SettingType) -> CellType {
    switch setting {
    case is Concrete1Setting:
        return Concrete1Cell()
    case is Concrete2Setting:
        return Concrete2Cell()
    default: fatalError()
    }
}

Обобщения используются, когда вы хотите, чтобы компилятор написал определенную функцию для каждого конкретного типа. Это не то, что вам нужно здесь. Одна функция работает.


Вы хотите использовать CellType s как UIView s.

Создайте базовый класс с именем CellTypeClass, который является UIView и принимает протокол CellType:

// Protocols
protocol SettingType {
    var color: UIColor { get }
}
protocol CellType {
    func configure(with setting: SettingType)
}

//  Concrete Settings
final class Concrete1Setting: SettingType {
    var color: UIColor = .blue
}

final class Concrete2Setting: SettingType {
    var color: UIColor = .green
}

class CellTypeClass: UIView, CellType {
    func configure(with setting: SettingType) {
        fatalError("You must override this function")
    }
}

//  Concrete Cells
final class Concrete1Cell: CellTypeClass {
    override func configure(with setting: SettingType) {
        print("Configured Cell 1")
        self.backgroundColor = setting.color
    }
}

final class Concrete2Cell: CellTypeClass {
    override func configure(with setting: SettingType) {
        print("Configured Cell 2")
        self.backgroundColor = setting.color
    }
}

//  Generic generator
func makeConcreteCell(_ setting: SettingType) -> CellTypeClass {
    switch setting {
    case is Concrete1Setting:
        return Concrete1Cell()
    case is Concrete2Setting:
        return Concrete2Cell()
    default: fatalError()
    }
}

// Test
var cells: [CellTypeClass] = [Concrete1Cell(), Concrete2Cell()]
let settings: [SettingType] = [Concrete1Setting(), Concrete2Setting()]
for setting in settings {
    cells.append(makeConcreteCell(setting))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...