Is it possible to send a struct in a block? - ios7

I am creating a Universal Class, for SQLite and I am trying to send a block of sqlite3_step, to be processed.
In sqlite3_step, I am passing the struct object statement. But, it seems I need to use pointers.
How can I possibly do ir?

Yeah, something like this should work:
typedef struct
{
int data;
}MyStruct;
#interface Foo()
#property (nonatomic, copy) void (^myBlock)(MyStruct);
#end
#implementation Foo
- (void) someMethod {
self.myBlock = ^(MyStruct theStruct) {
NSLog(#"Value of data in the struct %i", theStruct.data);
};
MyStruct theStruct;
theStruct.data = 5;
self.myBlock(theStruct);
}
#end

Related

Property doesn't match type of instance variable?

I took some sample code from Apple's SimpleFTPSample
Which looks like this:
#interface PutController () <UITextFieldDelegate, NSStreamDelegate>
...
#property (nonatomic, assign, readonly) uint8_t *buffer;
...
#end
#implementation PutController
{
uint8_t _buffer[kSendBufferSize];
}
...
#end
But when I copy it to my code I get an error:
Type of property 'buffer' ('uint8_t *' (aka 'unsigned char *')) does not match type of instance variable '_buffer' ('unsigned char [32768]')
My code is exactly the same as their sample, and yet it won't compile. What's going on here?
Unfortunately, while arrays can decay to pointers, with clang, at least, it doesn't auto-decay into a readonly pointer when used in a property.
The simplest way to fix this is by having a second instance variable which is simply a pointer to the first element into the array, and have your property synthesize to that, like this:
#interface MyObj : NSObject
#property (readonly) uint8_t *buffer;
#end
#implementation MyObj {
uint8_t *_bufferPtr;
uint8_t _buffer[1024];
}
#synthesize buffer = _bufferPtr;
-(id) init {
if (self = [super init]) {
_bufferPtr = &_buffer[0];
}
return self;
}
#end
Alternativey, simply implement your own getter implementation to simply return the pointer to the first element of buffer. It's your call, really.
It isn't optimal, but it does appear to work the way you want.

Creating and setting typedef struct values in Objective-C

I have a class in a game that is often used, and I thought it would be nice to tidy it up by grouping together instance variables with a typedef struct. I'm not completely convinced yet this will help or not.
Originally in my class header interface I had something like this:
#interface ThingClass : CCLayer {
#public
bool _invulnerableToggled;
int _invulnerableCount;
int _invulnerableMax;
}
#property(nonatomic, assign) bool invulnerableToggled;
#property(nonatomic, assign) int invulnerableCount;
#property(nonatomic, assign) int invulnerableMax;
and in my .m
#synthesize
invulnerableToggled = _invulnerableToggled,
invulnerableCount = _invulnerableCount,
invulnerableMax = _invulnerableMax;
A subclass of this class would set these variables to their default values in init. Another class could access an instance of this subclass and set the values accordingly with regular dot notation, like tempThing.invulnerableToggled = YES;
Now that I'm using a typedef struct, it looks as though my values cannot be adjusted, and I've tried various things to overcome it. Although it may be because I'm not setting this up correctly to begin with, so just in case I'll show you what I'm doing now.
Currently my class header:
typedef struct {
bool toggled;
int count;
int max;
} Invulnerable;
#interface ThingClass : CCLayer {
#public
Invulnerable _invulnerable;
}
#property(nonatomic, assign) Invulnerable invulnerable;
and in my .m
#synthesize
invulnerable = _invulnerable;
I set these values in a subclass init like so:
_invulnerable.toggled = NO;
_invulnerable.count = 0;
_invulnerable.max = 50;
When I try to set this in another class, I expect it to add 1 to the current value. It always remains 1 instead. This if statement is sometimes checked 60 times a second, but has not change to the count:
Invulnerable invulnerable = tempBaddy.invulnerable;
// check baddy invulnerability and increment if needed
if(invulnerable.toggled == YES){
int increase = invulnerable.count +1;
invulnerable.count = increase;
NSLog(#"invulnerable.count = %i", invulnerable.count);
}
This is not a common way in ObjC but you can pass the struct by reference, i.e. return a pointer to the struct:
#interface ThingClass : CCLayer {
#protected
Invulnerable _invulnerable;
}
#property(nonatomic, readonly) Invulnerable* invulnerable;
#end
The *.m file:
#implementation ThingClass
- (Invulnerable*)invulnerable {
return &_invulnerable;
}
#end
Updating the data:
Invulnerable* invulnerable = tempBaddy.invulnerable;
// check baddy invulnerability and increment if needed
if(invulnerable->toggled == YES){
invulnerable->count++;
NSLog(#"invulnerable.count == %i", tempBaddy.invulnerable->count);
}
I guess you are trying to perform some action on an instance of ThingClass (or its subclass). And the action affects the value of _invulnerable. In this case a more common way would be having a method in the Thing class that performs all the required updates:
#implementation ThingClass
- (void)headshot {
if (_invulnerable.toggled) {
_invulnerable.count++;
} else {
[self die];
}
}
#end

Custom property's getter and setter with c++ struct array in objective-c

I've got an c-struct array, and want to define a property.
Here is the relative code..
struct Vertex {
float x, y, z;
float nx, ny, nz;
float u, v;
};
#interface Mesh : NSObject{
Vertex m_vertices[MaxVertices];
}
#property (nonatomic) Vertex m_vertices[MaxVertices];
#end
#implementation Mesh;
#synthesize m_vertices[MaxVertices];
#end
I first wrote like this with an error.
how to set the property with c-struct array, or customlize the setter and getter?
Any tips will be appreciated!
Use
#property (nonatomic) Vertex *m_vertices;
and
#synthesize m_vertices;
instead. You can't use a static array like this; malloc() it using something like this in your constructor and free() in the destructor:
- (id)init
{
if ((self = [super init]))
{
m_vertices = malloc(sizeof(*m_vertices) * NUM_OF_VERTICES);
}
return self;
}
- (oneway void)dealloc
{
free(m_vertices);
[super dealloc];
}
This was a close as I could get.
typedef struct _Vertex {
float x, y, z;
float nx, ny, nz;
float u, v;
} Vertex;
#define MaxVertices 5
#interface Mesh : NSObject{
Vertex m_verticesX[MaxVertices];
Vertex *m_vertices;
}
#property (nonatomic) Vertex *m_vertices;
#end
#implementation Mesh;
#synthesize m_vertices;
- (Vertex *)m_vertices
{
if (!m_vertices)
m_vertices = m_verticesX;
return m_vertices;
}
#end
Hope it helps.
You cannot use arrays as properties. You can do two things:
1) Use a NSArray or NSMutableArray to hold objects instead of structs.
or
2) Put the array in a structure:
typedef struct VertexArray
{
struct Vertex m_vertices [MaxVertices];
};
#property (nonatomic, assign) VertexArray* m_vertices;
or
3) Put the array in an object
#interface VertexArray
{
struct Vertex m_vertices [MaxVertices];
}
- (struct Vertex)getVertexofIndex:(NSUInteger)index;
- (void)setVertex:(struct Vertex)vertex atIndex:(NSUInteger)index;
#end
and for the property in Mesh:
#property (nonatomic, retain) VertexArray* m_vertices;
or you can put the contents of VertexArray directly within Mesh (i.e. the member variable and two accessor methods).
When you return an array of (any type) in C, you are returning the first index of the array.
So if I wanted to return the variable below that was declared in the interface.
Vertex m_vertices[MaxVertices];
I could say...
- (Vertex *)m_vertices
{
return m_vertices;
}
This above is the same thing as saying...
- (Vertex *)m_vertices
{
return &m_vertices[0];
}
If you wanted to return the entire array back however, the best way to do this would probably be to use memcpy directive.
memcpy(<#void *#>, <#const void *#>, <#size_t#>)
Reference it here: http://www.cplusplus.com/reference/cstring/memcpy/
Write the function like this...
- (Vertex *)m_vertices
{
Vertex *localVertex;
memcpy(localVertex,&m_vertices,sizeof(Vertex)* MaxVertices);
return localVertex;
}
This copies the literal bytes over and is very fast. It will return the entire array back.
The better way to do this would be to make a function like this possibly as well.
- (Vertex *)m_vertices_nthIndex:(int)index
{
return(&m_vertices[index]);
}
This way you can get the index of whatever item you need.

Is it possible to declare an Objective-C method outside a class?

I know that you can declare a C function outside of a class, but is it possible to declare a Objective-C method outside of a class?
Example:
// Works
void printHelloC()
{
NSLog(#"Hello.");
}
// Error
-(void) printHelloOC
{
NSLog(#"Hello.");
}
int main (int argc, const char * argv[])
{
#autoreleasepool {
printHelloC();
[self printHelloOC];// 'self' obviously would not work but you get the idea
}
return 0;
}
It depends. You can do something similar with method adding at runtime:
#import <objc/runtime.h>
void myCustomMethod(id self, SEL _cmd, id arg1, id arg2)
{
NSLog(#"This is a test, arg1: %#, arg2: %#", arg1, arg2);
}
int main(int argc, char *argv[])
{
Class NSObjClass = [NSObject class];
class_addMethod(NSObjClass, #selector(myNewMethod::), (IMP) myCustomMethod, "v#:##");
NSObject myObject = [NSObject new];
[myObject myNewMethod:#"Hi" :#"There"];
[myObject release];
return 0;
}
But that is about it outside of a #class construct, and it really just covers up what happens with a category.
You can use a category for this.
As an instance method:
#interface NSObject (MONStuff)
- (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
- (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
NSObject * obj = ...;
[obj printHelloOC];
As a Class method:
#interface NSObject (MONStuff)
+ (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
+ (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
[NSObject printHelloOC];
Of course, you must associate that with a class - so it's not exactly the same as you posted, but it's a close definition + declaration separate from the formal class declaration.
A method without an associated class is a meaningless concept. Functions, as you've noted, are just fine.
No, it is not possible - you will need to either use global C functions or class (+) methods.
Objective c functions are always associated with a class. If you mean you want to use an objective-c function without instantiating a class, you can of course write a class method (notice the plus sign instead of the usual hyphen)
#interface Test
+ (void)aClassMethod;
#end
then you can call it by calling
[Test aClassMethod];

getting an error in Objective C

I am getting an error in the following code. I could not guess what mistake i have done for such error to come up.
remote.h
struct RMH_REQUEST_SESSION_MSG //Message Data
{
int uDeviceID;
int uProtocolVersion;
int uReserved[5];
};
RS232MsgRequestSession.m
#implementation RS232MsgRequestSession
-(id)init
{
if (self = [super init]) {
struct RMH_REQUEST_SESSION_MSG st;
}
return self;
}
#end
xyz.h
#import "RS232MsgRequestSession.h"
#implementation xyz
-(void)Open{
RS232MsgRequestSession* pMsg = [[RS232MsgRequestSession alloc]init];
pMsg->st.uProtocolVersion = RS232_VERSION; //error
pMsg->st.uDeviceID = RS232_PROTOCOL_DEVICE_ID; //error
memset(pMsg->st.uReserved,0x00,sizeof(pMsg->st.uReserved)); //error
}
#end
Error:'struct RS232MsgRequestSession' has no member named 'st'
Put iVar declaration in class's #interface block. In your code st is just a local variable in init method:
#interface RS232MsgRequestSession : NSObject{
...
#public
struct RMH_REQUEST_SESSION_MSG st;
}
...
#end
You are defining st as a local variable in the init function.
Move struct RMH_REQUEST_SESSION_MSG st; to the class definition in RS232MsgRequestSession.h
What you forgot to do was include the struct in your #interface as a public instance variable:
#interface RMH2532MsgRequestSession : NSObject {
#public
struct RMH_REQUEST_SESSION_MSG st;
}
- (void) Open;
#end
And your #implementation should be empty:
#implementation RS232MsgRequestSession
#end
PS - The reason why you must use #public here is because in xyz, you were doing a direct dereference of the object using the member operator ->. This is not allowed by default when working with Objective-C objects. However, if the instance variables are under a #public attribute, then you will not have any problems doing this.
As you might have guessed by now, using #public is a Very Bad Idea -- usually. It breaks encapsulation and opens a pandora's box of potential problems that you wouldn't have otherwise had if you had used proper encapsulation.