2009-10-05 4 views
18

Является ли это действительным способом инициализации NSArray с поплавковыми объектами?Инициализировать NSArray с поплавками?

NSArray *fatArray = [NSArray arrayWithObjects: 
        [NSNumber numberWithFloat:6.9], 
        [NSNumber numberWithFloat:4.7], 
        [NSNumber numberWithFloat:6.6], 
        [NSNumber numberWithFloat:6.9],nil]; 

Это работает, и он чувствует себя хорошо, просто хотел удостовериться, что я был на правильном пути.

Гэри

ответ

32

Как уже писал мувицель, это способ сделать это. Когда я пишу что-то вроде этого, я обычно сделать код короче, используя простой макрос:

#define FBOX(x) [NSNumber numberWithFloat:x] 

Затем вы можете переписать код так:

NSArray *fatArray = [NSArray arrayWithObjects: 
    FBOX(6.9), FBOX(4.7), FBOX(6.6), FBOX(6.9), nil]; 

Макросы являются злом, но в этом случае макросъемки так просто, я бы использовал его. Плюс код болит немного меньше, чтобы читать, особенно если определение макроса не далеко.

Если вы написали много таких кодов, вы можете создать категорию с пользовательским инициализатором с переменным числом из float аргументов, но тогда возникает проблема с окончанием списка аргументов. Сначала вы можете сместить общее число поплавок:

- (id) initWithFloats: (int) numFloats data: (float) float1, ...; 

Но подсчет аргументов вручную является склонным к ошибке. Или вы можете использовать какое-то значение дозорного, такое как ноль, который будет отмечать конец списка аргументов, но это открывает целую новую червь червей, называемую с плавающей запятой.


Пожалуйста, обратите внимание, что в настоящее время вы можете просто написать следующее:

NSArray *list = @[@6.9, @4.7, @6.6, @6.9]; 

Это не синтаксис мечта сбылась, но это официально поддерживается компилятором, и это намного лучше, чем предыдущие решения. See the documentation for more goodness.

+1

Большое спасибо – fuzzygoat

+0

Сравнение с 0.0 не проблематично, но это часто не полезно. Мне нравится идея макроса. –

4

Насколько я знаю, это вполне допустимый способ положить поплавки в NSArray.

+1

Это * * является путь! – Wevah

1

Я согласен с mouviciel. Поскольку вы не можете поместить простые типы в массив, это способ сделать это. Выглядит немного странно и написано много кода, но все в порядке.

3

Переход на небольшую касательную, если все, что вы хотите сделать, это хранить массив поплавков и не нуждается в дополнительных функциях NSArray или NSNumber, тогда вы также должны рассмотреть только стандартный массив C:

float fatArray[] = {6.6, 6.9, 4.7, 6.9}; 
+1

Конечно, массивы C не проверяются по границам или не подсчитываются по ссылке, поэтому, если вы пишете ошибку, связанную с ней, вы вряд ли поймаете ее быстро. –

+2

правда, но, похоже, немного расточительно выделить 5 объектов для хранения 4 поплавков. – pxl

+0

Объекты NS необходимы для сохранения в NSUserDefaults. Поскольку они более сложны, если нет необходимости их использовать, тогда OP уже будет использовать более простую конструкцию, приведенную здесь. – DragonLord

1

Если вы собираетесь создавать много этих массивов с точно таким же числом элементов, можно определить FloatArrayFactory класс, который реализует что-то вроде:

+ (NSArray *) arrayWithFloat: (float)f; 
+ (NSArray *) arrayWithFloat: (float)f1 and: (float)f2; 
+ (NSArray *) arrayWithFloat: (float)f1 and: (float)f2 and: (float)f3; 
+ (NSArray *) arrayWithFloat: (float)f1 and: (float)f2 and: (float)f3 and: (float)f4; 

И если это слишком многословным , вы могли бы пойти на краткий и надуманный взгляд u nnamed параметры:

+ (NSArray *) arr: (float)f1 : (float)f2 : (float)f3; 

, которые вы можете назвать так:

NSArray *a = [Factory arr: 1.0 :2.0 :3.0 :4.0]; 
+0

Или вместо фабрики сделайте это категорией (это то, для чего они были изобретены) –

+0

Я на самом деле написал это как категорию изначально, но понял, что не все это полезно для добавления методов построения в NSArray. –

1

Если у вас есть много поплавков, чтобы преобразовать, или хотите, чтобы вставить их из через запятую, что может быть проще для вызова функции, которая преобразует float в экземпляр NSArray.

NSArray* arrayFromFloats(NSUInteger count, float *floats) 
{ 
    NSMutableArray* ma = [NSMutableArray arrayWithCapacity:count]; 
    NSUInteger i; 
    for (i=0; i<count; i++) { 
     [ma addObject:[NSNumber numberWithFloat:floats[i]]]; 
    } 
    return (NSArray*)ma; 
} 

Пример вызывающего абонента:

static float floats[] = {1.1, 2.2, 3.3}; 
NSUInteger count = sizeof(floats)/sizeof(float); 
NSArray* a = arrayFromFloats(count, floats); 
+0

Прежде всего, так как нет причин для передачи отрицательного 'count', он должен быть неподписанным; «int», а не иначе квалифицированный, подписан. Во-вторых, это должен быть 'NSUInteger' вместо (' unsigned') 'int', на всякий случай, если у вас будет более четырех миллиардов' float' (возможно при работе в 64-разрядной версии). –

+0

Спасибо, Питер. Я изменил 'int' на' NSUInteger' в моем примере кода. – user206499

+0

не соглашается на NSUInteger вместо unsigned int; unsigned int в порядке, почему бы и нет (и NSUInteger _can_ be 'unsigned int', и нам не нужно больше индексировать элементы ~ 4 * 10^9, которых достаточно для большого количества приложений) – ShinTakezou

1

Другой ленивый вариант просто использовать массив NSStrings, а затем получить тип значения, вы ищете непосредственно из строки.

Как так:

NSArray *arrayOfNumbers = [NSArray arrayWithObjects:@"3.12",@"3.2", @"12", @"15", nil]; 
float number = [[arrayOfNumbers objectAtIndex:0] floatValue]; 
Смежные вопросы