Search code examples
iosswiftgenericsassociated-types

Swift: using instance of a generic type associatedtype segfaults compiler


I'm getting a segmentation fault when I try to compile the below code. I'm trying to make a type constrained extension on the CellUpdater struct, which accesses a property whose type is defined on an associatedtype on a generic type. Not sure if I'm doing something wrong or if it's a limitation of the Swift compiler, any ideas?

protocol CellUpdaterType {
    func generateDetailsDrillDownController(index: Int) -> UIViewController?
}

extension CellUpdaterType {
    func generateDetailsDrillDownController(index: Int) -> UIViewController? { return nil }
}


struct CellUpdater<Cell where Cell: UpdatableView> : CellUpdaterType {
    let viewModel: Cell.ViewModel
}

extension CellUpdater where Cell: HeadlineCell {
    func generateDetailsDrillDownController(index: Int) -> UIViewController? {
        let storyboard = UIStoryboard(name: "SomeStoryboard", bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("SomeViewController") as? SomeViewController
        vc?.headline = viewModel.headline // This line crashes the compiler
        return vc
    }
}

class HeadlineCell: UITableViewCell {
    var headline: Headline?
    // ...
}


extension HeadlineCell : UpdatableView {
    typealias ViewModel = HeadlineCellViewModel
    func update(viewModel viewModel: ViewModel) {
    // ...
    }
}


struct HeadlineCellViewModel {
    let headline: Headline

    init(headline: Headline) {
        self.headline = headline
    }
}

protocol UpdatableView: class {
    associatedtype ViewModel
    func update(viewModel viewModel: ViewModel)
}

Solution

  • I think it might be connected to compiler not being able to fix your view model type at compile time, which is required in Swift. It might have been fixed in Swift 3.0 though. I've manage to change your code a little so it now compiles. The major difference was to constraint view model instead of cell in CellUpdater extension.

    struct CellUpdater<Cell where Cell: UpdatableView> : CellUpdaterType {
        typealias ViewModel = Cell.ViewModel
    
        let viewModel: ViewModel
    }
    
    extension CellUpdater where Cell.ViewModel : HeadlineCellViewModelType {
        func generateDetailsDrillDownController(index: Int) -> UIViewController? {
            let storyboard = UIStoryboard(name: "SomeStoryboard", bundle: nil)
            let vc = storyboard.instantiateViewControllerWithIdentifier("SomeViewController") as? SomeViewController
            vc?.headline = viewModel.headline
            return vc
        }
    }
    
    protocol HeadlineCellViewModelType {
        var headline: Headline { get }
    }
    
    struct HeadlineCellViewModel : HeadlineCellViewModelType {
        let headline: Headline
    
        init(headline: Headline) {
            self.headline = headline
        }
    }