passing a value not defined in enum - objective-c

I have a class named blender that has a single instance variable, speed. speed is of type enum BlenderSpeed defined as
typedef NS_ENUM(NSUInteger, BlenderSpeed)
{
BlenderSpeedStir=1 ,
BlenderSpeedCop=2 ,
BlenderSpeedCrush=3
} ;
The main.m is as below. Basically, I was expecting there to be a warning when I passed 5 as argument in the setSpeed message send since speed is only supposed to take on values 1, 2 and 3 per enum definition.
But I don't see any issues when I build and run the code. The speed gets set to 5 without any issues.
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
blender *myBlender = [[blender alloc] init] ;
[myBlender setSpeed:2] ;
NSLog(#"Current blender speeed = %lu",[myBlender speed]);
[myBlender setSpeed:5] ;
NSLog(#"Current blender speeed = %lu",[myBlender speed]);
}
return 0;
}
Any pointers will be greatly appreciated.

Related

Objective-C source code debug: Thread Error

I cannot seem to solve this problem, im not sure what it is at this point but the tread error wont go away. I cant seem to find what im doing wrong.
This code may be a handful to read (sorry) but its very simple. I'am basically invoking a function from main and passing an array of function values, from there im passing two fractions at a time to a method so it find the LCM(least common multiple) using the denominators and return the value. But a thread error seems to be occurring at the call to the findLCM method from function at the point of where the method is declared.
#interface Fraction: NSObject
#property int numerator, denominator;
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction;
#implementation Fraction
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction{
int lcmOfFraction = 0;
int a, b;
a = fraction.denominator;
b = self.denominator;
int max =(a>b) ? a : b; // get max value out of the two denominators.
for (int i = 0; i < Xfraction; i++) {
while(1) /* Always true. */
{
if(max%a==0 && max%b==0)
{ lcmOfFraction = max;
break; /* while loop terminates. */
}
++max;
}
}
Fraction *lcmDenominator = [Fraction new];
[lcmDenominator setTo:0 over:max]; //passing just LCM (denominator of 2 fractions)
return lcmDenominator;
}
Fraction *addFraction(Fraction **arrayOfFractions, int arraySize) {
Fraction *LCM = [[Fraction alloc] init];
int lcmOfFractions = 0;
[LCM setTo:0 over:1];
for (int i = 0; i <= arraySize; i++) {
LCM = [LCM findLCM:arrayOfFractions[i] withXFractions:4];
//^gets the LCM (the common denominator)
}
return LCM;
}
int main () {
#autoreleasepool {
[frac1 setTo:2 over:12]; [frac2 setTo:2 over:4];
[frac3 setTo:6 over:8]; [frac4 setTo:8 over:3];
Fraction __autoreleasing *arrayOfFractions[4] = {frac1, frac2, frac3, frac4 };
Fraction *LCMFraction = addFraction(arrayOfFractions, 4);
//common LCM return
}
}
You create no threads in this code. When asking a question like this you should clearly explain what the error is, and what you have tried to find its source. People may then be able to help you.
Some hints/suggestions:
use breakpoints to stop your code during execution to allow you to examine the values of your variables
pay close attention to indexing operations, you are using a C array and those do not do bounds checking
ask whether using a C array here, rather than an NSArray is your best choice. Note there is nothing wrong with using C arrays when appropriate.
__autoreleasing probably doesn't mean what you think it does, it is rare to see this used explicitly in user code.
If you have a specific question when you've got further ask a new question on SO, somebody will probably be able to help you out.
HTH

Simplify block reference declaration using typedefs

I'm working through Advanced Mac OS X Programming book and one exercise has me stumbled.
Use typedefs to simplify the following block reference declaration:
int (^(*(^get_block_factory_funcptr)(void))(int))(void);
Here's how I understand the declaration:
Function not taking arguments, returns a block which returns a void pointer, which is a pointer to a function that takes int for an argument and returns a block which has no arguments, returns an int.
Now given that, I have these 2 typedefs
typedef void *(^get_block_factory_funcptr)(void);
typedef int (^myBlock(int))(void);
However I have no idea how to combine them to a single declaration, any help appreciated
If I'm reading it correctly, it's a block that returns a function pointer that returns a block. The name is a hint.
One way to figure it out is to start with the end result and work backwards. Or, start from the inside and work outwards.
What is get_block_factory_funcptr? It's a block:
MyBlock get_block_factory_funcptr;
What does it do? It takes a void and it returns a "Block Factory" function pointer. Let's declare MyBlock:
typedef FactoryFuncPtr (^MyBlock)(void);
What is FactoryFuncPtr? It takes an int and returns another block:
typedef OuterBlock (*FactoryFuncPtr)(int);
What is OuterBlock? It takes a void and returns an int:
typedef int (^OuterBlock)(void);
Those are the declarations in reverse order.
Edit: A working example.
#import <Foundation/Foundation.h>
typedef int (^OuterBlock)(void);
typedef OuterBlock (*FactoryFuncPtr)(int);
typedef FactoryFuncPtr (^MyBlock)(void);
OuterBlock factory(int foo) {
return ^ {
printf("A block with %d\n", foo);
return 123;
};
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
int (^(*(^get_block_factory_funcptr)(void))(int))(void) = ^ {
return &factory;
};
MyBlock myBlock = get_block_factory_funcptr;
FactoryFuncPtr foo = myBlock();
OuterBlock bar = foo(999);
int baz = bar();
printf("Final %d\n", baz);
}
return 0;
}

Objective-C: printing enum values

I was trying to print out the enum constant in Objective-C on Xcode.
The code:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
enum boolean{
no, yes
};
NSLog(#"%d", yes);
}
return 0;
}
I ran this code and all the console is showing me is "(lldb)".
Is it the syntax that I got wrong?
Or am I missing something here?
Also, I tried it different way using typedef:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
typedef enum {
no, yes
} boolean;
boolean boolVal = yes;
NSLog(#"%d", boolVal);
}
return 0;
}
I suspect I did something wrong with printing out the value, with NSLog().
But I have tried using %i, %#, %d. But the output was same, (lldb).
Are there any different ways to print out the enum values?
You have to give the members of the enum values is you want to print them. Try the following.
enum boolean {
no = 0,
yes = 1
};
NSLog(#"yes = %d",yes);
The previous code outputs the following.
yes = 1

Programmatically get all frame variables in objective-c

I'm trying to create my own custom assert. However, I would like my assertion to automatically include all of the relevant variables. This seems really basic to me, and I've searched around for about an hour but I can't seem to find a way get access to all the relevant stack frame variables. Does anyone know how to get these variables?
FYI - I don't need to access the variables in the debugger, I need to access them programmatically. I would like to upload them along with the crash report to give me more information about the crash. I also know that I can print them out manually...that is exactly what I'm looking to avoid.
You are basically asking to re-invent a good sized chunk of the debugger.
Without symbols, there isn't anything you can interrogate to figure out the layout of the local frame. Even with symbols, it is quite likely that the optimizer will have stomped on any local variables as the optimizer will re-use stack slots at whim once it determines the variable is no longer needed within the frame.
Note that many crashes won't be able to be caught at all or, if caught, the frame within which they occurred will have long since been destroyed.
Since you mention that you are creating a custom assertion, it sounds like you really aren't looking to introspect crashes as much as dump a snap of the local frame when you programatically detect that things have gone off the rails. While there really isn't a means of automatically reporting on local stack state, you could do something like:
{ ... some function ....
... local variables ...
#define reportblock ^{ ... code that summarizes locals ... ; return summary; }
YourAssert( cond, "cond gone bad. summary: %#", reportblock());
}
Note that the #define ensures that each YourAssert() captures the state at the time of the assertion. Note also that the above might have a potentially significant impact on performance.
Note also that I just made that code up. It seems like it is worthy of investigation, but may prove non-viable for a number of reasons.
If you're willing to use Objective-C++, then this is definitely a possibility, as long as you are also willing to declare your variables differently, and understand that you will only be able to grab your own variables with this method.
Also note that it will increase your stack frame size with extra __stack_ variables, which could cause memory issues (although I doubt it, personally).
It won't work with certain constructs such as for-loops, but for 95% of cases, this should work for what you need:
#include <vector>
struct stack_variable;
static std::vector<const stack_variable *> stack_variables;
struct stack_variable {
void **_value;
const char *_name;
const char *_type;
const char *_file;
const char *_line;
private:
template<typename T>
stack_variable(const T& value, const char *type, const char *name, const char *file, const char *line) : _value((void **) &value), _type(type), _name(name), _file(file), _line(line) {
add(*this);
}
static inline void add(const stack_variable &var) {
stack_variables.push_back(static_cast<const stack_variable *>(&var));
}
static inline void remove(const stack_variable &var) {
for (auto it = stack_variables.begin(); it != stack_variables.end(); it++) {
if ((*it) == &var) {
stack_variables.erase(it);
return;
}
}
}
public:
template<typename T>
static inline stack_variable create(const T& value, const char *type, const char *name, const char *file, const char *line) {
return stack_variable(value, type, name, file, line);
}
~stack_variable() {
remove(*this);
}
void print() const {
// treat the value as a pointer
printf("%s:%s - %s %s = %p\n", _file, _line, _type, _name, *_value);
}
static void dump_vars() {
for (auto var : stack_variables) {
var->print();
}
}
};
#define __LINE_STR(LINE) #LINE
#define _LINE_STR(LINE) __LINE_STR(LINE)
#define LINE_STR _LINE_STR(__LINE__)
#define LOCAL_VAR(type, name, value)\
type name = value;\
stack_variable __stack_ ## name = stack_variable::create<type>(name, #type, #name, __FILE__, LINE_STR);\
(void) __stack_ ## name;
Example:
int temp() {
LOCAL_VAR(int, i_wont_show, 0);
return i_wont_show;
}
int main(){
LOCAL_VAR(long, l, 15);
LOCAL_VAR(int, x, 192);
LOCAL_VAR(short, y, 256);
temp();
l += 10;
stack_variable::dump_vars();
}
Output (note the junk extra bytes for the values smaller than sizeof(void *), there isn't much I can do about that):
/Users/rross/Documents/TestProj/TestProj/main.mm:672 - long l = 0x19
/Users/rross/Documents/TestProj/TestProj/main.mm:673 - int x = 0x5fbff8b8000000c0
/Users/rross/Documents/TestProj/TestProj/main.mm:674 - short y = 0xd000000010100
Threads will royally screw this up, however, so in a multithreaded environment this is (almost) worthless.
I decided to add this as a separate answer, as it uses the same approach as my other one, but this time with an all ObjC code. Unfortunately, you still have to re-declare all of your stack variables, just like before, but hopefully now it will work better with your existing code-base.
StackVariable.h:
#import <Foundation/Foundation.h>
#define LOCAL_VAR(p_type, p_name, p_value)\
p_type p_name = p_value;\
StackVariable *__stack_ ## p_name = [[StackVariable alloc] initWithPointer:&p_name\
size:sizeof(p_type)\
name:#p_name\
type:#p_type\
file:__FILE__\
line:__LINE__];\
(void) __stack_ ## p_name;
#interface StackVariable : NSObject
-(id) initWithPointer:(void *) ptr
size:(size_t) size
name:(const char *) name
type:(const char *) type
file:(const char *) file
line:(const int) line;
+(NSString *) dump;
#end
StackVariable.m:
#import "StackVariable.h"
static NSMutableArray *stackVariables;
#implementation StackVariable {
void *_ptr;
size_t _size;
const char *_name;
const char *_type;
const char *_file;
int _line;
}
-(id) initWithPointer:(void *)ptr size:(size_t)size name:(const char *)name type:(const char *)type file:(const char *)file line:(int)line
{
if (self = [super init]) {
if (stackVariables == nil) {
stackVariables = [NSMutableArray new];
}
_ptr = ptr;
_size = size;
_name = name;
_type = type;
_file = file;
_line = line;
[stackVariables addObject:[NSValue valueWithNonretainedObject:self]];
}
return self;
}
-(NSString *) description {
NSMutableString *result = [NSMutableString stringWithFormat:#"%s:%d - %s %s = { ", _file, _line, _type, _name];
const uint8_t *bytes = (const uint8 *) _ptr;
for (size_t i = 0; i < _size; i++) {
[result appendFormat:#"%02x ", bytes[i]];
}
[result appendString:#"}"];
return result;
}
+(NSString *) dump {
NSMutableString *result = [NSMutableString new];
for (NSValue *value in stackVariables) {
__weak StackVariable *var = [value nonretainedObjectValue];
[result appendString:[var description]];
[result appendString:#"\n"];
}
return result;
}
-(void) dealloc {
[stackVariables removeObject:[NSValue valueWithNonretainedObject:self]];
}
#end
Example:
#include "StackVariable.h"
int temp() {
LOCAL_VAR(int, i_wont_show, 0);
return i_wont_show;
}
int main(){
LOCAL_VAR(long, l, 15);
LOCAL_VAR(int, x, 192);
LOCAL_VAR(short, y, 256);
temp();
l += 10;
puts([[StackVariable dump] UTF8String]);
}
Output:
/Users/rross/Documents/TestProj/TestProj/main.m:676 - long l = { 19 00 00 00 00 00 00 00 }
/Users/rross/Documents/TestProj/TestProj/main.m:677 - int x = { c0 00 00 00 }
/Users/rross/Documents/TestProj/TestProj/main.m:678 - short y = { 00 01 }
This requires ARC (and all of it's magic) enabled for any file you want to test this in, or you will manually have to release the __stack_ variables, which won't be pretty.
However, it now gives you a hex dump of the variable (rather than the weird pointer one), and if you really tried hard enough (using __builtin_types_compatible), it could detect whether the result was an object, and print that.
Once again, threads will mess this up, but a simple way to fix that would be to create a NSDictionary of NSArrays, with a NSThread as the key. Makes it a bit slower, but let's be honest, if you're using this over the C++ version, you aren't going for performance.

Objective-C error: initializer element is not constant

Why does the compiler give me the following error message on the provided code: "initializer element is not constant". The corresponding C/C++ code compiles perfectly under gcc.
#import <Foundation/Foundation.h>
const float a = 1;
const float b = a + a; // <- error here
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
That code will only compile correctly if the const float statements appear somewhere other than the file scope.
It is part of the standard, apparently. It is important that all file-scope declared variables are initialised with constant expressions, not expressions involving constant variables.
You are initialising the float 'b' with the value of another object. The value of any object, even if it is a const qualified, is not a constant expression in C.
#dreamlax is correct, you can't have a const declaration whose initialization depends upon another (const) variable. If you need one to depend on the other, I suggest creating a variable that you can treat as a constant and initialize it only once. See these SO questions for details:
Defining a constant in objective-c
Constants in Objective C
I don't have Xcode on my machine here so I can't try my example,
But can you try
#define A (1)
#define B (A + A)
const float a = A;
const float b = B;