The Iterable and Iterator interfaces are a great way to simplify code. For example, what if you want to iterate through dates in a range? Perhaps you’d like to write code like this:
For Each day As DateTime In startDate.Range(endDate) ListBox1.AddRow(day.ToString) Next
Although that is not part of the Xojo language, you can add it yourself using these Xojo features:
First, create an extension method in a module like this (make sure the method is Global):
Range(Extends startDate As DateTime, endDate As DateTime) As Iterable Return New DateTimeIterable(startDate, endDate)
Now add a new class, called DateTimeIterable. In its Inspector, click Interfaces and choose Iterable and click OK.
Your class now has an Iterable method on it. Before implementing that, add a Constructor:
Constructor(startDate As DateTime, endDate As DateTime) mStartDate = startDate mEndDate = endDate
Now create the two private properties:
- mStartDate As DateTime
- mEndDate As DateTime
Lastly, implement the Iterator method:
Return New DateTimeIterator(mStartDate, mEndDate)
With that done, now create the DateTimeIterator class and set its Interface to Iterator, which adds two methods: MoveNext and Value.
Before implementing those, add the Constructor:
Constructor(startDate As DateTime, endDate As DateTime) // Have to set the first date to be 1 before the actual first date // so that when it is first iterated it starts where we want. Var oneDay As New DateInterval oneDay.Days = 1 mCurrentDate = startDate - oneDay mEndDate = endDate
Now create the private properties:
- mEndDate As DateTime
- mCurrentDate As DateTime
MoveNext moves to the next item in the iterator and returns True. If there is no next item it returns False. Its code:
Var oneDay As New DateInterval oneDay.Days = 1 mCurrentDate = mCurrentDate + oneDay If mCurrentDate <= mEndDate Then Return True Else Return False End If
The Value method returns the current iterator value. Its code:
Return mCurrentDate
That is it. With this setup you can now write code like this to populate a ListBox with all the days in January 2022:
Var startDate As New DateTime(2022, 1, 1) Var endDate As New DateTime(2022, 1, 31) For Each day As DateTime In startDate.Range(endDate) ListBox1.AddRow(day.ToString) Next
Download the sample project. I hope you find this technique useful.