2010-03-03 2 views
3

Я пытаюсь определить чрезвычайно простой метод утилиты, который избавит меня от необходимости использовать калькулятор для определения значений RGB в процентах. Когда я смотрю в образец кода от Apple под названием «QuartzCache», в файле DrawView.m, строка 96, я вижу это:Objective-C Параметры метода Задача

float whiteColor[4] = {1, 1, 1, 1}; 

Однако, когда я пытаюсь создал метод, как в следующем, компилятор меня ненавидит , Полчаса интенсивного Googling не помогли.

+(float[])percentagesRGBArray:(float[])rgbArray{ 

     float red = rgbArray[0]; 
     float green = rgbArray[1]; 
     float blue = rgbArray[2]; 
     float alpha = rgbArray[3]; 
     red = red/255; 
     green = green/255; 
     blue = blue/255; 
     alpha = alpha; 
     float percentagesRGBArray[4] = {red, green, blue, alpha}; 


     return percentagesRGBArray; 
    } 

Каков правильный способ определения такого метода? Что я здесь делаю неправильно?

+0

Хорошо знать, что ваш компилятор вас ненавидит, но также хорошо знать, какую ошибку он производит. Если вы можете включить оба, это помогает :) –

ответ

5

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

  • struct путь:

    typedef struct 
    { 
        float red; 
        float green; 
        float blue; 
        float alpha; 
    } MyColor; 
    
    - (MyColor) percentagesRGBArray:(MyColor) incoming 
    { 
        MyColor result; 
        result.red = incoming.red/255; 
        result.green = incoming.green/255; 
        result.blue = incoming.blue/255; 
        result.alpha = incoming.alpha; 
        return result; 
    } 
    
  • NSNumber путь:

    - (NSArray *) percentagesRGBArray:(float[]) rgbArray 
    { 
        NSNumber *red = [NSNumber numberWithFloat:rgbArray[0]/255]; 
        NSNumber *green = [NSNumber numberWithFloat:rgbArray[1]/255]; 
        NSNumber *blue = [NSNumber numberWithFloat:rgbArray[2]/255]; 
        NSNumber *alpha = [NSNumber numberWithFloat:rgbArray[3]]; 
    
        return [NSArray arrayWithObjects:red, green, blue, alpha, nil]; 
    } 
    
  • NSColor путь:

    - (NSColor *) percentagesRGBArray:(float[]) rgbArray 
    { 
        CGFloat red = rgbArray[0]/255; 
        CGFloat green = rgbArray[1]/255; 
        CGFloat blue = rgbArray[2]/255; 
        CGFloat alpha = rgbArray[3]; 
    
        return [NSColor colorWithDeviceRed:red 
               green:green 
                blue:blue 
               alpha:alpha]; 
    } 
    
+0

+1 Это гораздо более глубокий, чем мой ответ. –

+0

Спасибо. Я узнал больше от этого ответа, чем вы могли себе представить. – mwt

3

Как правило, вы должны использовать класс Cocoa NSColor для управления такими вещами, но похоже, что вы делаете что-то более низкоуровневое.

В этом случае, я хотел бы сделать следующее:

typedef struct 
{ 
    float red; 
    float green; 
    float blue; 
    float alpha; 
} 
RGBAData; 

RGBAData ConvertRGBAToPercentages(const RGBAData source) 
{ 
    RGBAData percentages; 

    percentages.red = source.red/255; 
    percentages.green = source.green/255; 
    percentages.blue = source.blue/255; 
    percentages.alpha = source.alpha/255; 

    return percentages; 
} 

Для того, чтобы использовать следующим образом:

RGBAData original = { 0xFF, 0xFF, 0x00, 0x80 }; // 50% transparent yellow 
RGBAData percents = ConvertRGBAToPercentages(original); 
+0

Если вы * можете * использовать 'NSColor', я бы предложил использовать удобную категорию для упрощения взаимодействия. Я опубликовал одну такую ​​категорию в одном из моих собственных вопросов: http://stackoverflow.com/questions/1342286/what-kind-of-category-methods-do-you-use-to-make-cocoa-programming-easier –

+0

Вам не нужно объявлять 'percentages' как' struct RGBAData percentages' (а также для 'original' и' percents') или 'typedef'' '' '' 'как' RGBAData'? edit: Я думаю, что мой ответ слишком длинный. , , +1 для простоты :) – dreamlax

+0

А, спасибо. хорошая точка зрения. Я исправлю объявление –

2

Ответы на e.James и Dreamlax дают хорошие подходы для этого. Но чтобы ответить на то, что было не так с вашим исходным кодом:

В принципе, это связано с тем, как работают массивы C. Массив по существу эквивалентен указателю на его первый элемент. Фактически, когда вы передаете массив функции, она распадается на указатель. Вам по-прежнему разрешено указывать аргумент float myArray[4] (вы должны объявить число элементов), чтобы было ясно, что указатель должен быть в виде массива из 4 элементов, но вы все равно получаете указатель. Теперь рассмотрим возвращаемое значение. Что ты возвращаешь? Мы уже установили, что вы не можете вернуть массив по значению, потому что он распадается на указатель. Но даже если вы измените тип возвращаемого значения на указатель, он все равно не будет работать, потому что после возвращения функции массив исчезнет из области видимости. Чтобы вернуть массив, вы должны malloc память, а затем вы несете ответственность за ее освобождение позже.

Вот почему вам следует избегать работы с массивами C, когда это возможно. Они действительно низкоуровневые и неудобные. Даже когда вы их используете, обычно рекомендуется скрывать их за API, который заботится о деталях низкого уровня для вас.

+0

+1 для описания проблемы :) –

+0

Я вижу. Спасибо. – mwt

0

Я думаю, что я опаздываю), но я только что нашел эту тему.

C способ сделать это - создать массив перед вызовом функции;

+(void) percentagesRGBArray:(float[])inArray toArray:(float*)outArray { 
    ... 
} 

float array1[4]; 
float array2[4]; 
[MyClass percentagesRGBArray:array1 toArray:array2]; 
Смежные вопросы