Я пишу приложение для iPad с помощью Xcode 5.0. Я попытался реализовать категорию, которая позволит перетасовать NSMutableArray. Я использую Test Driven Development, и я написал тест, подобный следующему, используя Objective-С++:
size_t randomInteger(size_t);
@implementation ShuffleArrayTests
- (void)testsShufflesAnArray
{
NSMutableArray* array = [@[@"one", @"two", @"three", @"four", @"five",
@"six", @"seven", @"eight", @"nine", @"ten"] mutableCopy];
std::vector<__unsafe_unretained id> values(array.count);
[array getObjects:&values[0] range:NSMakeRange(0, array.count)];
::srandom(0);
std::random_shuffle(values.begin(), values.end(), randomInteger);
NSMutableArray* expectedValues =
[NSMutableArray arrayWithObjects:&values[0] count:values.size()];
::srandom(0);
[array shuffle];
XCTAssertEqualObjects(expectedValues, array);
}
Реализация метода категорий тасовки записывается следующим образом, также в Objective-С++:
- (void)shuffle
{
std::vector<__unsafe_unretained id> buffer(self.count);
[self getObjects:&buffer[0] range:NSMakeRange(0, self.count)];
std::random_shuffle(buffer.begin(), buffer.end(), randomInteger);
[self setArray:[NSMutableArray arrayWithObjects:&(buffer[0])
count:buffer.size()]];
}
и randomInteger в основном реализуется следующим образом:
size_t randomInteger(size_t limit)
{
return ::random() % limit;
}
Можно было бы подумать, что необходимо установить одно и то же значение семени перед выполнением каждого случайного перетасовки, которое пройдет тест, и ожидаемый массив будет соответствовать фактическому массиву.
Однако тест не работает на iOS-симуляторе, и он несколько раз задумывался о том, почему. Я наконец понял, что тест вызывает другую версию std :: random_shuffle, чем то, что используется в реализации категории. Я не знаю, почему это происходит. Что можно сделать, чтобы код проверки и реализации использовал один и тот же алгоритм std :: random_shuffle?
Ожидаемые значения не перетасовываются дважды. Содержимое массива копируется и перетасовывается. Результаты скопированного перетасовки хранятся в ожидаемых результатах
Случайное семя затем сбрасывается, поэтому он будет производить те же перетасованные результаты, а затем массив, который полностью не зависит от ожидаемых результатов, перетасовывается, и сравниваются два массива.
Кажется, я нашел проблему. Этот проект был первоначально создан с использованием Xcode 4.6, работающего на Mac OS X 10.7. Я обновился до Xcode 5, работающего на OS X 10.9, и похоже, что некоторые параметры, которые должны были быть изменены, не изменились. Я создал новое приложение с нуля и поставил тест в этом приложении, и он прошел отлично. Затем я смог посмотреть на различия между проектом.
Для самого приложения я обнаружил, что в настройках сборки в Apple LLVM 5.0 - Language - C++ стандартная библиотека C++ была установлена в Compiler Default; Я изменил его на lib C++ (стандартная библиотека LLVM C++ с поддержкой C++ 11], и это, похоже, устраняет проблему.
Мне кажется, что у вас есть логическая проблема в вашем тесте.
Во-первых, вы создаете array
и вставляете в него кучу значений. Все идет нормально.
Во-вторых, вы копируете их в values
и перетасовываете их. Все еще прекрасно.
В-третьих, вы копируете элементы из values
в expectedValues
и перетасовываете их. ОК
Наконец, вы ожидаете, что содержимое array
и expectedValues
значений expectedValues
одинаковым. Почему вы думаете, что это будет так? expectedValues
- это в основном array
, перетасованный дважды.
Если я понимаю, что вы пытаетесь проверить, я думаю, вы хотите скопировать из array
в expectedValues
и перетасовать это, а затем сравнить expectedValues
values
и values
.