itsji10dra
itsji10dra

Reputation: 4675

Return struct type confirming to protocols

Here is my piece of code,

protocol Configuration {

    static var url: String { get }
    static var username: String { get }
    static var password: String { get }
}

protocol Server {

    associatedtype Profile: Configuration
    associatedtype Payment: Configuration
    associatedtype Images: Configuration
}

struct Development: Server {

    struct Profile: Configuration {

        static var url: String { return "http://google.com" }
        static var username: String { return "abc" }
        static var password: String { return "xyz" }
    }

    struct Payment: Configuration {

        static var url: String { return "http://bing.com" }
        static var username: String { return "abc" }
        static var password: String { return "xyz" }
    }

    struct Images: Configuration {

        static var url: String { return "http://duckduckgo.com" }
        static var username: String { return "abc" }
        static var password: String { return "xyz" }
    }
}

struct Production: Server {

    struct Profile: Configuration {

        static var url: String { return "http://amazon.com" }
        static var username: String { return "pqr" }
        static var password: String { return "xyz" }
    }

    struct Payment: Configuration {

        static var url: String { return "http://facebook.com" }
        static var username: String { return "pqr" }
        static var password: String { return "xyz" }
    }

    struct Images: Configuration {

        static var url: String { return "http://orkut.com" }
        static var username: String { return "pqr" }
        static var password: String { return "xyz" }
    }
}

Question is I would like to fetch my 'struct' (depending on my environment). I need something like,

struct Environment {

    static func current() -> Any:Server {

        if #DEBUG
            return Development
        #endif

        return Production
    }
}

But returning a specific type confirming to my protocol is not possible.

Any suggestion on this or a different approach will be helpful.

Upvotes: 0

Views: 188

Answers (3)

Rob Napier
Rob Napier

Reputation: 299355

"Development" and "Production" are values, not types. You don't need protocols here and shouldn't be using them. Just create the values you need and return them:

struct Server {
    let url: String
    let username: String
    let password: String
}

struct Environment {
    let profile: Server
    let payment: Server
    let images: Server

    static let development = Environment(
        profile: Server(url: "http://google.com", username: "abc", password: "xyz"),
        payment: Server(url: "http://bing.com", username: "abc", password: "xyz"),
        images: Server(url: "http://duckduckgo.com", username: "abc", password: "xyz")
    )

    static let production = Environment(...)

    static var current: Environment {
        #if DEBUG
            return development
        #else
            return production
        #endif
    }
}

Upvotes: 4

Stefan Wieland
Stefan Wieland

Reputation: 253

You can return a generic type or you can simply do something like this:

struct Config {

  static var BaseURL: URL {
    switch Environment.current {
      case .debug:
        return URL(string: "https://...dev.com")!
      case .staging:
        return URL(string: "https://...staging.com")!
      case .release:
        return URL(string: "https://...production.com")!
      }
  }

}

Upvotes: 1

Andreas Oetjen
Andreas Oetjen

Reputation: 10199

Just return Server, not Any:Server:

static func current() -> Server {

    if #DEBUG
        return Development
    #endif

    return Production
}

Upvotes: 0

Related Questions