iOS Creating an Object Best Practice

2019-08-27 19:11发布

问题:

I've created a wizard for user's to sign up using my app, however, I'm having some doubts as to how I should store their information along the way.

I have a User model, which is filled out when users are pulled from the database, however, there are some required fields on this model that wouldn't be filled out if I were to use it as the object that is passed along as the user goes through the the wizard.

Here is my User model:

final class User: NSObject, ResponseObjectSerializable, ResponseCollectionSerializable {
    let id: Int
    var facebookUID: String?
    var email: String
    var firstName: String
    var lastName: String
    var phone: String?
    var position: String?
    var thumbnail: UIImage?
    var timeCreated: CVDate

    init?(response: NSHTTPURLResponse, var representation: AnyObject) {
        if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
            representation = dataRepresentation
        }

        self.id = representation.valueForKeyPath("id") as! Int
        self.facebookUID = (representation.valueForKeyPath("facebook_UID") as? String)
        self.email = (representation.valueForKeyPath("email") as? String) ?? ""
        self.firstName = (representation.valueForKeyPath("first_name") as? String) ?? ""
        self.lastName = (representation.valueForKeyPath("last_name") as? String) ?? ""
        self.phone = (representation.valueForKeyPath("phone") as? String)
        self.position = (representation.valueForKeyPath("position_name") as? String)
        self.thumbnail = UIImage(named: "ThomasBaldwin")

        if let timeCreated = representation.valueForKeyPath("time_created") as? String {
            let formatter = NSDateFormatter()
            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
            if let date = formatter.dateFromString(timeCreated) {
                self.timeCreated = CVDate(date: date)
            } else {
                self.timeCreated = CVDate(date: NSDate())
            }
        } else {
            self.timeCreated = CVDate(date: NSDate())
        }
    }

    static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [User] {
        var users: [User] = []

        if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [NSDictionary]) {
            if let dataRepresentation = dataRepresentation as? [[String: AnyObject]] {
                for userRepresentation in dataRepresentation {
                    if let user = User(response: response, representation: userRepresentation) {
                        users.append(user)
                    }
                }
            }
        }

        return users
    }
}

Notice the variables id and timeCreated. These are both generated when a new row is added to the Users table in the database, therefore, I wouldn't have values for those variables until the user is actually created.

Also, I would like to add some methods to the model, such as validateUser which will be a method that makes sure all the fields are filled out, and validateEmail which will be a method that makes sure the email is in proper syntax, and so on...

My question is, should I

A. just make those constants optional and add those methods to my current User model
B. make another model called CreateUserModel that only has variables for the information the user will be filling out and put the extra methods in there

UPDATE

I updated my User class to use a dictionary as the storage mechanism and it already looks a lot cleaner. However, the issue that comes to mind is, how will another programmer know which fields he can grab from the User model since I'm not individually storing them as variables anymore. Would they just have to check the DB and look at the structure of the table?

Here's my updated User class:

final class User: NSObject, ResponseObjectSerializable, ResponseCollectionSerializable {

    var properties = NSDictionary()

    init?(response: NSHTTPURLResponse, representation: AnyObject) {
        if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
            properties = dataRepresentation
        }

        properties = representation as! NSDictionary
    }

    static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [User] {
        var users: [User] = []

        if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [NSDictionary]) {
            if let dataRepresentation = dataRepresentation as? [[String: AnyObject]] {
                for userRepresentation in dataRepresentation {
                    if let user = User(response: response, representation: userRepresentation) {
                        users.append(user)
                    }
                }
            }
        }

        return users
    }
}

回答1:

I would make them Optionals. That is the beauty of Optionals - you can use nil to mean exactly "no data here".

The other grand strategy that comes to mind is to use a dictionary as the storage mechanism inside your model, because that way either it has a certain key or it doesn't. You could make your User object key-value coding compliant, and thus effectively transparent, by passing keys on to the dictionary.