Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 742 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do you use a switch statement with a nested enum?

#1
I've created an enum for Instagram endpoints with nested enums similar to [Moya][1].

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)
}
}

I would like to return the path for each endpoint.

extension Instagram: TargetType {
var path: String {
switch self {
case .Media.Shortcode(let id):
return "/media/shortcode"
}
}
}

However I'm getting an error on the switch statement above for the `path`.
> Enum case `Shortcode` is not a member of type `Instagram`

How to fix?

[Advanced Practical Enums][1]

[1]:

[To see links please register here]

Reply

#2
I'm adding a more general answer for a few reasons.

1. This is the only open question regarding nested enums and switch statements. [The other one is sadly closed][1].
1. The only legit answer does not show how to assign the value of a nested enum to a symbol. The syntax was not intuitive to me.
1. None of the other answers have extensive case examples.
1. An enum nested 3 levels deep is more illustrative of the required syntax. Using efremidze answer still took me a while to work it out.

<pre><code>
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")
}
</code></pre>

[1]:

[To see links please register here]

Reply

#3
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))) {}
Reply

#4
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.

1. If your type needs to conform to that protocol, feel free to use it to
ensure you set your own standards. I don't even see that in the github project you referred to.
2. Extension are good way to have a primitive type and extend its functionality in other parts of the project. It doesn't make sense to me why you should extend the type right after declaration. A good use case of it is where the String type has been extended to support URL Encoded values:

<pre><code>private extension String {
var URLEscapedString: String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())!
}
}
</code></pre>

3. When you are using this type of switch-case block

<pre><code>switch self {
case .Zen:
return "/zen"
case .UserProfile(let name):
return "/users/\(name.URLEscapedString)"
case .UserRepositories(let name):
return "/users/\(name.URLEscapedString)/repos"
}
</code></pre>

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:

<pre><code>
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)
</pre></code>

4. As a piece of advice, in each step of building your whole architecture just question yourself if that piece of code belongs to that type or should be accessible publicly. In this case it makes complete sense to move search to Media cause you are searching media. You can add the same pattern for something like User and have search under user that returns different value.
Reply

#5
> 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"
}
}
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through