How to resolve designated initialization error for UITableViewController?

喜夏-厌秋 提交于 2019-12-10 14:29:21

问题


I'm new to swift and I'm having problems declaring my initializer in my PlacesTableViewController class. It prompts me "Super.init isn't called before returning from initializer" and when I added the Super.init, it prompts me:

"Must call a designated initializer of the superclass 'UITableViewController'"

this is my PlacesTableViewController.swift file:

class PlacesTableViewController: UITableViewController { 

    var pa55DB : COpaquePointer = nil
    var selectStatement : COpaquePointer = nil;

    var chapterdata : Array<Entry> = []
    var ety : Entry
    var sqlString : String = "";

    var chpData : ChapterData

    init(pa55DB : COpaquePointer,selectStatement : COpaquePointer, chapterdata : Array<Entry>, ety : Entry, sqlString : String) {
        super.init()
        self.pa55DB = pa55DB
        self.selectStatement = selectStatement
        self.chapterdata = chapterdata
        self.ety = ety
        self.sqlString = sqlString

    }

    required init!(coder aDecoder: NSCoder!) {
        fatalError("init(coder:) has not been implemented")
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        chpData = ChapterData(newEntryArray : chapterdata, entryV : ety, paDB55 : pa55DB, selectStatement : selectStatement, sqlString : sqlString)
        chpData.openDB()
        chapterdata = chpData.prepareStartment()

        println("Testing...")
    }
...
}

Here's my another class file called ChapterData.swift, used to open database and retrieve data

class Entry {

    let image : String!
    let heading : String!
    let title : String!
    let description : String!
    public init(image : String, heading : String, title : String, desc : String) {
        self.heading = heading
        self.image = image
        self.title = title
        self.description = desc
    }
}


class ChapterData {

    var paDB : COpaquePointer = nil;
    var selectStatement : COpaquePointer = nil;
    var sqlString : String = "";

    var newEntryArray : Array<Entry> = [];
    var entryV : Entry;

    init(newEntryArray : Array<Entry>, entryV : Entry, paDB55 : COpaquePointer, selectStatement : COpaquePointer, sqlString : String){
        self.newEntryArray = newEntryArray
        self.entryV = entryV
        self.paDB = paDB55
        self.selectStatement = selectStatement
        self.sqlString = sqlString
    }

    func openDB() {
        var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String
        var docsDir = paths.stringByAppendingPathComponent("pa55.sqlite")


        if (sqlite3_open(docsDir, &paDB) == SQLITE_OK) {
            println("success open database")
        }
        else {
            println("failed to open database")
        }
    }

    func prepareStartment() -> Array<Entry>   {
        sqlString = "SELECT * FROM Chapter ORDER BY CID ASC"
        var cSql = sqlString.cStringUsingEncoding(NSUTF8StringEncoding)
        sqlite3_prepare_v2(paDB, cSql!, -1, &selectStatement, nil)

        println("startment start")

        while (sqlite3_step(selectStatement) == SQLITE_ROW) {

            let image_buf = sqlite3_column_text(selectStatement, 3)
            var image = String.fromCString(UnsafePointer<CChar>(image_buf))

            let heading_buf = sqlite3_column_text(selectStatement, 1)
            var heading = String.fromCString(UnsafePointer<CChar>(heading_buf))

            let title_buf = sqlite3_column_text(selectStatement, 2)
            var title = String.fromCString(UnsafePointer<CChar>(title_buf))

            let desc_buf = sqlite3_column_text(selectStatement, 4)
            var description = String.fromCString(UnsafePointer<CChar>(desc_buf))

            entryV = Entry(image: image!, heading: heading!, title: title!, desc: description!)
            newEntryArray.append(entryV)
        }
        println("select statement successful executed")
        return newEntryArray
    }

}

回答1:


The init mess is a known limitation of the ObjC <-> Swift bridging.

One way to work around this is to delegate to super's init(nibName:bundle:) initializer.

class PlacesTableViewController: UITableViewController { 

    var chapterdata: [Entry]
    var chpData: ChapterData?
    var ety: Entry
    var pa55DB: COpaquePointer
    var selectStatement: COpaquePointer
    var sqlString: String


    init(pa55DB: COpaquePointer, selectStatement: COpaquePointer, chapterdata: [Entry], ety: Entry, sqlString: String) {
        self.pa55DB = pa55DB
        self.selectStatement = selectStatement
        self.chapterdata = chapterdata
        self.ety = ety
        self.sqlString = sqlString

        super.init(nibName: nil, bundle: nil)
    }


    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // …
}



回答2:


See if this resolves your issue:

override init(style: UITableViewStyle) {
    super.init(style: style)
}

init(pa55DB : COpaquePointer,selectStatement : COpaquePointer, chapterdata : Array<Entry>, ety : Entry, sqlString : String) {
    super.init(style: UITableView.Style.plain)
    self.pa55DB = pa55DB
    self.selectStatement = selectStatement
    self.chapterdata = chapterdata
    self.ety = ety
    self.sqlString = sqlString

}

UITableView Class Reference

From the Swift Programming Language Guide:

Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.

[read more]


Update:

The above code actually resolves the issue with your designated initializer. You now need to properly initialize your self.ety property.




回答3:


Maybe try something like this:

class PlacesTableViewController: UITableViewController { 

   var chapterdata: [Entry]
   var chpData: ChapterData?
   var ety: Entry
   var pa55DB: COpaquePointer
   var selectStatement: COpaquePointer
   var sqlString: String


   convenience init(pa55DB: COpaquePointer, selectStatement: COpaquePointer, chapterdata: [Entry], ety: Entry, sqlString: String) {
       self.init()

       self.pa55DB = pa55DB
       self.selectStatement = selectStatement
       self.chapterdata = chapterdata
       self.ety = ety
       self.sqlString = sqlString

   }

   required init(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
   }

   // …
}



回答4:


UITableViewController isn't anything good for advanced use cases. You can always subclass UIViewController and put an UITableView property in it, just like this:

class PlacesTableViewController: UIViewController {

    let tableView = UITableView(frame: CGRectZero, style: .Plain)

    override func loadView() {
        view = tableView
    }

    // Custom designated initializer
    init(pa55DB : COpaquePointer,selectStatement : COpaquePointer, chapterdata : Array<Entry>, ety : Entry, sqlString : String) {
        // setting up these properties
        super.init(nibName: nil, bundle: nil)  // designated initializer of the superclass 'UIViewController'"
    }
}

And it works like UITableViewController.

Other utilities UITableViewController provides, like refreshControl you can also set one for yourself, like clearsSelectionOnViewWillAppear mechanism can also be implemented in viewWillAppear() or didSelectRowAtIndexPath depending on your needs.



来源:https://stackoverflow.com/questions/30316021/how-to-resolve-designated-initialization-error-for-uitableviewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!