Подтвердить что ты не робот

Почему свойство row NSIndexPath имеет целое число со знаком?

Почему свойство строки NSIndexPath имеет целое число со знаком?

Может ли это когда-либо принимать "действительное" отрицательное значение?

enter image description here

изменить

Я не думал об этом до сегодняшнего дня, когда я установил LLVM для проверки сравнения знака. Это заставило компилятор извергать предупреждения всякий раз, когда был indexPath.row <= [someArray count] или аналогичный.

4b9b3361

Ответ 1

Что произойдет, если вы используете отрицательные числа?

Нецелесообразно использовать отрицательные значения, если вы это сделаете, вы получите сумасшедшие результаты

NSIndexPath* path = [NSIndexPath indexPathForRow:-2 inSection:0];

Приведенные выше результаты состоят из раздела 0 и строки 4294967294 (для меня это выглядит как underflow NSUInteger!). Будьте уверены, что это происходит только в категории UIKit Additions, а не в NSIndexPath сам. Рассматривая концепцию NSIndexPath, на самом деле не имеет смысла удерживать отрицательные значения. Так почему?

(возможно) Причина, почему это так

Основной объект NSIndexPath из OS X использует NSUInteger для своих индексов, но UIKit Addition использует NSInteger. Категория только строится поверх основного объекта, но использование NSInteger over NSUInteger не предоставляет никаких дополнительных возможностей.

Почему это работает так, я понятия не имею. Мое предположение (и я предугадываю предположение), это был наивный API slipup при первом запуске iOS. Когда в iOS 2 был выпущен UITableView, он использовал NSInteger для множества вещей (например, numberOfSections). Подумайте об этом: это концептуально не имеет смысла, вы не можете иметь отрицательное количество разделов. Теперь даже в iOS 6 он все еще использует NSInteger, чтобы не разорвать предыдущую совместимость приложений с представлениями таблицы.

Наряду с UITableView у нас есть дополнения к NSIndexPath, которые используются в сочетании с табличным представлением для доступа к ним и тому подобным. Поскольку они должны работать вместе, им нужны совместимые типы (в данном случае NSInteger).

Чтобы изменить тип на NSUInteger по всей доске, это сломает много вещей, и для безопасного проектирования API все нужно будет переименовать, чтобы аналоги Nabelteger и NSUInteger могли безопасно работать бок о бок. Apple, вероятно, не хочет этого хлопота (и разработчиков тоже!), И поэтому они сохранили его до NSInteger.

Ответ 2

Одна из возможных причин заключается в том, что неподписанные типы очень легко перетекают. В качестве примера у меня была переменная NSUInteger для ширины штриха в моем коде. Мне нужно было создать "конверт" вокруг точки, нарисованной с помощью этого штриха, поэтому этот код:

NSUInteger width = 3;
CGRect envelope = CGRectInset(CGRectZero, -width, -width);
NSLog(@"%@", NSStringFromCGRect(envelope));

При неподписанном типе это выводит {{inf, inf}, {0, 0}}, с целым знаком, вы получаете {{-3, -3}, {6, 6}}. Причина в том, что унарный минус перед переменной width создает нижнее течение. Это может быть очевидно для кого-то, но удивит многих программистов:

NSUInteger a = -1;
NSUInteger b =  1;
NSLog(@"a: %u, b: %u", a, -b); // a: 4294967295, b: 4294967295

Таким образом, даже в ситуациях, когда нет смысла использовать отрицательное значение (ширина штриха не может быть отрицательной), имеет смысл использовать значение в отрицательном контексте, вызывая недоисполнение. Переход на подписанный тип приводит к меньшим неожиданностям, сохраняя при этом диапазон достаточно высоким. Похоже на хороший компромисс.

Ответ 3

Я думаю, что UIKit Дополнения на NSIndexPath используют тип NSInteger намеренно. Если по какой-то причине отрицательная строка будет передана как parameter любому методу (в настоящий момент я не вижу ни одного), значение autocast до NSIntegerMax + parameter не произойдет, и любой возможный объект не будет искать смехотворно большие параметр, который не существует. Тем не менее, есть и другие способы предотвратить это, поэтому это может быть просто вопрос вкуса.

Я, например, не принимал бы NSUInteger в качестве параметров в классе NSIndexPath, а скорее NSInteger и проверял знак и вообще не создавал бы NSIndexPath, если бы какой-либо параметр был отрицательным.