I\'ve created an enum for Instagram endpoints with nested enums similar to Moya.
enum Instagram {
enum Media {
case Popular
case Shortcode(id
Enum case Search is not a member of type Instagram
As the compiler say, Search
is not a member of type Instagram
. It's just an enum in the scope of Instagram
. You have to create a member that is an instance of Search
in Instagram
struct Instagram {
enum Media {
case Search(lat: Float, lng: Float, distance: Int)
}
// something like:
var media = .Search(lat: 0, lng: 0, distance: 0)
// I'm not sure this one is right syntax
// because I can't check it right now.
// please just get the idea
}
extension Instagram: TargetType {
var path: String {
switch self.media {
case .Search(let _, let _, let _):
return "/media/search"
}
}
}
By adding an associated value for the nested enum you can access it using a switch statement.
enum Instagram {
enum MediaEndpoint {
case Search(lat: Float, lng: Float, distance: Int)
}
case Media(MediaEndpoint)
}
extension Instagram: TargetType {
var path: String {
switch self {
case .Media(.Search):
return "/media/search"
}
}
}
// Demo
protocol TargetType {
var path: String { get }
}
class MoyaProvider<Target: TargetType> {
func request(_ target: Target, completion: @escaping () -> ()) {}
}
let provider = MoyaProvider<Instagram>()
provider.request(.Media(.Search(lat: 0, lng: 0, distance: 0))) {}
I'm adding a more general answer for a few reasons.
enum Action {
case fighter(F)
case weapon(W)
enum F {
case attack(A)
case defend(D)
case hurt(H)
enum A {
case fail
case success
}
enum D {
case fail
case success
}
enum H {
case none
case some
}
}
enum W {
case swing
case back
}
}
// Matches "3 deep"
let action = Action.fighter(.attack(.fail))
// Matches "1 deep" because more general case listed first.
let action2 = Action.weapon(.swing)
switch action {
case .fighter(.attack(.fail)):
print("3 deep")
case .weapon:
print("1 deep")
case .weapon(.swing):
print("2 deep to case")
case .fighter(.attack):
print("2 deep to another enum level")
default:
print("WTF enum")
}
There is a couple of problems with your architecture. You should know when and why you need to use extensions and protocols and how you should structure your blocks of code.
private extension String {
var URLEscapedString: String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())!
}
}
switch self {
case .Zen:
return "/zen"
case .UserProfile(let name):
return "/users/\(name.URLEscapedString)"
case .UserRepositories(let name):
return "/users/\(name.URLEscapedString)/repos"
}
The value in the case should be a member of self. that's why it can not find the type. the type is declared inside Instagram enum but it doesn't hold value in the self. it holds value inside Media. So move your media related function into the declaration of Media and access them there. That way self is referring to Media. Here's the full working code for me:
private extension String {
var URLEscapedString: String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())!
}
}
public enum Instagram {
public enum Media {
case Search(String)
var path:String {
switch self {
case Media.Search(let keyword):
return "/media/search/\(keyword.URLEscapedString)"
}
}
}
}
var me = Instagram.Media.Search("me")
print(me.path)