2016-12-27 18 views
5

में एनम के माध्यम से छेड़छाड़ करना मेरे पास एक साधारण enum है जिसे मैं फिर से शुरू करना चाहता हूं। इस उद्देश्य के लिए, मैंने नीचे दिए गए कोड में दिखाए गए अनुसार अनुक्रम और IteratorProtocol अपनाया है। BTW, यह हो सकता है कॉपी/Xcode 8.स्विफ्ट 3.0

import UIKit 

enum Sections: Int { 
    case Section0 = 0 
    case Section1 
    case Section2 
} 

extension Sections : Sequence { 
    func makeIterator() -> SectionsGenerator { 
    return SectionsGenerator() 
    } 

    struct SectionsGenerator: IteratorProtocol { 
    var currentSection = 0 

    mutating func next() -> Sections? { 
     guard let item = Sections(rawValue:currentSection) else { 
     return nil 
     } 
     currentSection += 1 
     return item 
    } 
    } 
} 

for section in Sections { 
    print(section) 
} 

में एक खेल का मैदान के लिए चिपकाया लेकिन के लिए में पाश त्रुटि संदेश "प्रकार 'Sections.Type' प्रोटोकॉल के लिए 'अनुक्रम' अनुरूप नहीं है" उत्पन्न । प्रोटोकॉल अनुरूपता मेरे विस्तार में है; तो, इस कोड के साथ क्या गलत है?

मुझे पता है कि ऐसा करने के अन्य तरीके हैं लेकिन मैं समझना चाहता हूं कि इस दृष्टिकोण में क्या गलत है।

धन्यवाद।

+0

जवाब है कि यहां आपकी समस्या का समाधान (प्रश्न स्ट्रिंग प्रकार के बारे में है, लेकिन अधिकतर उत्तर किसी भी प्रकार के साथ काम करेंगे) की एक संख्या हैं : http://stackoverflow.com/questions/24007461/how-to-enumerate-an-enum-with-string-type – kevin

उत्तर

5

आप एक मूल्य एक प्रकार है जो Sequence प्रोटोकॉल के अनुरूप की से अधिक पुनरावृति कर सकते हैं। इसलिए

for section in Sections.Section0 { 
    print(section) 
} 

संकलित और अपेक्षित परिणाम देगा। लेकिन निश्चित रूप से वास्तव में आप क्या चाहते हैं क्योंकि मूल्य की पसंद मनमानी है और मूल्य अनुक्रम में स्वयं की आवश्यकता नहीं है।

जहाँ तक मुझे पता है, वहाँ एक प्रकार पर ही पुनरावृत्ति करने के लिए कोई रास्ता नहीं है, तो यह है कि

for section in Sections { 
    print(section) 
} 

संकलित करता है। इसकी आवश्यकता होगी कि "मेटाटाइप" Sections.Type से Sequence अनुरूप है। शायद कोई मुझे गलत साबित करता है।

आप क्या कर सकते हैं एक प्रकार विधि है जो एक दृश्य देता है परिभाषित करने के लिए है:

extension Sections { 
    static func all() -> AnySequence<Sections> { 
     return AnySequence { 
      return SectionsGenerator() 
     } 
    } 

    struct SectionsGenerator: IteratorProtocol { 
     var currentSection = 0 

     mutating func next() -> Sections? { 
      guard let item = Sections(rawValue:currentSection) else { 
       return nil 
      } 
      currentSection += 1 
      return item 
     } 
    } 

} 

for section in Sections.all() { 
    print(section) 
} 
+0

अनिवार्य रूप से आपके द्वारा सुझाए गए "मेटाटाइप" के लिए एक एसई प्रस्ताव है; https://gist.github.com/andyyhope/2fc5b6bee8ee1346f688 उम्मीद है कि यह अपनाया गया है क्योंकि यह एक समग्र उपयोगी सुविधा प्रतीत होता है जो सभी प्रकार के कस्टम समाधान से बच जाएगा। अभी के लिए, मैं इस प्रकार के पुनरावृत्ति के साथ रहना होगा। धन्यवाद! – Phantom59

+0

इसकी स्थिति पर एक और संदर्भ यहां पाया जा सकता है: https://github.com/apple/swift-evolution/pull/114 – Kdawgwilk

+0

कृपया, यह भी जांचें [http://stackoverflow.com/a/28341290/4041795) उत्तर .. जो दिखाता है कि स्विफ्ट के कई संस्करणों के लिए iterateEnum() फ़ंक्शन कैसे बनाएं। – Montmons

6

Martin’s solution एक प्रोटोकॉल के रूप में पुनर्संशोधित किया जा सकता है ध्यान दें कि:

import Foundation 

protocol EnumSequence 
{ 
    associatedtype T: RawRepresentable where T.RawValue == Int 
    static func all() -> AnySequence<T> 
} 
extension EnumSequence 
{ 
    static func all() -> AnySequence<T> { 
     return AnySequence { return EnumGenerator() } 
    } 
} 

private struct EnumGenerator<T: RawRepresentable>: IteratorProtocol where T.RawValue == Int { 
    var index = 0 
    mutating func next() -> T? { 
     guard let item = T(rawValue: index) else { 
      return nil 
     } 
     index += 1 
     return item 
    } 
} 

फिर, एक enum

दिया
enum Fruits: Int { 
    case apple, orange, pear 
} 

आप प्रोटोकॉल और टाइपलास को थप्पड़ मारते हैं:

enum Fruits: Int, EnumSequence { 
    typealias T = Fruits 
    case apple, orange, pear 
} 

Fruits.all().forEach({ print($0) }) // apple orange pear 
1

यह इतना आसान दिखता है:

public protocol EnumSequence { 
    init?(rawValue: Int) 
} 

public extension EnumSequence { 

    public static var items: [Self] { 
     var caseIndex: Int = 0 
     let interator: AnyIterator<Self> = AnyIterator { 
      let result = Self(rawValue: caseIndex) 
      caseIndex += 1 
      return result 
     } 
     return Array(interator) 
    } 
} 
0

ऊपर समाधान पर आवर्ती, एक प्रोटोकॉल है जो allValues ​​अनुक्रम को जोड़ने के लिए, लेकिन यह भी संभावना कन्वर्ट करने के लिए अनुमति देने के लिए और enumerations से लागू किया जा सकता नीचे देखें स्ट्रिंग मान से।

स्ट्रिंग-जैसी गणनाओं के लिए बहुत सुविधाजनक है जो उद्देश्य सी का समर्थन करने की आवश्यकता है (केवल int गणनाओं की अनुमति है)।

public protocol ObjcEnumeration: LosslessStringConvertible, RawRepresentable where RawValue == Int { 
    static var allValues: AnySequence<Self> { get } 
} 

public extension ObjcEnumeration { 
    public static var allValues: AnySequence<Self> { 
     return AnySequence { 
      return IntegerEnumIterator() 
     } 
    } 

    public init?(_ description: String) { 
     guard let enumValue = Self.allValues.first(where: { $0.description == description }) else { 
      return nil 
     } 
     self.init(rawValue: enumValue.rawValue) 
    } 

    public var description: String { 
     return String(describing: self) 
    } 
} 

fileprivate struct IntegerEnumIterator<T: RawRepresentable>: IteratorProtocol where T.RawValue == Int { 
    private var index = 0 
    mutating func next() -> T? { 
     defer { 
      index += 1 
     } 
     return T(rawValue: index) 
    } 
} 

एक ठोस उदाहरण के लिए:

@objc 
enum Fruit: Int, ObjcEnumeration { 
    case apple, orange, pear 
} 

अब आप कर सकते हैं:

for fruit in Fruit.allValues { 

    //Prints: "apple", "orange", "pear" 
    print("Fruit: \(fruit.description)") 

    if let otherFruit = Fruit(fruit.description), fruit == otherFruit { 
     print("Fruit could be constructed successfully from its description!") 
    } 
} 
0

यदि आपका enum एक आधार पर एक इंट है, तो आप की तरह एक प्रभावी लेकिन थोड़ा गंदा चाल कर सकते हैं इस।

enum MyEnum: Int { 
    case One 
    case Two 
} 

extension MyEnum { 
    func static allCases() -> [MyEnum] { 
     var allCases = [MyEnum]() 
     for i in 0..<10000 { 
      if let type = MyEnum(rawValue: i) { 
       allCases.append(type) 
      } else { 
       break 
      } 
     } 
     return allCases 
    } 
} 

फिर MyEnum.allCases() पर पाश ..

संबंधित मुद्दे