How do you use a switch statement with a nested enumeration?

I get an error in the switch statement below for path .

Enum Search case is not a member of Instagram type

 enum Instagram { enum Media { case Popular case Shortcode(id: String) case Search(lat: Float, lng: Float, distance: Int) } enum Users { case User(id: String) case Feed case Recent(id: String) } } extension Instagram: TargetType { var path: String { switch self { case .Media.Search(let _, let _, let _): return "/media/search" } } } 

I want to use the switch statement to return the path, however cases lead to errors. Could this work?

This is using extended enumerations: https://github.com/terhechte/appventure-blog/blob/master/resources/posts/2015-10-17-advanced-practical-enum-examples.org#api-endpoints

+7
enums switch-statement swift
source share
4 answers

By adding a bound value for a nested enumeration, you can access it using the 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))) {} 
+10
source share

I am adding a more general answer for several reasons.

  • This is the only open question regarding nested enumerations and switch statements. The other is sadly closed .
  • The only legitimate answer does not show how to assign a nested enumeration value to a character. The syntax was not intuitive for me.
  • None of the other answers contain extensive examples.
  • Nested nested 3 levels of depth more illustrate the required syntax. Using the efremidze answer above still took me some time to solve this problem.

Example:

 enum Action { enum F { enum A { case fail case success } enum D { case fail case success } enum H { case none case some } case Attack(A) case Defend(D) case Hurt(H) } enum W { case swing case back } case Fighter(F) case Weapon(W) } // 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") } 
+15
source share

There are a couple of problems with your architecture. You need to know when and why you need to use extensions and protocols and how you should structure your code blocks.

  • If your type must comply with this protocol, feel free to use it to make sure that you set your own standards. I don't even see this in the github project you talked about.
  • Extension is a good way to have a primitive type and extend its functionality in other parts of the project. It makes no sense to me why you should extend the type immediately after the declaration. A good use case is that the String type has been extended to support URL-encoded values:
 private extension String { var URLEscapedString: String { return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())! } } 
  1. When you use this type of switch lock
 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 must be a member of self. why can't he find the type. the type is declared inside an Instagram enumeration, but it does not store the value in self. It retains value inside Media. So move your media-related feature to your Media ad and access them. So, I mean 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" ) (me.path)

code>
  1. As one of the tips at each stage of building the entire architecture, just ask yourself the question, does this part of the code belong to this type or should it be publicly available. In this case, it makes sense to move the search to Media because you are looking for media. You can add the same template for something like User and do a search under a user that returns a different value.
+4
source share

Search enumeration case is not a member of type Instagram

As the compiler says, Search not a member of the Instagram type. This is just an listing in Instagram . You must create an element 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" } } } 
+1
source share

All Articles