I'm trying to use Parse SDK for iOS in my new project. It has viewController with enum property;
typedef enum {
PFLogInFieldsNone = 0,
PFLogInFieldsUsernameAndPassword = 1 << 0,
PFLogInFieldsPasswordForgotten = 1 << 1,
PFLogInFieldsLogInButton = 1 << 2,
PFLogInFieldsFacebook = 1 << 3,
PFLogInFieldsTwitter = 1 << 4,
PFLogInFieldsSignUpButton = 1 << 5,
PFLogInFieldsDismissButton = 1 << 6,
PFLogInFieldsDefault = PFLogInFieldsUsernameAndPassword | PFLogInFieldsLogInButton | PFLogInFieldsSignUpButton | PFLogInFieldsPasswordForgotten | PFLogInFieldsDismissButton
} PFLogInFields;
According to tutorial in Objective-C I should set it in this way:
[logInViewController setFields: PFLogInFieldsTwitter | PFLogInFieldsFacebook | PFLogInFieldsDismissButton];
I'm trying to do it in this way(using swift):
loginViewController.fields = PFLogInFieldsTwitter | PFLogInFieldsFacebook | PFLogInFieldsDismissButton
But I get error:"'PFLogInFields' is not convertible to 'Bool'"
So, what is the correct way to set such kind of properties?
Consecutive enums in Objective-C should be refactored to use NS_ENUM, and bit-field enums should be refactored to use NS_OPTIONS.
You should change
typedef enum {
//...
} PFLogInFields;
to
typedef NS_OPTIONS(NSInteger, PFLogInFields) {
//...
};
I had the same problem as you. See this answer for how to set PFLogInFields in Swift. It worked for me!!
In Swift you have to prefix the enums with the Type. I am not sure if this works automatically with Objective-C imports, but it might:
logInViewController.fields = PFLogInFields.PFLogInFieldsTwitter | ...
If the library were ported to Swift standard, the fields would already expect PFLoginFields and the enum items would be defined in a manner so that you can write
logInViewController.fields = .Twitter | .Facebook ...
Related
I am trying to create a simple nim wrapper around the Clever Audio Plugin c library.
In c there is an enum of format flags that can be activated using bitwise operations.
summary of the c code
# definitions
enum clap_note_dialect {
CLAP_NOTE_DIALECT_CLAP = 1 << 0,
CLAP_NOTE_DIALECT_MIDI = 1 << 1,
CLAP_NOTE_DIALECT_MIDI_MPE = 1 << 2,
CLAP_NOTE_DIALECT_MIDI2 = 1 << 3,
};
typedef struct clap_note_port_info {
...
uint32_t supported_dialects; // bitfield, see clap_note_dialect
...
} clap_note_port_info_t;
# implementation
info->supported_dialects =
CLAP_NOTE_DIALECT_CLAP | CLAP_NOTE_DIALECT_MIDI_MPE | CLAP_NOTE_DIALECT_MIDI2;
using c2nim I get the following nim code:
type
clap_note_dialect* = enum
CLAP_NOTE_DIALECT_CLAP = 1 shl 0,
CLAP_NOTE_DIALECT_MIDI = 1 shl 1,
CLAP_NOTE_DIALECT_MIDI_MPE = 1 shl 2,
CLAP_NOTE_DIALECT_MIDI2 = 1 shl 3
clap_note_port_info* {.bycopy.} = object
...
supported_dialects*: uint32 ## bitfield, see clap_note_dialect
# implementation:
info.supported_dialects = CLAP_NOTE_DIALECT_CLAP or CLAP_NOTE_DIALECT_MIDI_MPE or
CLAP_NOTE_DIALECT_MIDI2
When compiling I get an mismatch error and message that "expression 'CLAP_NOTE_DIALECT_CLAP' is of type: clap_note_dialect"
How can I let nim know that my enum should be uint32 values?
Note that you may also use an enum set in Nim when you have to wrap C enums that are used as ored bits. I did that in the GTK wrapper. You can find an example at the end of the the "Sets" section here: https://ssalewski.de/nimprogramming.html#_sets
But some care is necessary, so for plain and ugly wrappers, or unexperienced people, using distinct ints may be another solution.
This fix came from user Vindaar on the Nim #main discord channel:
"in order to or the enum values you'll want to wrap them in an ord, so:"
info.supported_dialects = ord(CLAP_NOTE_DIALECT_CLAP) or ord(CLAP_NOTE_DIALECT_MIDI_MPE) or ord(CLAP_NOTE_DIALECT_MIDI2)
How to forward declare NS_OPTIONS in Objective-C?
Related SO question for NS_ENUMS: Forward-declare enum in Objective-C
Unanswered question on Apple Dev Forum: https://forums.developer.apple.com/thread/16305
typedef NS_OPTIONS(NSInteger, MSSOption) {
MSSOptionNone = 0,
MSSOptionName = 1 << 0,
MSSOptionEmail = 1 << 1,
MSSOptionTelephone = 1 << 2
};
Strictly the same as for NS_ENUM, so the answers from Forward-declare enum in Objective-C are all valid.
To forward declare your NS_OPTIONS, you have two solutions:
solution 1
typedef NS_ENUM(NSInteger, MSSOption);
solution 2
typedef NS_OPTIONS(NSInteger, MSSOption);
Both solutions work fine. Tested with Xcode 9.3.1 and Xcode 10.1.
Demonstration at https://github.com/Coeur/StackOverflow50499172.
I was looking at PSPDFkit sample code and saw this:
NSDictionary *options = #{kPSPDFProcessorAnnotationTypes :
#(PSPDFAnnotationTypeNone & ~PSPDFAnnotationTypeLink)
};
The constants PSPDFAnnotationTypeNone and PSPDFAnnotationTypeLink are defined below:
// Available keys for options. kPSPDFProcessorAnnotationDict in
// form of pageIndex -> annotations.
// ..
extern NSString *const kPSPDFProcessorAnnotationTypes;
// Annotations defined after the PDF standard.
typedef NS_OPTIONS(NSUInteger, PSPDFAnnotationType) {
PSPDFAnnotationTypeNone = 0,
PSPDFAnnotationTypeLink = 1 << 1, // Links and multimedia extensions
PSPDFAnnotationTypeHighlight = 1 << 2, // (Highlight, Underline, StrikeOut) -
PSPDFAnnotationTypeText = 1 << 3, // FreeText
PSPDFAnnotationTypeInk = 1 << 4,
PSPDFAnnotationTypeShape = 1 << 5, // Square, Circle
PSPDFAnnotationTypeLine = 1 << 6,
PSPDFAnnotationTypeNote = 1 << 7,
PSPDFAnnotationTypeStamp = 1 << 8,
PSPDFAnnotationTypeRichMedia = 1 << 10, // Embedded PDF videos
PSPDFAnnotationTypeScreen = 1 << 11, // Embedded PDF videos
PSPDFAnnotationTypeUndefined = 1 << 31, // any annotation whose type not recognized
PSPDFAnnotationTypeAll = UINT_MAX
};
I understand that ~ is the bitwise not operator and & the bitwise and operator, but what is the purpose of their application in this code?
NSDictionary *options = #{kPSPDFProcessorAnnotationTypes :
#(PSPDFAnnotationTypeNone & ~PSPDFAnnotationTypeLink)
};
Based on comments below, the above could have been written simply as
NSDictionary *options = #{kPSPDFProcessorAnnotationTypes :#(PSPDFAnnotationTypeNone)};
Since it is the same as (0 & ~2) => 0. What's the point of adding the & ~PSPDFAnnotationTypeLink part?
"~" is the bitwise not-operator.
As "&" the bitwise and.
These are usually used for bitmask (like in your example) or other binary operations (as the name lets suggest). More info on wiki - Operators in C and C++.
They are in no relationship to literals.
First of all, I don't know obj-c, only C, but I guess the '&' is 'bitwise AND' and the '~' is bitwise NOT.
It's the bitwise NOT operator (same as many C-based languages), which inverts all bits in the underlying value.
So, for example, the eight bit value 0x57 (binary 0101 0111) becomes 1010 1000 or 0xa8.
See here for a more complete description of the various bitwise operators.
I am trying to implement the following typedef
typedef NS_OPTIONS (NSInteger, MyCellCorners) {
MyCellCornerTopLeft,
MyCellCornerTopRight,
MyCellCornerBottomLeft,
MyCellCornerBottomRight,
};
and correctly assign a value with
MyCellCorners cellCorners = (MyCellCornerTopLeft | MyCellCornerTopRight);
when drawing my cell, how can I check which of the options match so I can correctly draw it.
Use bit masking:
typedef NS_OPTIONS (NSInteger, MyCellCorners) {
MyCellCornerTopLeft = 1 << 0,
MyCellCornerTopRight = 1 << 1,
MyCellCornerBottomLeft = 1 << 2,
MyCellCornerBottomRight = 1 << 3,
};
MyCellCorners cellCorners = MyCellCornerTopLeft | MyCellCornerTopRight;
if (cellCorners & MyCellCornerTopLeft) {
// top left corner set
}
if (etc...) {
}
The correct way to check for this value is to first bitwise AND the values and then check for equality to the required value.
MyCellCorners cellCorners = MyCellCornerTopLeft | MyCellCornerTopRight;
if ((cellCorners & MyCellCornerTopLeft) == MyCellCornerTopLeft) {
// top left corner set
}
The following reference explains why this is correct and provides other insights into enumerated types.
Reference: checking-for-a-value-in-a-bit-mask
I agree with NSWill. I recently had a similar issue with wrong comparison.
The right if statement should be:
if ((cellCorners & MyCellCornerTopLeft) == MyCellCornerTopLeft){
I have an enum declaration using bit flags and I cant exactly figure out on how to use this.
enum
{
kWhite = 0,
kBlue = 1 << 0,
kRed = 1 << 1,
kYellow = 1 << 2,
kBrown = 1 << 3,
};
typedef char ColorType;
I suppose to store multiple colors in one colorType I should OR the bits together?
ColorType pinkColor = kWhite | kRed;
But suppose I would want to check if pinkColor contains kRed, how would I do this?
Anyone care to give me an example using the provided ColorType example ?
Yes, use bitwise OR (|) to set multiple flags:
ColorType pinkColor = kWhite | kRed;
Then use bitwise AND (&) to test if a flag is set:
if ( pinkColor & kRed )
{
// do something
}
The result of & has any bit set only if the same bit is set in both operands. Since the only bit in kRed is bit 1, the result will be 0 if the other operand doesn't have this bit set too.
If you need to get whether a particular flag is set as a BOOL rather than just testing it in an if condition immediately, compare the result of the bitwise AND to the tested bit:
BOOL hasRed = ((pinkColor & kRed) == kRed);