Cocoa Objective-c Property C structure assign fails - objective-c

I want to change the variable value which is a member of a structure of another class.
But the value is not getting changed.
Here is the code.
//Structure..
typedef struct {
int a;
double b;
} SomeType;
//Class which has the structure as member..
#interface Test2 : NSObject {
// Define some class which uses SomeType
SomeType member;
}
#property SomeType member;
#end
#implementation Test2
#synthesize member;
#end
//Tester file, here value is changed..
#implementation TesstAppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
Test2 *t = [[Test2 alloc]init];
t.member.a = 10;
//After this the value still shows 0
}
#end
I tried out with the below link.
Structure as a class member in Objective C
Regards,
Dhana.

To make a change to your 'member' instance variable, you need to set it in its entirety. You should do something like:
SomeType mem = t.member;
mem.a = 10;
t.member = mem;
The problem is that t.member is being used as a "getter" (since it's not immediately followed by an '='), so t.member.a = 10; is the same as [t member].a = 10;
That won't accomplish anything, because [t member] returns a struct, which is an "r-value", ie. a value that's only valid for use on the right-hand side of an assignment. It has a value, but it's meaningless to try to change that value.
Basically, t.member is returning a copy of your 'member' struct. You're then immediately modifying that copy, and at the end of the method that copy is discarded.

Make a pointer to your struct instead, then just dereference it when you want to change a part of it.
Example:
struct myStruct {
int a,
b;
};
#interface myClass : NSObject {
myStruct *testStruct;
}
#property myStruct *testStruct;
Then to change a part of myStruct just do myClassObject.testStruct->a = 55;

Change the synthesize line to:
#synthesize member = _member;
Then you can assign values in one line of code:
_member.a = 10;

Related

Is it possible to send a struct in a block?

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

Is it possible to apply rules to a Objective C class properties for RPG attributes?

In Objective C you write 20 or so RPG attributes like:
#interface Employee : NSObject
{
NSString *name;
NSString *nickname;
NSString *filename;
// Attributes
int personality;
int behaviour;
int attitude;
int workrate;
int morale;
int health;
}
I want to make all my RPG attributes listen to rules. ie: Personality can be 1-99, health can be 1-100, morale can be 0-100 and so on.
I'd like to know if I can make a class for Attributes that will automatically test whether the number stored is within rules; this way I can save time having to test it for like 20 different fields.
I guess I could use a dictionary, but even if I do this I'd like to make sure the attributes listen to rules.
Is this kind of thing possible?
Yeah, you'd generally make each attribute a #property and provide a custom setter which either rejects or corrects invalid values:
.h file:
#interface Employee : NSObject
#property (assign, nonatomic, readwrite) int personality;
// others omitted
#end
.m file:
#implementation Employee
- (void)setPersonality:(int)personality {
if (personality < 1)
personality = 1;
else if (personality > 99)
personality = 99;
// _personality is an auto-generated backing instance variable
_personality = personality;
}
// - (int)personality { ... } will be auto-generated
If every one of those attributes has a min/max value then create an static function to restrict the value:
static int restrict(int minValue, int maxValue, int value) {
if (value < minValue)
value = minValue;
else if (value > maxValue)
value = maxValue;
return value;
}
...
- (void)setPersonality:(int)personality {
// _personality is an auto-generated backing instance variable
_personality = restrict(1, 99, personality);
}
Note: that you must not assign _personality (and friends) directly; you must use self.personality = 34; or employee.personality = 34; to invoke the setter.

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

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.

Structure as a class member in Objective C

Is it possible a structure as a class member in objective C? If yes how can I assign values to that structure from another class?
Yes, you can. You either just expose the structure as a property (in which case you have to set/get the whole thing) or you write custom accessors that walk into the fields of the strucutre.
For a concrete example, CGRect is a structure (though it is hidden by a typdef), which means the frame property of UIView get and set a structure.
In other words:
CGRect myFrame = CGRectMake(0,0,320,480); //CGRect is a struct
myView.frame = myFrmae; //Setting a struct
You just use dot notation to assign and access the values. You can also use -> if you have a pointer to a struct.
typedef struct {
int a;
double b;
} SomeType;
// Define some class which uses SomeType
SomeType myVar;
myVar.a = 1;
myVar.b = 1.0;
SomeType* myPtr = &myVar;
NSLog (#"%i", myPtr->a);
// This works...
SomeType mySecondVar = myVar;
// But you have to be careful in cases where you have pointers rather than values.
// So this wouldn't work if either element was a C string or an array.
Yes and there is an easy way to access that struct using Objective-C 2.0 Properties. Consider the following struct from Stephens post.
typedef struct {
int a;
double b;
} SomeType;
In your .h file you would declare the member in your #interface
#interface AClass : NSObject{
SomeType member;
}
#property SomeType member;
#end
Remember that if you choose to go with pointers here you will need to manage your own memory.
And in your #implementation (your .m file) don't forget add a #synthesize
#implementation AClass
#synthesize member;
#end
I hope this helps.