Is it possible to create a #property for an anonymous struct in Objective-C? - objective-c

I have an anonymous struct in my code that I'd like to access via an assign #property (no pointer). However, since this is an anonymous structure. Here's the cocoa code I created (even if it's cocoa code, it's relevant to objective-c in general.)
#interface ProfileViewController : UIViewController {
struct {
BOOL isDeviceOwner:1;
} _statusFlags;
}
Now I'd like to create a property for _statusFlags:
#property (nonatomic, assign)

Yes, you just define it inline where you would define the type.
#property (nonatomic, assign) struct { ... } statusFlags;
Then when you synthesize it you can do #synthesize statusFlags = _statusFlags if you really like the underscored ivars, but this will generate the ivar for you. You do not need to define it explicitly.

You can also do it by making the property or method take a pointer to a struck, you then only have to let the compiler know that the struct exists but not what is in the struct i.e. the size, for example
struct myPrivateStruct;
...
#property(assign,nonatomic) struct myPrivateStruct * myStructProperty;
the struct myPrivateStruct then has to be then defined in your implementation file and property implement the property manually for example
struct myPrivateStruct { int a, b; float c; };
- (void)setMyStructProperty:(struct myPrivateStruct *)aValue
{
memcpy(&myIVar,aValue,sizeof(struct myPrivateStruct));
}
this is vary similar to us #class in interface files, of Objective-C class.

Related

Need help trying to use #property in Objective-C

New to Objective-C (and programming for that matter), so please don't be too harsh if this question is very basic.
Apart from my main.m class, I have a Student.h and Student.m class, which I created. I am trying to avoid using many getters and setters for future projects, and if I'm correct, #property can help me with that. My basic code that works is this:
Student.h:
#import <Foundation/Foundation.h>
#interface Student : NSObject{
NSString *name;
int age;
}
//setters
- (void)setName:(NSString*)fName;
- (void)setAge:(int)newAge;
//getters
- (NSString*)getName;
- (int)getAge;
#end
Student.m:
#import "Student.h"
#implementation Student
- (void)setName:(NSString*)fName {
name = fName;
}
- (void)setAge:(int)newAge {
age = newAge;
}
- (NSString*)getName {
return name;
}
- (int)getAge {
return age;
}
#end
Can I use #property to have something like this, which would avoid using getter and setter methods? Or do I understand it all wrong?
#import <Foundation/Foundation.h>
#interface Student : NSObject{
}
#property int age;
#property NSString *name;
#end
Few things:
In Objective C you don't use get prefix for getters. You should use either plain name or with 'is' prefix for boolean properties. (Objective C conventions reference)
You really won't avoid using getters and setters. #property notation just defines them for you (maybe with some additional behaviors like copying the value instead of assigning it). It's just the matter of . notation. Underneath it's using getter/setter methods. Here you have a bit more on properties (Objetive C properties reference).
You should define your NSString property as (copy). It's much better to have as if you change it somewhere else it will affect this object (and probably you want to avoid that).
Are you coming from Java perhaps?
Yes, Objective-C used to require getters and setters to be written out laboriously by hand. Nowadays if you use #property and don't go out of your way to do anything else then a suitable instance variable and an appropriate getter and setter will be generate for you.
So the following is a complete class with usable properties, accessible either via traditional setName:/name-style setters and getters or via the dot notation (which calls the setters and getters despite looking like a C struct access:
#interface Student : NSObject
#property int age;
#property NSString *name;
#end
/* ... */
#implementation Student
#end
Also as a general encapsulation / data-hiding comment, notice that Objective-C has long ago been modified so that instance variables can be declared in the [unpublished] #implementation rather than the [published] #interface. On a technical level it was all to do with the ABI and the fragile base class problem, neither of which haunts the modern runtime.

Objective C: Should I assign the variable AND create a property or is just one of them enough?

I have got a header file (.h) and I want to declare name but all these ways work the same I think because I haven't seen any difference with functionality. Could you tell me what the difference is between:
This with both declarations:
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Without variable:
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Or Without property:
#interface someClass : UIViewController
{
NSString *name;
}
#end
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Doing this you will explicitly declare both a property and an ivar.
A property is just a set of methods:
- (void)setName:(NSString*)name;
- (NSString*)name;
An ivar is the memory store holding the value that the property methods manage. This allows you to do:
self.name = ... // access through setter method
name = ... // direct access
The advantage of using properties is that they deal with memory management for you. E.g., in your case, the property is of type copy: this means that with the first syntax (self.name = ...) a copy of the object will be done. If not using properties, you would explicitly need to do: name = [originalString copy]; to obtain the same effect.
Other options you can specify for properties (but not ivars) are: strong and weak ownerships.
Furthermore, a property also represents a public interface to access the variable from outside your class.
Using direct access you are on your own as to memory management (if you are not using ARC).
If you are using ARC and don't define properties, you will not be able to control how the memory is managed by specifying the ownership: strong, weak, retain).
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Here you only declare the properties; the ivar is "inferred" by the #synthesize directive in your implementation file. This is only possible in Objective C 2.0 and later (previously, the ivar declaration as above was mandatory).
The same considerations as above applies, with a minor nuance: with older versions of LLVM (ObjC compiler) you will not be able to reference directly the auto-synthesized ivar; with current version of LLVM, if you omit the #synthesize directive, then an automatic ivar named after your property would also be declared (in your case it would be _name).
This last paragraph may seem a bit "advanced", or contrived, but you can safely ignore it.
#interface someClass : UIViewController
{
NSString *name;
}
#end
In this case you are only declaring the ivar. No accessor methods. You will need to handle memory management on your own (if not using ARC), futhermore you will not be able to access the variable from outside the class. For that you need accessors.
Hope this helps.
Case 1:
The is the old method, here the #property and variable are not related until you #synthesize name = name;
Access methods :
variable : name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
With the latest xcode just the property is enough.
Case 2:
the new xcode style. Here the synthesize and variable creation is taken care by the compiler. (so less 2 lines of code and this also helps with memory management)
Access methods :
variable : _name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
Case 3:
Here the name is just a variable and it dose not have a setter or a getter.
with out property (or) setter & getter this is as good as a local variable and it cannot be accessed from other objects.

How to do pointer work with accessor methods in Objective-C

Basic problem statement:
I have a very good reason for doing some pointer fanciness in an app where I need to pass a decimal by reference.
So I have a class which stores many a decimal, so let's say is has a property as such:
#property (nonatomic) double myDecimalValue;
I want to pass it by reference to some other class.
[someOtherObject sendMyDecimalByReference:&myDecimalValue];
But, a problem emerges! The way that actually has to be written (because it's a property) is
[someOtherObject sendMyDecimalByReference:&decimalOrigin.myDecimalValue];
This fails to compile in objective-c
I get around it by writing the following
- (double *) myDecimalValueRef;
[someOtherObject sendMyDecimalByReference:[decimalOrigin myDecimalValue]];
Except I have dozens of these decimals and I don't want to write that stupid wrapper function for every value.
Is there a shorthand way to do this in Objective-C using just the Getter functions?
Let's just assume I have a great reason for not using NSNumber.
Thanks!
Can you use and access an instance variable directly instead of a property? Then it would work the same way as a C struct member...
#interface SomeClass : NSObject
{
#public
double myDecimalValue;
}
// Keep the getter or not, assuming you synthesize it in a way that uses the
// myDecimalValue ivar
#property (nonatomic) double myDecimalValue;
#end
Then you could access it this way:
[someOtherObject sendMyDecimalByReference:&decimalOrigin->myDecimalValue];
Of course, the robustness is limited, someOtherObject has to remain a valid object when you actually dereference the value, and if you have subclasses/superclasses, you will have to take this design into account...
While far from ideal, you could make the ivars public. I hate even saying that, but it is a possible solution.
Another option is to create a pair of properties for each decimal. Create regular property and also a reference property:
#interface Foo : NSObject
double _myDecimal;
#property (nonatomic, assign) double myDecimal;
#property (nonatomic, assign) double *myDecimalRef;
#end
#implementation Foo
#synthesize myDecimal = _myDecimal;
- (double *)myDecimalRef {
return &_myDecimal;
}
- (void)setMyDecimalRef(double *)val {
_myDecimal = *val;
}
#end
Now you can things like:
[someOtherObject sendMyDecimalByReference:decimalOrigin.myDecimalRef];
Or something like this:
*decimalOrigin.myDecimalRef = 3.14;
Have you looked at the NSValue class? It allows you to pass pointers around as objects.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/Reference/Reference.html

Is it possible to decoupling Setters/Getters from data in Objective-C Properties?

I understand that Properties in Objective-C allows us to compactly define:
setter
getter
data
I would like to use Properties, but it would be nice if I could decouple the data from the getter/setter.
In other words, I like the getter/setter interface of Properties, but I would like to define my own internal representation of data.
For instance, if I were to define MyOwnTime class, I want getters/setters for Properties like hour, date, and minute (as a consumer, I want to be able to set them and get them). However, to save memory in the representation, rather than store date, month, year, hour, minute, second, etc..., I prefer to store secondsSinceEpoch as an unsigned long.
In my situation should I/can I use Properties? How would I do this? Or should I manually roll my own setters and getters?
You can certainly do this. Indeed, it's pretty common. Since the mapping to data is not direct, you cannot synthesise the methods, you have to write the getters and setters manually. But the property will work like any other.
As a simple dummy example:
#interface BytePair
{
UInt16 data;
}
#property UInt8 loByte;
#property UInt8 hiByte;
#end
#implementation BytePair
- (UInt8) loByte
{
return (UInt8) data & 0xff;
}
- (void) setLoByte:(UInt8)lo
{
data = (data & 0xff00) | lo;
}
- (UInt8) hiByte
{
return (UInt8) (data & 0xff00) >> 8;
}
- (void) setHiByte:(UInt8)lo
{
data = (data & 0xff) | (lo << 8);
}
#end
Or whatever. You get the idea.
Of course you can :
#interface MyObject : NSObject
{
int toto;
}
#property(nonatomic, setter=mySetterMethod:, getter=myGetterMethod) int toto;
-(void) mySetterMethod:(int) t;
-(void) myGetterMethod;
Or you can also override the setter and getter default methods, in my case (in the .m file) :
-(int) toto
{
return toto;
}
-(void) setToto:(int) t
{
toto = t;
}
Declare a
#property (nonatomic, assign) sometype somename
in the interface as normal. Then instead of writing
#sythesize somename = _somename
in the implementation, you write
-(sometype)somename {
return whatever;
}
-(void)setSomename(sometype)newValue {
whatever;
}
You don't need to use the #property notation at all. Just do this:
#interface MyObject
- (id)foo;
- (void)setFoo:(id)newFoo;
#end
Then, elsewhere you can do myObject.foo = #"bar";.
Calling myObject.foo is exactly the same as [myObject foo] or [myObject setFoo:foo]. It has nothing to do with properties, it just happens to be most commonly used for them.
And the #property syntax is just a formal way of declaring properties allowing you to do more advanced stuff (like nonatomic). If you're defining your own methods, instead of letting the compiler define them for you, then there isn't much point to using #property.
If you have ARC disabled, then you might want to look into how to properly memory manage a property, as there are some non-obvious edge cases where you can get into trouble defining your own data storage code.
You can, it's common, and pretty easy to do.
As with a standard property, you don't even need to declare an instance variable for that and can still #synthesize your property (contrary to what other answers are saying), you simply have to override the setter of the property:
#interface MyObject : NSObject
#property(nonatomic, copy) NSString* myprop; // like any other property
#property(nonatomic, readonly) BOOL hasProp;
#end
#implementation MyObject
#synthesize myprop = _myprop; // optional with latest LLVM compiler, will generate the _myprop instance variable at compile time
// Override default setter for myprop
-(void)setMyprop:(NSString*)newvalue
{
if (_myprop != newvalue)
{
[_myprop release]; // release only necessary if not using ARC
_myprop = [newvalue retain]; // retain only necessary if not using ARC
// And/Or whatever you want your custom setter to do
}
}
// You can override default "-(NSString*)myprop" getter too if you want
// You you can keep the default getter implementation and only override the setter.
// Or vice-versa. It's really up to you
// Another example: we created a #property(readonly) hasProp and implement its getter by ourselves, without any dedicated instance variable
-(BOOL)hasProp
{
return (self.myprop != nil);
}
#end

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.