Swift - Inheriting UIViewController from a generic base class that is also a UIViewController









up vote
0
down vote

favorite












So I have a base class, DataViewController<T>, which inherits from UITableViewController as follows:



class DataTableViewController<T : BMPage<BMData>> : UITableViewController, UISearchBarDelegate 
// implementations...



I also have a TournamentsViewController which inherits from DataViewController with the generics passed in:



class TournamentsViewController: DataTableViewController<TournamentPage> 
// overrides, etc.



For reference, here are BMPage<T>:



open class BMPage<T : Codable> : Decodable 

public enum CodingKeys: String, CodingKey
case data


var data : [T]

required public init(from decoder:Decoder) throws
let vals = try decoder.container(keyedBy: CodingKeys.self)
data = try vals.decode([T].self, forKey: .data)



extension BMPage: Encodable
public func encode(to encoder: Encoder) throws
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(data, forKey: .data)




... and BMData:



open class BMData : Codable 

public enum CodingKeys: CodingKey
case id
case name


var id: Int
var name: String

required public init(from decoder:Decoder) throws
let vals = try decoder.container(keyedBy: CodingKeys.self)
id = try vals.decode(Int.self, forKey: .id)
name = try vals.decode(String.self, forKey: .name)




What I'm trying to achieve: various UITableViewController subclasses that just need to specify generics in order to specify their specific data. Here are my Tournament and TournamentPage implementations which should better explain this concept:



open class Tournament : BMData 
let game_id: Int = 0
let game_iteration_id: Int = 0
let state: Int = 0
let starts_at: String = ""
let creator_id: Int = 0
let stream_url: String? = nil
let entrant_count: Int = 0
let prereg_count: Int = 0
let path: String = ""


open class TournamentPage : BMPage<BMData>
public enum CodingKeys: String, CodingKey
case data = "tournaments"


let page: String? = nil
let results_per_page: String = ""
let tournament_count: Int = 0



The problem: the compiler doesn't like that I'm doing this as it's throwing multiple, yet very similar errors such as:



  • Cannot convert return expression of type 'TournamentsViewController'
    to return type 'UIViewController'

  • Cannot convert return expression of type
    'TournamentsViewController?' to return type 'UIViewController?'

Here is an example of such an expression (taken from the default ModelController that XCode threw in there, which is where all of these errors occur:



 let dataViewController = storyboard.instantiateViewController(withIdentifier: "DataViewController") as! TournamentsViewController


Is there a way to achieve what I am trying to do? I'll admit, I am new to Swift (only started learning it this week), so maybe I'm completely misunderstanding typical Swift practices and just what it was designed to do, but achieving this in a language such as C# (and probably even Objective-C, though I'm a bit rusty on it as it's been a while since I've last used it) is pretty much what I'm doing here.










share|improve this question



























    up vote
    0
    down vote

    favorite












    So I have a base class, DataViewController<T>, which inherits from UITableViewController as follows:



    class DataTableViewController<T : BMPage<BMData>> : UITableViewController, UISearchBarDelegate 
    // implementations...



    I also have a TournamentsViewController which inherits from DataViewController with the generics passed in:



    class TournamentsViewController: DataTableViewController<TournamentPage> 
    // overrides, etc.



    For reference, here are BMPage<T>:



    open class BMPage<T : Codable> : Decodable 

    public enum CodingKeys: String, CodingKey
    case data


    var data : [T]

    required public init(from decoder:Decoder) throws
    let vals = try decoder.container(keyedBy: CodingKeys.self)
    data = try vals.decode([T].self, forKey: .data)



    extension BMPage: Encodable
    public func encode(to encoder: Encoder) throws
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(data, forKey: .data)




    ... and BMData:



    open class BMData : Codable 

    public enum CodingKeys: CodingKey
    case id
    case name


    var id: Int
    var name: String

    required public init(from decoder:Decoder) throws
    let vals = try decoder.container(keyedBy: CodingKeys.self)
    id = try vals.decode(Int.self, forKey: .id)
    name = try vals.decode(String.self, forKey: .name)




    What I'm trying to achieve: various UITableViewController subclasses that just need to specify generics in order to specify their specific data. Here are my Tournament and TournamentPage implementations which should better explain this concept:



    open class Tournament : BMData 
    let game_id: Int = 0
    let game_iteration_id: Int = 0
    let state: Int = 0
    let starts_at: String = ""
    let creator_id: Int = 0
    let stream_url: String? = nil
    let entrant_count: Int = 0
    let prereg_count: Int = 0
    let path: String = ""


    open class TournamentPage : BMPage<BMData>
    public enum CodingKeys: String, CodingKey
    case data = "tournaments"


    let page: String? = nil
    let results_per_page: String = ""
    let tournament_count: Int = 0



    The problem: the compiler doesn't like that I'm doing this as it's throwing multiple, yet very similar errors such as:



    • Cannot convert return expression of type 'TournamentsViewController'
      to return type 'UIViewController'

    • Cannot convert return expression of type
      'TournamentsViewController?' to return type 'UIViewController?'

    Here is an example of such an expression (taken from the default ModelController that XCode threw in there, which is where all of these errors occur:



     let dataViewController = storyboard.instantiateViewController(withIdentifier: "DataViewController") as! TournamentsViewController


    Is there a way to achieve what I am trying to do? I'll admit, I am new to Swift (only started learning it this week), so maybe I'm completely misunderstanding typical Swift practices and just what it was designed to do, but achieving this in a language such as C# (and probably even Objective-C, though I'm a bit rusty on it as it's been a while since I've last used it) is pretty much what I'm doing here.










    share|improve this question

























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      So I have a base class, DataViewController<T>, which inherits from UITableViewController as follows:



      class DataTableViewController<T : BMPage<BMData>> : UITableViewController, UISearchBarDelegate 
      // implementations...



      I also have a TournamentsViewController which inherits from DataViewController with the generics passed in:



      class TournamentsViewController: DataTableViewController<TournamentPage> 
      // overrides, etc.



      For reference, here are BMPage<T>:



      open class BMPage<T : Codable> : Decodable 

      public enum CodingKeys: String, CodingKey
      case data


      var data : [T]

      required public init(from decoder:Decoder) throws
      let vals = try decoder.container(keyedBy: CodingKeys.self)
      data = try vals.decode([T].self, forKey: .data)



      extension BMPage: Encodable
      public func encode(to encoder: Encoder) throws
      var container = encoder.container(keyedBy: CodingKeys.self)
      try container.encode(data, forKey: .data)




      ... and BMData:



      open class BMData : Codable 

      public enum CodingKeys: CodingKey
      case id
      case name


      var id: Int
      var name: String

      required public init(from decoder:Decoder) throws
      let vals = try decoder.container(keyedBy: CodingKeys.self)
      id = try vals.decode(Int.self, forKey: .id)
      name = try vals.decode(String.self, forKey: .name)




      What I'm trying to achieve: various UITableViewController subclasses that just need to specify generics in order to specify their specific data. Here are my Tournament and TournamentPage implementations which should better explain this concept:



      open class Tournament : BMData 
      let game_id: Int = 0
      let game_iteration_id: Int = 0
      let state: Int = 0
      let starts_at: String = ""
      let creator_id: Int = 0
      let stream_url: String? = nil
      let entrant_count: Int = 0
      let prereg_count: Int = 0
      let path: String = ""


      open class TournamentPage : BMPage<BMData>
      public enum CodingKeys: String, CodingKey
      case data = "tournaments"


      let page: String? = nil
      let results_per_page: String = ""
      let tournament_count: Int = 0



      The problem: the compiler doesn't like that I'm doing this as it's throwing multiple, yet very similar errors such as:



      • Cannot convert return expression of type 'TournamentsViewController'
        to return type 'UIViewController'

      • Cannot convert return expression of type
        'TournamentsViewController?' to return type 'UIViewController?'

      Here is an example of such an expression (taken from the default ModelController that XCode threw in there, which is where all of these errors occur:



       let dataViewController = storyboard.instantiateViewController(withIdentifier: "DataViewController") as! TournamentsViewController


      Is there a way to achieve what I am trying to do? I'll admit, I am new to Swift (only started learning it this week), so maybe I'm completely misunderstanding typical Swift practices and just what it was designed to do, but achieving this in a language such as C# (and probably even Objective-C, though I'm a bit rusty on it as it's been a while since I've last used it) is pretty much what I'm doing here.










      share|improve this question















      So I have a base class, DataViewController<T>, which inherits from UITableViewController as follows:



      class DataTableViewController<T : BMPage<BMData>> : UITableViewController, UISearchBarDelegate 
      // implementations...



      I also have a TournamentsViewController which inherits from DataViewController with the generics passed in:



      class TournamentsViewController: DataTableViewController<TournamentPage> 
      // overrides, etc.



      For reference, here are BMPage<T>:



      open class BMPage<T : Codable> : Decodable 

      public enum CodingKeys: String, CodingKey
      case data


      var data : [T]

      required public init(from decoder:Decoder) throws
      let vals = try decoder.container(keyedBy: CodingKeys.self)
      data = try vals.decode([T].self, forKey: .data)



      extension BMPage: Encodable
      public func encode(to encoder: Encoder) throws
      var container = encoder.container(keyedBy: CodingKeys.self)
      try container.encode(data, forKey: .data)




      ... and BMData:



      open class BMData : Codable 

      public enum CodingKeys: CodingKey
      case id
      case name


      var id: Int
      var name: String

      required public init(from decoder:Decoder) throws
      let vals = try decoder.container(keyedBy: CodingKeys.self)
      id = try vals.decode(Int.self, forKey: .id)
      name = try vals.decode(String.self, forKey: .name)




      What I'm trying to achieve: various UITableViewController subclasses that just need to specify generics in order to specify their specific data. Here are my Tournament and TournamentPage implementations which should better explain this concept:



      open class Tournament : BMData 
      let game_id: Int = 0
      let game_iteration_id: Int = 0
      let state: Int = 0
      let starts_at: String = ""
      let creator_id: Int = 0
      let stream_url: String? = nil
      let entrant_count: Int = 0
      let prereg_count: Int = 0
      let path: String = ""


      open class TournamentPage : BMPage<BMData>
      public enum CodingKeys: String, CodingKey
      case data = "tournaments"


      let page: String? = nil
      let results_per_page: String = ""
      let tournament_count: Int = 0



      The problem: the compiler doesn't like that I'm doing this as it's throwing multiple, yet very similar errors such as:



      • Cannot convert return expression of type 'TournamentsViewController'
        to return type 'UIViewController'

      • Cannot convert return expression of type
        'TournamentsViewController?' to return type 'UIViewController?'

      Here is an example of such an expression (taken from the default ModelController that XCode threw in there, which is where all of these errors occur:



       let dataViewController = storyboard.instantiateViewController(withIdentifier: "DataViewController") as! TournamentsViewController


      Is there a way to achieve what I am trying to do? I'll admit, I am new to Swift (only started learning it this week), so maybe I'm completely misunderstanding typical Swift practices and just what it was designed to do, but achieving this in a language such as C# (and probably even Objective-C, though I'm a bit rusty on it as it's been a while since I've last used it) is pretty much what I'm doing here.







      ios swift oop generics inheritance






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 9 at 23:55

























      asked Nov 9 at 23:49









      tayoung

      101110




      101110






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          Have you tried to instantiate view controller like this?
          let viewController = MyTableViewController()
          Than navigationController.pushViewController(viewController, animated: true)
          }






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234700%2fswift-inheriting-uiviewcontroller-from-a-generic-base-class-that-is-also-a-uiv%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            Have you tried to instantiate view controller like this?
            let viewController = MyTableViewController()
            Than navigationController.pushViewController(viewController, animated: true)
            }






            share|improve this answer
























              up vote
              0
              down vote













              Have you tried to instantiate view controller like this?
              let viewController = MyTableViewController()
              Than navigationController.pushViewController(viewController, animated: true)
              }






              share|improve this answer






















                up vote
                0
                down vote










                up vote
                0
                down vote









                Have you tried to instantiate view controller like this?
                let viewController = MyTableViewController()
                Than navigationController.pushViewController(viewController, animated: true)
                }






                share|improve this answer












                Have you tried to instantiate view controller like this?
                let viewController = MyTableViewController()
                Than navigationController.pushViewController(viewController, animated: true)
                }







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 10 at 0:16









                Alastar

                524




                524



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234700%2fswift-inheriting-uiviewcontroller-from-a-generic-base-class-that-is-also-a-uiv%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Use pre created SQLite database for Android project in kotlin

                    Darth Vader #20

                    Ondo