Bitmasking in Objective C

I'd like to learn bit masking. As far as I understand, it is means to store binary values of certain type into one variable.

If the above assumption is true, I figured I could do something like this:

typedef NSUInteger Traits;

enum
{
    TraitsCharacterHonest       = 0,
    TraitsCharacterOptimistic   = 1,
    TraitsCharacterPolite       = 4,
    TraitsCharacterDevious      = 8,
    TraitsPhysicalTall          = 16,
    TraitsPhysicalBeautiful     = 32,
    TraitsPhysicalFat           = 64,
    TraitsPhysicalBigEyes       = 128,
    TraitsPhysicalRedHair       = 256, 
};

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (strong, nonatomic) NSString  *name;
@property (assign, nonatomic) Traits    *traits;

@end

Question 1 is, how do I assign more traits to one person?

Question 2 is, do I have to put ever increasing numbers to enum items, or is there a way to indicate this?

Ultimately I want to achieve something like this:

Person *john = [[Person alloc] init];

//here code that assigns john three traits: TraitsCharacterHonest,      
//TraitsCharacterOptimistic and TraitsPhysicalBeautiful.

If I understand it correctly, the value of

john.traits should be 100011., reading from right and each place representing that particular enum value / trait..and 0 meaning not having it and 1 meaning having it.

Can you please advice on syntax and explain a particular aspect if needed?

Answers


I'd recommend changing a few things:

  • The enum values can be changed to be a one left-shifted. Makes it a little easier to write, in my opinion.

  • You don't need to typedef to NSUInteger, you can declare a enum type directly using typedef enum.

  • And, as other people have mentioned, your property shouldn't be a pointer to a Traits type.

My code would look like this:

typedef enum
{
    TraitsCharacterHonest       = 1 << 0,
    TraitsCharacterOptimistic   = 1 << 1,
    TraitsCharacterPolite       = 1 << 2,
    TraitsCharacterDevious      = 1 << 3,
    TraitsPhysicalTall          = 1 << 4,
    TraitsPhysicalBeautiful     = 1 << 5,
    TraitsPhysicalFat           = 1 << 6,
    TraitsPhysicalBigEyes       = 1 << 7,
    TraitsPhysicalRedHair       = 1 << 8
} Traits;

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (strong, nonatomic) NSString  *name;
@property (assign, nonatomic) Traits     traits;

@end

Setting John's traits will look like this:

Person *john = [[Person alloc] init];

john.traits = TraitsCharacterHonest | TraitsCharacterOptimistic | TraitsPhysicalBeautiful;

However, while bit-fields are useful to learn, but they're a real pain to debug. If you want to go and print this character's traits now, you'll have to write code like this:

NSMutableString *result = [NSMutableString string];

if (self.traits & TraitsCharacterHonest)
{
    [result appendString: @"Honest, "];
}
if (self.traits & TraitsCharacterOptimistic)
{
    [result appendString: @"Optimistic, "];
}
if (self.traits & TraitsCharacterPolite)
{
    [result appendString: @"Polite, "];
}
// etc...

Additionally, syntax for operations like removing a trait are confusing. You'll have to use & and a NOT-ed constant,

// remove 'Tall' trait
john.traits = john.traits & ~TraitsPhysicalTall

If you can (and performance isn't too much of a issue), I'd prefer using a higher-level feature. Perhaps an NSSet with string constants? e.g.

__unused static NSString *TraitsCharacterHonest = @"TraitsCharacterHonest";
__unused static NSString *TraitsCharacterOptimistic = @"TraitsCharacterOptimistic";
__unused static NSString *TraitsCharacterPolite = @"TraitsCharacterPolite";
// etc...

@interface Person : NSObject

@property (strong, nonatomic) NSString     *name;
@property (assign, nonatomic) NSMutableSet *traits;

@end

Then you can do:

// adding
[john.traits addObject: TraitsCharacterHonest];
// checking
[john.traits containsObject: TraitsCharacterHonest];
// removing 
[john.traits removeObject: TraitsCharacterHonest];

Makes more sense to me. What's more, you can print the description of the traits directly with

NSLog(@"John's traits: %@", john.traits);

and you'll get reasonable output.


Need Your Help

glTexSubImage2D with GL_PIXEL_UNPACK_BUFFER gives GL_INVALID_OPERATION

osx opengl pbo

Currently I am attempting to use PBOs to get video data to textures. I'm not sure if what I'm trying to do is even possible, or a good way to do it if it IS possible... I have 3 textures with the G...