I'm searching for the way to make my code more clean and efficient. I Have an "BaseInfo" it has got some properties and also it is a parent to the "SomeInfo", and "AnotherInfo" classes, which have own additional properties. I've made a generic function that saves and gets those objects from UserDefaults. And I have ViewController that's saves and loads info using those functions, considering the type of info it should use. I want to know is there any way to make my code cleaner and get rid of those type casting in my ViewContoller. Here is my info classes:
public class BaseInfo: Codable{
var name: String?
init(_ dict: [String: Any]){
name = dict["name"] as? String
}
}
class AnotherInfo: BaseInfo {
var secondName: String?
override init(_ dict: [String : Any]) {
super.init(dict)
secondName = dict["secondName"] as? String
}
required init(from decoder: Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
class SomeInfo: BaseInfo {
var middleName: String?
override init(_ dict: [String : Any]) {
super.init(dict)
middleName = dict["middleName"]
}
required init(from decoder: Decoder) throws {
fatalError("init(from:) has not been implemented")
}
}
Here is my class that manages info
protocol InfoManagerProtocol {
static func getInfo(with type: InfoType) -> BaseInfo?
static func saveInfo <T: BaseInfo>(with type: InfoType, info: T)
}
class InfoManager: InfoManagerProtocol {
static func getInfo<T: BaseInfo>(with type: InfoType) -> T? {
if let data = UserDefaults.standard.object(forKey: type.toString()) as? Data, let info = try? JSONDecoder().decode(type.typeOfInfo() as! T.Type, from: data){
return info
}
return nil
}
static func saveInfo<T>(with type: InfoType, info: T) where T : BaseInfo {
if let encodedData = try? JSONEncoder().encode(info){
UserDefaults.standard.setValue(encodedData, forKey: type.toString())
}
}
}
InfoType enum:
enum InfoType: Int{
case base = 1
case another = 2
case some = 3
}
extension InfoType{
func toString() -> String{
switch self{
case .base:
return "base"
case .another:
return "another"
case .some:
return "some"
}
}
func typeOfInfo() -> BaseInfo.Type{
switch self{
case .base:
return BaseInfo.self
case .another:
return AnotherInfo.self
case .some:
return SomeInfo.self
}
}
}
and some controller
class ViewCV: UIViewController{
......
// some outlets
var infoType: InfoType? // info
// some func that updates UI
func updateUI(){
let genericInfo = InfoManager.getInfo(info: .infoType)
self.someNameOutletLabel.text = genericInfo.name
self.secondNameOutletLabel?.text = (genericInfo as? AnotherInfo).secondName // here I don't like it
if let someInfo = genericInfo as? SomeInfo{
self.secondNameOutletLabel?.text = someInfo.thirdName // or like here I also don't like
}
}
}
Looking forward for other critics and advices