使用协议扩展中的默认值向下转换到协议

时间:2018-11-10 17:33:11

标签: swift protocols downcast

向下转换一个结构数组后,“变量视图”窗口显示我的结构中的所有值都已“向下移动”(将在稍后解释)。但是当我打印(structName)时,值很好。但是,当我在该结构上执行相等性检查时,它再次表现出好像我的值已移动。

例如,我正尝试将模型A转换为ModelProtocol。 var m =模型A,其值为{id:“ 1234”,名称:“ Cal”}。当我向下转换时,m现在具有值{id:“ \ 0 \ 0”,name:“ 1234”}。

向下转换一个结构数组后,“变量视图”窗口显示我的结构中的所有值都已“向下移动”(将在稍后解释)。但是当我打印(structName)时,值很好。但是,当我在该结构上执行相等性检查时,它再次表现出好像我的值已移动。

例如,我正尝试将模型A转换为ModelProtocol。 var m =模型A,其值为{id:“ 1234”,名称:“ Cal”}。当我向下转换时,m现在具有值{id:“ \ 0 \ 0”,name:“ 1234”}。

以下实际示例:

我要下调的模型:

struct PrivateSchoolModel: Decodable, SchoolProtocol {
    var id: String
    var name: String
    var city: String
    var state: String
}

struct PublicSchoolModel: Decodable, SchoolProtocol {
    var id: String
    var name: String
    var city: String
    var state: String  
    var latitude: String
    var longitude: String
}

我想向下转换的协议:

protocol SchoolProtocol {
    var id: String { get set }
    var name: String { get set }
    var city: String { get set }
    var state: String { get set }
    var longitude: Float { get set }
    var latitude: Float { get set }
}

extension SchoolProtocol {
    var longitude: Float {
        get { return -1.0 }
        set {}
    }
    var latitude: Float {
        get { return -1.0 }
        set {}
    }
}

向下转换:

guard let downcastedArr = privateSchoolArray as? [SchoolProtocol] else { return [] }

结果(索引为0的项目)或originalArr:

id = "1234"
name = "Leo High School"
city = "Bellview"
state = "WA"

downcastedArr的结果(索引为0的项目):

id = "\0\0"
name = "1234"
city = "Leo High School"
state = "Bellview"

但是如果我打印(downcastArr [0]),它将显示:

id = "1234"
name = "Leo High School"
city = "Bellview"
state = "WA"

但是,如果我尝试originalArray [0] .id == downcastArr [0] .id,它将返回false

我的代码有问题:

class SchoolJSONHandler {
    private enum JSONFile: String {
        case publicSchool = "publicSchool"
        case privateSchool = "privateSchool"
    }

    private lazy var privateSchoolArray = getPrivateSchools()
    private lazy var publicSchoolArray = getPublicSchools()

    func getSchoolArray(sorted: Bool, filtered: Bool, by stateAbbreviation: String?) -> [SchoolProtocol] {
        var schools = combineArrays()

        if sorted {
            schools.sort(by: { $0.name < $1.name })
        }

        if filtered {
            guard let abbr = stateAbbreviation else { return [] }
            schools = schools.filter {
                return $0.state == abbr
            }
        }

        return schools
    }

    private func combineArrays() -> [SchoolProtocol] {
        // EVERYTHING IS FINE IN NEXT LINE
        let a = privateSchoolArray
        // PROBLEM OCCURS IN NEXT 2 LINES WHEN DOWNCASTING
        let b = privateSchoolArray as [SchoolProtocol]
        let c = publicSchoolArray as [SchoolProtocol]
        return b + c
    }

    private func getPublicSchools() -> [PublicSchoolModel] {
        guard let jsonData = getJSONData(from: .publicSchool) else { return [] }
        guard let schools = decode(jsonData: jsonData, using: [PublicSchoolModel].self) else { return [] }
        return schools
    }

    private func getPrivateSchools() -> [PrivateSchoolModel] {
        guard let jsonData = getJSONData(from: .privateSchool) else { return [] }
        guard let schools = decode(jsonData: jsonData, using: [PrivateSchoolModel].self) else { return [] }
        return schools
    }

    private func getJSONData(from resource: JSONFile) -> Data? {
        let url = Bundle.main.url(forResource: resource.rawValue, withExtension: "json")!
        do {
            let jsonData = try Data(contentsOf: url)

            return jsonData
        }
        catch {
            print(error)
        }

        return nil
    }

    private func decode<M: Decodable>(jsonData: Data, using modelType: M.Type) -> M? {
        do {
            //here dataResponse received from a network request
            let decoder = JSONDecoder()
            let model = try decoder.decode(modelType, from:
                jsonData) //Decode JSON Response Data

            return model
        } catch let parsingError {
            print("Error", parsingError)
        }

        return nil
    }
}

然后schoolJSONHandler.getSchoolArray(sorted: true, filtered: true, by: "WA")

在另一个类中调用它

0 个答案:

没有答案