I'll add some explanation to the other, correct answers.
So, here is how it goes:
self.nodes.count is of type NSUInteger, which is the same as unsigned long int in 64 bit systems, or alternatively unsigned int in 32 bit systems.
The literal 20 is of type int.
When you form the expression self.nodes.count - 20, 20 is 'promoted' to the unsigned integer type of the other operand (self.nodes.count), because it has the wider range of the two.
That is because, when both operands have types of different sizes, the smaller one gets promoted to the larger one to make them equal and calculate the result in those terms (in hardware, arithmetical operations between values of different types aren't really defined - the bit representations differ).
The problem is that, in exchange for being able to represent a wider range of positive values with the same bit length, unsigned integers can not represent negative values. So, when 20 is greater than self.nodes.count, the result "wraps around" to a large, unsigned integer.
On the other hand indexPath.row, too, is an unsigned integer (NSUInteger), so you end up comparing the relatively small row value with the huge result of the subtraction operation; the test:
if (indexPath.row >= self.nodes.count - 20)
...always fails (the left side is smaller).
If you first cast both results to signed integer and then compare those signed integers: