Using struct with Objective-C methods - objective-c

I'm writing a simple game, and thought it would be much easier to use structures. However, I can't declare methods that need the structs.
How could I use a struct as an argument to an Objective-C method and get an object of the struct returned?
//my structure in the .h file
struct Entity
{
int entityX;
int entityY;
int entityLength;
int entityWidth;
int entityType;
bool isDead;
};
//And the methods i'm trying to use
-(BOOL)detectCollisionBetweenEntity:Entity ent1 andEntity:Entity ent2;
-(struct Entity)createEntityWithX:int newEntityX andY:int newEntityY, withType:int newEntityType withWidth:int newEntityWidth andLength:int newEntityLength;

You can use structs exactly like you would expect, your problem seems to be with the syntax of methods:
struct Entity
{
int entityX;
int entityY;
int entityLength;
int entityWidth;
int entityType;
bool isDead;
};
//And the methods i'm trying to use
-(BOOL)detectCollisionBetweenEntity:(struct Entity) ent1 andEntity:(struct Entity) ent2;
-(struct Entity)createEntityWithX:(int) newEntityX andY:(int) newEntityY withType:(int) newEntityType withWidth:(int) newEntityWidth andLength:(int) newEntityLength;
Types in methods need to be in parens, and you have to refer to struct Entity instead of Entity unless you typedef (in plain Objective-C, Objective-C++ might let you do it)

Structs are used as parameters in Objective-C all the time. For example the CGRect from Apple's CGGeometry Reference
struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect;
You just have to create a type for your struct, which can be done in the same way as Apple, or could have been done as
typedef struct CGRect {
CGPoint origin;
CGSize size;
} CGRect;
So in your case:
typedef struct
{
int entityX;
int entityY;
int entityLength;
int entityWidth;
int entityType;
bool isDead;
} Entity;
Should allow you to define
-(BOOL)detectCollisionBetweenEntity:(Entity) ent1 andEntity:(Entity) ent2;
-(Entity)createEntityWithX:int newEntityX andY:int newEntityY, withType:int newEntityType withWidth:int newEntityWidth andLength:int newEntityLength;

Related

When should we use two-dimensional pointer in objective c

I want to know when should we use two-dimensional pointer in objective c. I read a article about the runtime mechanism. The implementation details of method objc_msgSend is as follows:
Any NSObject objective has a attribute of isa which will point to the corresponding Class object.
#interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
Class objective is as follows:
struct objc_class {
Class isa;
Class superclass;
const char *name;
uint32_t version;
uint32_t info;
uint32_t instance_size;
struct old_ivar_list *ivars;
struct old_method_list **methodLists; // Method list of the class
Cache cache;
struct old_protocol_list *protocols;
}
The question I want to ask is that why methodLists is two-dimensional pointer, what if we use one-dimensional or do not use pointer, can sb explain this question to me?Thanks in advance.
The struct old_method_list is as below:
struct old_method_list {
void *obsolete;
int method_count;
/* variable length structure */
struct old_method method_list[1]; //The address of the first Method
};
OK, I read another article about why old_method_list use two-dimensional pointer, the reason is that, it may point to an array.My another question is that for struct old_method method_list[1], the comment is "The address of the first Method", but method_list is an old_method array which length is 1. How it can store address?
I solved this question by reading another article.
The array struct old_method method_list[1] is dynamic, it can be changed by adding elements(methods) to it.
Because it points at array of pointers at old_method_list.
Update for old_method_list.
old_method_list * can point not just at old_method_list. It also can point at for example:
struct old_method_list_with_10_methods
{
struct old_method_list list;
struct old_method method_list[9];
};
Or if you need dynamic size:
old_method_list* list = malloc(sizeof(old_method_list) + (n-1) * sizeof(old_method));
list->method_count = n;
It's such variable length structure.

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

Struct array in struct [Objective-c]

Let say I have these:
typedef id Title;
typedef struct{
Title title;
int pages;
}Book;
So far, the code is okay. But the problem is here:
typedef struct{
int shelfNumber;
Book book; //How can I make this an array of Book?
}Shelf;
Like what I have stated in the comment in the code, I want to make Book as array so that it can hold a number of books. Is that even possible? If it is, how can I do it?
typedef struct{
int shelfNumber;
Book book[10]; // Fixed number of book: 10
}Shelf;
or
typedef struct{
int shelfNumber;
Book *book; // Variable number of book
}Shelf;
in the latter case you'll have to use malloc to allocate the array.
Note that you could use a flexible array member to achieve this effect:
typedef struct {
int shelfNumber;
size_t nbooks;
Book book[];
} Shelf;
This is an elegant use case because you have the simplicity of use of a static array but if you need to allocate a Shelf object of size sz, you only have to do one malloc:
Shelf *mkShelf(int num, size_t sz) {
Shelf *s = malloc(sizeof(Shelf) + sz * sizeof(Book));
if (!s) return NULL;
*s = (Shelf){ num, sz };
return s;
}
Compound literals and flexible array members that I used above are C99 features, so if you program with VC++ it might not be available.

Change enum values at runtime?

Is there a way to assign values to enums during runtime in objective c?
I have several enums and want each of the enum to have certain value.
The values could be read from a xml file. Is there a way to do this?
Unfortunatley, #Binyamin is correct, you cannot do this with an enum. For this reason, I usually do the following in my projects:
// in .h
typedef int MyEnum;
struct {
MyEnum value1;
MyEnum value2;
MyEnum value3;
} MyEnumValues;
// in .m
__attribute__((constructor))
static void initMyEnum()
{
MyEnumValues.value1 = 10;
MyEnumValues.value2 = 75;
MyEnumValues.value3 = 46;
}
This also has the advantage of being able to iterate through the values, which is not possible with a normal enum:
int count = sizeof(MyEnumValues) / sizeof(MyEnum);
MyEnum *values = (MyEnum *) &MyEnumValues;
for (int i = 0; i < count; i++)
{
printf("Value %i is: %i\n", i, values[i]);
}
All in all, this is my preferred way to do enums in C.
No, enums information is erased at compile time.

Incompatible types in return?

Incompatible types in return ?
file.h
struct typeCSVFile {
NSString *nssPath;
NSString *nssData;
NSString ***p_nssData;//
int iRows;
int iCols;
};
....
struct typeCSVFile structCSVFile;
....
-(struct structCSVFile) fileCSVRead;
file.m
-(struct structCSVFile) fileCSVRead{
...
return structCSVFile; // <-- Incompatible types in return
}
Possibly, you mean:
-(struct typeCSVFile) fileCSVRead;
and:
-(struct typeCSVFile) fileCSVRead{
...
return structCSVFile;
}
The type name is struct typeCSVFile, while structCSVFile is an instance of that type. You could also think of using typedef to get rid of the struct part:
typedef struct typeCSVFile typeCSVFile;