YapDatabaseViewRangeOptions

@interface YapDatabaseViewRangeOptions : NSObject <NSCopying>

Range options allow you to specify a particular range of a group.

For example, if a group contains thousands of items, but you only want to display the most recent 50 items in your tableView, then you can easily use range options to accomplish this.

YapDatabaseViewRangeOptions are plugged into YapDatabaseViewMappings.

See

YapDatabaseViewMappings setRangeOptions:forGroup:
  • There are 2 types of supported ranges: Fixed & Flexible

    A fixed range is similar to using a LIMIT & OFFSET in a SQL query. That is, it represents a designated range that doesn’t change.

    You create a fixed range by specifying a desired length and an offset from either the beginning or end.

    Using YapDatabaseViewMappings along with a fixed range provides some unique features:

    • If you specify an offset from the end of the group (YapDatabaseViewEnd), you are essentially pinning the range to the end, and it will stay pinned that way regardless of inserted or deleted items elsewhere in the group.

    For example: If you pin the range to the end, with an offset of zero, and a length of 20, then the range will always specify the last 20 items in the group, even as the group length (as a whole) increases or decreases.

    • The changeset processing will automatically create the proper row changes to match what you want.

    For example: You have a fixed range with length 20, pinned to the beginning with an offset of 0, and a new item is inserted at index 0. The changeset processing will automatically give you a row insert at index 0, and a row delete at the end of your range to properly account for the row that got pushed outside your range.

    Thus you get row animations for free, even when only displaying a subset. And all the math is already done for you.

    Declaration

    Objective-C

    + (nullable YapDatabaseViewRangeOptions *)
        fixedRangeWithLength:(NSUInteger)length
                      offset:(NSUInteger)offset
                        from:(YapDatabaseViewPin)beginningOrEnd;

    Swift

    class func fixedRange(withLength length: UInt, offset: UInt, from beginningOrEnd: YapDatabaseViewPin) -> YapDatabaseViewRangeOptions?

    Parameters

    length

    The desired length of the range. The length doesn’t need to be valid at this point in time. For example, if the group only has 4 items, you can still specify a length of 20 if that is the desired length. The mappings will automatically use a length of 4 to start, and automatically expand up to 20.

    offset

    The offset from one either the beginning or end of the group.

    beginningOrEnd

    Either YapDatabaseViewBeginning or YapDatabaseViewEnd.

  • There are 2 types of supported ranges: Fixed & Flexible

    A flexible range is designed to grow and shrink. To explain this concept, consider Apple’s SMS Messages app:

    When you go into a conversation (tap on a persons name), the messages app starts by displaying the most recent 50 messages (with the most recent at bottom). Although there might be thousands of old messages between you and the other person, only 50 are in the view to begin with. As you send and/or receive messages within the view, the length will grow. And similarly, if you manually delete messages, the length will shrink.

    Flexible ranges are designed to handle these types of user interfaces. They’re also quite customizeable to handle a number of different situations.

    You create a flexible range by specifying an starting length and an offset from either the beginning or end.

    Using YapDatabaseViewMappings along with a flexible range provides some unique features:

    • If you specify an offset from the end of the group (YapDatabaseViewEnd), you are essentially pinning the range to the end, and it will stay pinned that way regardless of inserted or deleted items elsewhere in the group.

    For example: If you pin the range to the end, with an offset of zero, then the range length will grow as items are added to the end.

    • The changeset processing will automatically create the proper row changes to match what you want.

    Thus you get row animations for free, even when only displaying a subset. And all the math is already done for you.

    Declaration

    Objective-C

    + (nullable YapDatabaseViewRangeOptions *)
        flexibleRangeWithLength:(NSUInteger)length
                         offset:(NSUInteger)offset
                           from:(YapDatabaseViewPin)beginningOrEnd;

    Swift

    class func flexibleRange(withLength length: UInt, offset: UInt, from beginningOrEnd: YapDatabaseViewPin) -> YapDatabaseViewRangeOptions?

    Parameters

    length

    The desired starting length of the range. The length doesn’t need to be valid at this point in time. For example, if the group only has 4 items, you can still specify a length of 20. The mappings will automatically correct the length as appropriate.

    offset

    The offset from one either the beginning or end of the group.

    beginningOrEnd

    Either YapDatabaseViewBeginning or YapDatabaseViewEnd.

  • The current length of the range.

    When rangeOptions get plugged into mappings, the length is automatically updated to reflect the available length.

    For a fixed range, the length will always be less than or equal to the original length. For a flexible range, the length will grow and shrink as items get inserted and removed from the original range.

    Declaration

    Objective-C

    @property (readonly, assign, nonatomic) NSUInteger length;

    Swift

    var length: UInt { get }
  • The current offset of the range, relative to the pin (beginning or end of the group).

    For a fixed range, the offset never changes. For a flexible range, the offset will grow and shrink as items get inserted and removed between the range and pin.

    Declaration

    Objective-C

    @property (readonly, assign, nonatomic) NSUInteger offset;

    Swift

    var offset: UInt { get }
  • pin

    The pin value represents the end from which the offset is calculated. For example, assume a group contains 50 items and:

    • length=10, offset=10, pin=YapDatabaseViewBeginning => the range is 10-19 (10 back from 0)

    • length=10, offset=10, pin=YapDatabaseViewEnd => the range is 30-39 (10 back from 49)

    Declaration

    Objective-C

    @property (readonly, assign, nonatomic) YapDatabaseViewPin pin;

    Swift

    var pin: YapDatabaseViewPin { get }
  • There are 2 types of supported ranges: Fixed & Flexible

    Declaration

    Objective-C

    @property (readonly, nonatomic) BOOL isFixedRange;

    Swift

    var isFixedRange: Bool { get }
  • Undocumented

    Declaration

    Objective-C

    @property (nonatomic, readonly) BOOL isFlexibleRange

    Swift

    var isFlexibleRange: Bool { get }
  • For FIXED ranges:

    • the maxLength is readonly.
    • it will always equal the length originally specified.

    For FLEXIBLE ranges:

    • the maxLength allows you to specify a maximum length in which the range can grow.

    In particular, if the range overflows the maxLength, then the changeset processing will automatically trim items from the range (on the non-pin-side) to keep the range length within this maxLength.

    For example, imagine you’re displaying log entries in a tableView. The range is pinned to the end, so as new log entries get appended to the database, they automatically get inserted into the tableView. This allows the tableView to grow as the log grows. However, you don’t want the tableView growing too big, so you can set the maxLength in order to prevent this. That way, your tableView grows as the logs come in (as expected). But if your tableView starts to get too big, then the oldest log entries in the tableView start to fall off as new entries arrive. This is eqivalent to switching from a flexible range to a fixed range, but happens automatically without you having to write extra code to handle the edge case.

    By default there is no maxLength, and thus the default maxLength is NSUIntegerMax.

    Declaration

    Objective-C

    @property (assign, readwrite, nonatomic) NSUInteger maxLength;

    Swift

    var maxLength: UInt { get set }
  • For FIXED ranges:

    • the minLength is readonly.
    • it will always equal zero.

    For FLEXIBLE ranges:

    • the minLength allows you to specify a minimum length that the range should keep (if possible).

    In particular, if the range underflows the minLength, then the changeset processing will automatically adjust the offset or expand the range in order to keep entries in the view.

    This is sometimes useful if items can get deleted from your range.

    By default there is no minLength, and thus the default minLength is zero.

    Declaration

    Objective-C

    @property (assign, readwrite, nonatomic) NSUInteger minLength;

    Swift

    var minLength: UInt { get set }
  • GrowOptions ONLY apply to FLEXIBLE ranges.

    The growOptions allow you to specify in which direction(s) the range may grow. Let’s look at a few concrete examples.

    Example #1

    We’re using a flexible range, with an offset of zero, pinned to the beginning. We’re displaying news items, and the most recent items get inserted at index 0. The group currently contains thousands of items, and our range has a starting length of 50. If a new item gets inserted (at the beginning), we want it to get added to our range. So we would set our growOptions to be YapDatabaseViewGrowPinSide (this is the default value).

    Example #2

    We’re using a flexible range, with an offset of zero, pinned to the end. We’re displaying log entries, with the most recent items getting appended to the end. The group currently contains thousands of items, and our range has a starting length of 50. If a new log item gets inserted (at the end), we want it to get added to our range. So we would set our growOptions to be YapDatabaseViewGrowPinSide (this is the default value).

    Example #3

    We’re making a UI that is somewhat akin to Facebook’s news feed. That is, the most recent items come in at the top, but if you scroll to the bottom we automatically download older posts. However, we don’t want to limit how far the user can scroll down. That is, if the user is bored, we’re going to allow them to scroll down for however long we can fetch old items from the server. But obviously we can’t allow the length of our tableView to grow infinitely long. So to accomplish this, we’re going to use flexible ranges, and we’re going to shift the length as the user scrolls down. To start with, we only have the 30 most recent posts in the database. And we set our flexible range as: length=30, offset=0, pin=YapDatabaseViewBeginning. Additionally we set our growOptions to: YapDatabaseViewGrowOnBothSides. Thus if we download new items, they’ll get included in the range. And if we fetch older items, they’ll also get included in the range. Now as the the user scrolls down, and we fetch more and more old items, we eventually get to the point were we shift the range. So when the range length gets to some max length that we want to support, we shift to a new flexible range: length=max, offset=0, pin=YapDatabaseViewEnd, growOptions=YapDatabaseViewGrowPinSide, maxLength=max This new range will keep the tableView length capped at max, and continually load older content as it gets fetched. To allow the user to scroll back up, we just increment the offset as the go. When they eventually get back up to the top, we reset the flexible range to its original value.

    To explain the different options, consider the following picture:


    | |x|x|x| | <– x marks the range


    0 1 2 3 4

    groupCount = 5 flexibleRange: length=3, offset=1, pin=YapDatabaseViewBeginning, growOptions=YapDatabaseViewGrowPinSide

    Now an item gets inserted at index 1 as follows:


    | |?|x|x|x| | <– is ? added to the flexible range?


    0 1 2 3 4 5

    Does the item get added to the flexible range (with the given config options)? The answer is YES.


    | |x|x|x|x| | <– YES (based on pin & growOptions)


    0 1 2 3 4 5

    Because the flexible range is pinned to the beginning, and grows pin side. So if anything gets inserted between what was originally at index 0, and what was originally at index 1, then those items get added to the flexible range.

    Notice that after the insert, the offset remains set at 1. Notice that the answer would be NO if the flexible range was pinned to the end (with the same growOptions).

    Now let’s see what happens if something gets inserted at the end:


    | |x|x|x|x|?| | <– is ? added to the flexible range?


    0 1 2 3 4 5 6

    Does the item get added to the flexible range (with the given config options)? The answer is NO.


    | |x|x|x|x| | | <– NO (based on pin & growOptions)


    0 1 2 3 4 5 6

    Because the flexible range is pinned to the beginning, and grows pin side.

    Notice that after the insert, the offset remains set at 1. Notice that the answer would be YES if the flexible range was pinned to the end (with the same growOptions).


    |?| |x|x|x|x| | | => NEVER => | | |x|x|x|x| | |


    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7


    | | |x|?|x|x|x| | | => ALWAYS => | | |x|x|x|x|x| | |


    0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8

    Declaration

    Objective-C

    @property (assign, readwrite, nonatomic) YapDatabaseViewGrowOptions growOptions;

    Swift

    var growOptions: YapDatabaseViewGrowOptions { get set }
  • Various copy options.

    Declaration

    Objective-C

    - (nonnull id)copyWithNewLength:(NSUInteger)newLength;

    Swift

    func copy(withNewLength newLength: UInt) -> Any
  • Undocumented

    Declaration

    Objective-C

    - (id)copyWithNewOffset:(NSUInteger)newOffset;

    Swift

    func copy(withNewOffset newOffset: UInt) -> Any
  • Undocumented

    Declaration

    Objective-C

    - (id)copyWithNewLength:(NSUInteger)newLength newOffset:(NSUInteger)newOffset;

    Swift

    func copy(withNewLength newLength: UInt, newOffset: UInt) -> Any