Задача параметров метода Objective C - PullRequest
3 голосов
/ 04 марта 2010

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

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

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

 +(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;
    }

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

Ответы [ 4 ]

5 голосов
/ 04 марта 2010

Определите 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];
    }
    
3 голосов
/ 04 марта 2010

Обычно вы используете класс 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);
2 голосов
/ 04 марта 2010

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

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

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

0 голосов
/ 02 сентября 2010

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

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

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

float array1[4];
float array2[4];
[MyClass percentagesRGBArray:array1 toArray:array2];
...