Флаги, enum (C)

Я создал помощника в UIView

@interface UIView (Helper)

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset;
@end

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

[self.view roundCornerswithRadius:5 andShadowOffset:5];

Вот реализация

- (void)roundCornerswithRadius:(float)cornerRadius
               andShadowOffset:(float)shadowOffset
{
    const float CORNER_RADIUS = cornerRadius;
    const float SHADOW_OFFSET = shadowOffset;
    const float SHADOW_OPACITY = 0.5;
    const float SHADOW_RADIUS = 3.0;

    UIView *superView = self.superview;

    CGRect oldBackgroundFrame = self.frame;
    [self removeFromSuperview];

    CGRect frameForShadowView = CGRectMake(0, 0, oldBackgroundFrame.size.width, oldBackgroundFrame.size.height);
    UIView *shadowView = [[UIView alloc] initWithFrame:frameForShadowView];
    [shadowView.layer setShadowOpacity:SHADOW_OPACITY];
    [shadowView.layer setShadowRadius:SHADOW_RADIUS];
    [shadowView.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];

    [self.layer setCornerRadius:CORNER_RADIUS];
    [self.layer setMasksToBounds:YES];

    [shadowView addSubview:self];
    [superView addSubview:shadowView];

}
13
задан unwind 27 October 2009 в 14:48
поделиться

6 ответов

Ваше перечисление должно быть степенями двойки:

enum
{
    TAKES_DAMAGE = 1,
    GRABBABLE = 2,
    LIQUID = 4,
    SOME_OTHER = 8
};

Или более читаемым способом:

enum
{
    TAKES_DAMAGE = 1 << 0,
    GRABBABLE = 1 << 1,
    LIQUID = 1 << 2,
    SOME_OTHER = 1 << 3
};

Почему? Потому что вы хотите иметь возможность комбинировать флаги без перекрытия, а также иметь возможность делать это:

if(myVar & GRABBABLE)
{
    // grabbable code
}

... Что работает, если значения перечисления выглядят так:

 TAKES_DAMAGE: 00000001
 GRABBABLE:    00000010
 LIQUID:       00000100
 SOME_OTHER:   00001000

Итак, допустим, вы установили myVar в GRABBABLE | TAKES_DAMAGE , вот как это работает, когда вам нужно проверить флаг GRABBABLE:

 myVar:     00000011
 GRABBABLE: 00000010 [AND]
 -------------------
            00000010 // non-zero => converts to true

Если вы установите myVar на LIQUID | SOME_OTHER , операция привела бы к следующему:

 myVar:     00001100
 GRABBABLE: 00000010 [AND]
 -------------------
            00000000 // zero => converts to false
53
ответ дан 1 December 2019 в 05:48
поделиться

Другой способ хранения флагов - вообще не беспокоиться о базовом типе. при использовании перечисления значения перечисления по умолчанию сохраняются в целое число без знака, которое на обычном компьютере составляет 32 бита. это дает вам только 32 возможных флага: хотя, конечно, много, в некоторых случаях этого недостаточно.

теперь вы можете определить свой флаг следующим образом:

typedef struct
{
    int takes_damage : 1;
    int grabbable    : 1;
    int liquid       : 1;
    int some_other   : 1;
} flags;

если вы никогда не сталкивались с этим, часть ': 1' сообщает компилятору использовать только 1 бит для хранения этого члена структуры.

теперь вы можете определить переменную для хранения флагов и работать с этими флагами:

flags myflags = {1,0,0,1}; // defines a variable holding a set of flags, with an initial value of takes_damage & some_other

myflags.liquid = 1; // change the flags to include the liquid

if ( myflags.takes_damage ) // test for one flag
    apply_damage();
if ( myflags.liquid && myflags.some_other ) // test for multiple flags
    show_strange_behavior();

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

28
ответ дан 1 December 2019 в 05:48
поделиться

Да. Вместо этого сделайте члены перечисления степенями 2:

enum
{
    TAKES_DAMAGE = (1 << 0),
    GRABBABLE = (1 << 1),
    LIQUID = (1 << 2),
    SOME_OTHER = (1 << 3)
};
5
ответ дан 1 December 2019 в 05:48
поделиться

Вы должны сделать флаги только степенями двойки, то есть каждый из них является битом в любом типе данных, в котором вы его храните, и ничто не перекрывается при побитовом ИЛИ.

4
ответ дан 1 December 2019 в 05:48
поделиться

вам нужно

enum
{
    TAKES_DAMAGE = 1,
    GRABBABLE = 2,
    LIQUID = 4,
    SOME_OTHER = 8
};
3
ответ дан 1 December 2019 в 05:48
поделиться

Нельзя просто установить значения в enum?

enum {
 TAKES_DAMAGE = 1,
 GRABBABLE    = 2,
 LIQUID       = 4
}

После этого просто выполните для них побитовое ИЛИ.

4
ответ дан 1 December 2019 в 05:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: