Using AnyGenerator with Swift 2.2+ (“for in” loop support for custom classes)

Previously I was using the following function to make my custom class conform to the SequenceType protocol:

func generate() -> AnyGenerator<UInt32> {

    var nextIndex = 0

    return anyGenerator {
        if (nextIndex > self.scalarArray.count-1) {
            return nil
        }
        return self.scalarArray[nextIndex++]
    }
}

This is a similar implementation to the accepted answers to these two questions:

  • Searching through objects in array swift
  • UIImageView, setClipsToBounds and how my images are losing their head
  • Can I access the files used for external binary storage in Core Data?
  • Shutter animation AVFoundation iphone
  • iOS 7 Simulator on Mac doesn't work with custom location (Also doesn't ask permission)
  • PhoneGap - Open external application
    • Add "for in" support to iterate over Swift custom classes
    • Add 'for…in' support to a class in Swift 2

    But after a Swift 2.2 update…

    ‘++’ is deprecated: it will be removed in Swift 3

    func generate() -> AnyGenerator<UInt32> {
    
        var nextIndex = 0
    
        return AnyGenerator {
            if (nextIndex > self.scalarArray.count-1) {
                return nil
            }
            nextIndex += 1
            return self.scalarArray[nextIndex]
        }
    }
    

    But this throws an Index out of range error because I actually need to use the pre-incremented index and then increment it after the return.

    How does this work for AnyGenerator now in Swift? (Also, should I be decrementing rather than incrementing as the other two answers I linked to do?)

    2 Solutions Collect From Internet About “Using AnyGenerator with Swift 2.2+ (“for in” loop support for custom classes)”

    (I assume that your code refers to struct ScalarString
    from Working with Unicode code points in Swift.)

    You can do a Swift 2.2+ compatible “increment index after determining
    the return value” with defer:

    func generate() -> AnyGenerator<UInt32> {
    
        var nextIndex = 0
    
        return AnyGenerator {
            if nextIndex >= self.scalarArray.count {
                return nil
            }
            defer {
                nextIndex += 1
            }
            return self.scalarArray[nextIndex]
        }
    }
    

    In your special case however, it would be easier to just
    forward the generator of the

    private var scalarArray: [UInt32] = []
    

    property, either directly:

    func generate() -> IndexingGenerator<[UInt32]> {
        return scalarArray.generate()
    }
    

    or as a type-erased generator which forwards the next() method
    to the array generator:

    func generate() -> AnyGenerator<UInt32> {
        return AnyGenerator(scalarArray.generate())
    }
    

    Why don’t you just introduced a dummy variable?

    func generate() -> AnyGenerator<UInt32> {
    
        var nextIndex = 0
    
        return AnyGenerator {
            if (nextIndex > self.scalarArray.count-1) {
                return nil
            }
            let next = self.scalarArray[nextIndex]
            nextIndex += 1
            return next
    }