使用Swift 2中的面向协议编程解析抽象层

时间:2015-12-24 21:28:10

标签: ios swift

所以我对Swift相当新,对于面向协议编程的最佳实践还不太清楚,可以使用一些建议。我想要做的是在Parse之上创建一个抽象层,它允许我从Parse加载对象并将它们转换为实现“BackendLoading”协议的结构/类。这是我到目前为止所提出的:

import Foundation
import Parse

protocol BackendLoading {
    typealias AbstractType
    static var backendDBKey: String { get }
    static var propertyKeyNames: [String] { get }
    init()
    init(parameterDictionary: [String: AnyObject])
}

protocol BackendLoader {
    func loadAllObjectsFromBackend<T where T: BackendLoading>(classType: T.Type) -> [T];
}

extension BackendLoader {
    func getPropertyDictionaryFromType<T where T: BackendLoading>(classType: T.Type) -> [String: String] {
        var returnDictionary = [String: String]()
        let mirror = Mirror(reflecting: T())
        for child in mirror.children {
            if let label = child.label {
                returnDictionary[label] = label
            }
        }
        return returnDictionary
    }
}

struct ParseBackendLoader: BackendLoader {

    func loadAllObjectsFromBackend<T where T: BackendLoading>(classType: T.Type) -> [T] {
        var returnArray = [T]()
        let parseObjectArray = loadAllParseObjectsFromBackend(classType)
        let propertyDictionary = getPropertyDictionaryFromType(T)
        for parseObject in parseObjectArray {
            let extractedDictionary = extractPropertiesFromParseObject(parseObject, propertyDictionary: propertyDictionary)
            let object = T(parameterDictionary: extractedDictionary)
            returnArray.append(object)
        }
        return returnArray
    }

    func extractPropertiesFromParseObject(parseObject: PFObject, propertyDictionary: [String: String]) -> [String: AnyObject] {
        var returnDictionary = [String: AnyObject]()
        for (key, _) in propertyDictionary {
            if let parseValue = parseObject[key] {
                returnDictionary[key] = parseValue
            }
        }
        return returnDictionary;
    }

    func loadAllParseObjectsFromBackend<T where T: BackendLoading>(classType: T.Type) -> [PFObject] {
        do {
            let query = PFQuery(className: T.backendDBKey)
            return try query.findObjects()
        } catch {
            print(error)
            return [PFObject]()
        }
    }
}

这是我在单元测试中使用的对象,它连接到Parse中的后端等效项:

class TestLoading: BackendLoading {
    typealias AbstractType = TestLoading
    static var backendDBKey = "TestObject"
    static var propertyKeyNames = ["testObjectString"]
    var testObjectString: String?
    required init() {}

    required init(parameterDictionary: [String: AnyObject]) {
        if let testObjectStringFromDict = parameterDictionary["testObjectString"] as? String {
            testObjectString = testObjectStringFromDict
        }
    }
}

一切正常......只是想知道我是否正确地走这条路。谢谢!

1 个答案:

答案 0 :(得分:1)

除了protocoll设计之外的一个注意事项:取决于findObjects()抛出的错误,需要特定的错误处理。我通常不会捕获错误并记录它,但将其传递给调用者。有些错误可以自动恢复,有些可能需要用户交互,有些可以或必须被忽略。例如。应该向用户报告打开的飞行模式。考虑API设计早期的错误处理 - 最终你不能忽视它。