Generic controller in swift 2.0 using storyboards

后端 未结 4 1775
名媛妹妹
名媛妹妹 2020-12-08 04:35

Im trying to create a GenericListController for my app.

I have a ProductListController that extend this generic controller which extends UIViewController. I have

4条回答
  •  天涯浪人
    2020-12-08 05:39

    This answers why it is not possible : use a generic class as a custom view in interface builder

    Interface Builder "talks" to your code through the ObjC runtime. As such, IB can can access only features of your code that are representable in the ObjC runtime. ObjC doesn't do generics

    This hint at a possible work around : generics in obj-c Maybe you can create a generic ViewController in obj-c and then IB will accept it?

    Have you considered using a protocol? This doesn't upset the storyboard. Changed the code a bit to make it easily testable. The downside of this is that you can't have stored properties in a protocol. So you would still need to copy paste those. Upside is that it works.

    protocol GenericListProtocol {       
        typealias T
        var list : [T] { get set }
        var filteredlist : [T] { get set }
        func setData(list : [T])        
    }    
    extension GenericListProtocol {        
        func setData(list: [T]) {
            list.forEach { item in print(item) }
        }        
    }
    
    class ProductModel {        
        var productID : Int = 0        
        init(id:Int) {
            productID = id
        }        
    }    
    
    class ProductListController: UIViewController, GenericListProtocol {
    
        var list : [ProductModel] = [ProductModel(id: 1),ProductModel(id: 2),ProductModel(id: 3),ProductModel(id: 4)]
        var filteredlist : [ProductModel] = []
    
        override func viewDidLoad() {            
            super.viewDidLoad()            
            setData(list)            
        }
    }
    

    Update: Allow some access to attributes to the generic class. Changed it to a basic class to easily test in a Playground. UIViewController stuff is in the code above.

    class ProductModel {        
        var productID : Int = 0        
        init(id:Int) {
            productID = id
        }        
    }
    
    class ProductA : ProductModel {
        var aSpecificStuff : Float = 0
    }    
    
    class ProductB : ProductModel {
        var bSpecificStuff : String = ""
    }
    
    protocol GenericListProtocol {        
        typealias T = ProductModel
        var list : [T] { get set }
        var filteredlist : [T] { get set }
        func setData(list : [T])        
    }
    
    extension GenericListProtocol {        
        func setData(list: [T]) {
            list.forEach { item in
                guard let productItem = item as? ProductModel else {
                    return
                }
                print(productItem.productID)
            }
        }        
    }
    
    
    class ProductListController: GenericListProtocol {
    
        var list : [ProductA] = [ProductA(id: 1),ProductA(id: 2),ProductA(id: 3),ProductA(id: 4)]
        var filteredlist : [ProductA] = []
    
        init() {            
            setData(list)            
        }
    }
    
    var test = ProductListController()
    

提交回复
热议问题