gpt4 book ai didi

ios - 在 Swift 4 中使用泛型 T.Type 类时如何调用正确的构造函数?

转载 作者:搜寻专家 更新时间:2023-11-01 06:29:17 25 4
gpt4 key购买 nike

我有一个包含一些表的数据库,每个表代表我项目的一个对象。我想编写一个通用函数来通过 SQL 读取一个表并创建一个包含读取记录的对象。所以,我的函数的参数是:表名和对象类型。下面的代码是我执行此操作的功能。在 func 的最后,我尝试调用我想做的事情,但是对于一个特定的对象,这不是我想要的。

func readAll<T>(objeto: String, typeClass: T.Type) -> [T] {
var ret : [T] = []

// STATEMENT DATA
let queryString = "SELECT * FROM \(objeto);"
var queryStatement: OpaquePointer? = nil

// STATEMENT DATA TYPE
let queryString2 = "PRAGMA table_info(\(objeto));"
var queryStatement2: OpaquePointer? = nil

// 1
if sqlite3_prepare_v2(db,queryString,-1,&queryStatement,nil) != SQLITE_OK {
print("Error to compile readAll \(objeto) 1")
return ret
}

if sqlite3_prepare_v2(db,queryString2,-1,&queryStatement2,nil) != SQLITE_OK {
print("Error to compile readAll \(objeto) 2")
return ret
}

var listNameColumns : [String] = []

while( sqlite3_step(queryStatement2) == SQLITE_ROW ) {
listNameColumns.append( String(cString: sqlite3_column_text(queryStatement2, 2)!) )
}

// 2
while ( sqlite3_step(queryStatement) == SQLITE_ROW ) {
var dict: [String:Any] = [:]

for i in 0...listNameColumns.count-1 {
let nameColumn = String(cString: sqlite3_column_name(queryStatement,Int32(i))!)
switch (sqlite3_column_type(queryStatement, Int32(i))) {

case SQLITE_TEXT:
dict[nameColumn] = String(cString: sqlite3_column_text(queryStatement, Int32(i))!)
break

case SQLITE_INTEGER:
dict[nameColumn] = sqlite3_column_int(queryStatement, Int32(i))
break

case SQLITE_FLOAT:
dict[nameColumn] = sqlite3_column_double(queryStatement, Int32(i))
break

default:
print("Tipo desconhecido.")
break
}
}

ret.append(ResPartner(dict: dict)) <------ HERE IS MY QUESTION!
}

// 3
sqlite3_finalize(queryStatement2)
sqlite3_finalize(queryStatement)

return ret
}

这里有两个对象,它们有点不同,但构建器和字段的工作方式相同。

class ResPartner {

static let fieldsResPartner : [String] = ["id","company_type_enum_for_customer","name","contact_address","customer_account_number","customer_group_id","segment_id","subsegment_id","economic_group_id","street","category_id","type_stablishment_id","final_user","final_taxpayer","cnpj_cpf","inscr_est","ccm","cnae","phone","phone_extension","mobile","fax","email","email_extra","website","lang"]

var attributes : [String:Any] = [:]

init(dict : [String:Any]) {
for k in dict.keys {
if(ResPartner.fieldsResPartner.contains(k)) {
attributes[k] = dict[k]
}
}
}

func toString() {
for k in attributes.keys{
print("\(k) - \(attributes[k]!)")
}
}
}

class Product {

static let fieldsProducts : [String] = ["id","name","default_code","display_name","categ_id","company_ax_id","destination_type","fiscal_class_code","multiple","taxes_id","uom_id","uom_po_id","__last_update","active","create_date","create_uid","currency_id","invoice_police","item_ids","list_price","price","pricelist_id","type"]

public var default_code: String!
public var display_name: String!
public var id: Int!
public var name: String!
public var destination_type: String!
public var company_ax_id: Int!
public var categ_id: Int!
public var fiscal_class_code: String!
public var taxes_id: Int!
public var uom_id: Int!
public var uom_po_id: Int!
public var multiple: Int!
public var last_update: String!
public var active: Bool!
public var create_date: String!
public var create_uid: Int!
public var currency_id: Int!
public var invoice_police: String!
public var item_ids: [Int]!
public var list_price: String!
public var price: Float!
public var pricelist_id: Int!
public var type: String!

init() {

}

init( dict : [String:Any] ) {
self.default_code = dict["default_code"] as! String
self.display_name = dict["display_name"] as! String
self.id = dict["id"] as! Int
self.name = dict["name"] as! String
self.destination_type = dict["destination_type"] as! String
self.company_ax_id = dict["company_ax_id"] as! Int
self.categ_id = dict["categ_id"] as! Int
self.fiscal_class_code = dict["fiscal_class_code"] as! String
self.taxes_id = dict["taxes_id"] as! Int
self.uom_id = dict["uom_id"] as! Int
self.uom_po_id = dict["uom_po_id"] as! Int
self.multiple = dict["multiple"] as! Int
self.last_update = dict["last_update"] as! String
self.active = dict["active"] as! Bool
self.create_date = dict["create_date"] as! String
self.create_uid = dict["create_uid"] as! Int
self.currency_id = dict["currency_id"] as! Int
self.invoice_police = dict["invoice_police"] as! String
self.item_ids = dict["item_ids"] as! [Int]
self.list_price = dict["list_price"] as! String
self.price = dict["price"] as! Float
self.pricelist_id = dict["pricelist_id"] as! Int
self.type = dict["type"] as! String
}
}

所以,我的问题是,如何调用参数传递的 T.Type 类的构造函数?我确实阅读了有关协议(protocol)、扩展和其他帖子的内容,但没有解决我的问题。

最佳答案

你可以用协议(protocol)来约束你的泛型:

  1. 定义一个用字典初始化的协议(protocol):

    protocol DictionaryInitializable {
    init(dict: [String: Any])
    }
  2. 使您的两个类型符合该类型(您必须按照 Xcode 的提示将 required 添加到您的 init 方法),例如:

    class Product: DictionaryInitializable {

    ...

    required init(dict: [String: Any]) {
    ...
    }
    }

    class ResPartner: DictionaryInitializable {

    static let fieldsResPartner = ...

    var attributes: [String: Any] = [:]

    required init(dict: [String: Any]) {
    for k in dict.keys where ResPartner.fieldsResPartner.contains(k) {
    attributes[k] = dict[k]
    }
    }

    func toString() { ... }
    }
  3. 更改您的方法声明以明确T 必须符合您的新协议(protocol):

    func readAll<T: DictionaryInitializable>(objeto: String, typeClass: T.Type) -> [T] {
    var ret: [T] = []

    ...

    // 2
    while ( sqlite3_step(queryStatement) == SQLITE_ROW ) {
    var dict: [String: Any] = [:]

    ...

    ret.append(T(dict: dict)) // You can now use `T` here
    }

    return ret
    }
  4. 你可以这样调用它:

    let list = db_respartner.readAll(objeto: "res_partner", typeClass: ResPartner.self)

关于ios - 在 Swift 4 中使用泛型 T.Type 类时如何调用正确的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49577256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com