objective-c union "->" vs "." - objective-c

let me start by saying i am pretty new to the whole struct and union thing. i have done my homework before posting this and honestly trying to get legitimate clarification. if this is the wrong way to this please let me know. first off, i am attempted to create a union because i am combining different data types. my only real problem / question is the dot operator vs the ->. i can get what i want working using the
->
but not the
.
im just curious as to why? iv read a bunch of posts on stack that show examples or "answers" using the ".", but no luck in the real world. i have played with "typedef" like...
typedef union _myUnion
{
int intValue;
bool boolValue;
}myUnion;
but that doesn't seam to make a difference. if anyone explain what im doing wrong it would be greatly appreciated. here is a quick sample of what i am trying to do. for the sake of simplicity, i will just post some struct/union syntax and wont add any of the sub-classing code since that's not an issue.
example.h
#import "<Foundation/Foundation.h"
union myUnion
{
int intValue;
bool boolValue;
};
#interface MyClass : NSObject
{
union myUnion *someProperty;
}
#property (nonatomic, assign) union myUnion *someProperty;
-(void)doSomething;
#end
example.m
#import "MyClass.h"
#implementation MyClass
#synthesize someProperty = _someProperty;
- (id)init
{
//Some init method...
}
- (void)doSomething
{
NSLog(#"I Did Something...");
}
#end
so now in my other class this works...
MyClass *newObject = [MyClass alloc] init];
newObject.someProperty->intValue = 6;
but this doesn't...
MyClass *newObject = [MyClass alloc] init];
newObject.someProperty.intValue = 6;
at this point in time i'm more interested in learning why that latter doesn't work? what's interesting is if i take off the pointer in the .h file for the property.
#interface MyClass : NSObject
{
union myUnion someProperty;
}
#property (nonatomic, assign) union myUnion someProperty;
the "." works instead of the "->", but now its not assignable.
as a side note, if i change the bool to an int and make it a struct the same thing happens. unfortunately i became proficient at objective-c first and am slowly picking up strict c as i go. so my understanding of c is a tad weak, but that's the beauty of obc, i get to learn two languages for the price of one! if you don't count open-gl.
i would ask, if someone could post a working example of code and i can then figure out what i did wrong, or explain thoroughly what it is i am doing wrong and some of the fundamental concepts i missed. from there i can figure out how to write my own working code. i don't need both, and don't expect a hand out but would like to learn so i can solve my own problems and not just patch buggy code without understanding how or why it works.

The a->b operator is shorthand for (*a).b - it's like using the . but doing a dereference first. It's appropriate when a is a pointer.
Since in your original example someProperty is a pointer to a union, you'll need to dereference that pointer first. This means you'll need to either use:
(*newObject.someProperty).intValue // confusing!
Or
newObject.someProperty->intValue // much better
to access it.
Of course, once you've changed someProperty to be a union instead of a pointer to a union, you can use the . instead. So:
a->b: Accesses a struct/union member on a pointer
a.b: Accesses a struct/union member on a raw struct/union

In this case, it's quite probable that you want the union as a value -- not a pointer to an external memory location:
#interface MyClass : NSObject
{
union myUnion someProperty; // << no '*'
}
#end
then you use the period for member access:
someProperty.intValue = 6;
and if it were a pointer:
someProperty->intValue = 6;
However, there's another issue. You have two (primary) options to use the union as a property. Value or pointer. This is commonly handled by value, especially when all fields refer to memory local to the structure/union, and when the field id not large. In this case, you would often return and set by value. This means that your program would be written as follows:
#interface MyClass : NSObject
{
union myUnion someProperty;
}
#property (nonatomic, assign) union myUnion someProperty; // << by value
#end
then the client may access and set it by value, like so:
union myUnion p = obj.someProperty;
++p.intValue;
obj.someProperty = p;
and that's how it's often accomplished with small structures which don't refer to shared resources.
Of course, you will not need a copy when your instance has direct access to it, should you choose to access the field directly:
- (void)doSomething
{
++someProperty.intValue;
}
if this becomes complex, it's likely a good idea to abstract the data behind methods, and leave accessing and mutation to the instance of MyClass which holds the union.

Related

objective-c "generic" type for #property for use with multiple subclasses

i'm not sure of the most eloquent way to state this but i will give it my best. i have created a custom class that is a generic object with some properties. i have created a couple subclasses to extend that and make them more specific than the superclass. so for the sake of example i will throw out some generic example code that may or may not be proper syntax only to illustrate what i would like to accomplish.
#interface Vehicle : NSObject
#property (nonatomic) int wheels;
- (id)initWithNumberOfWheels:(int)wheels;
#end
from there i create some subclasses for same "car" & "truck" which give more detail to the class.
#interface Car : Vehicle
#property (nonatomic) BOOL convertible;
#property etc...
#end
and...
#interface Truck : Vehicle
#property (nonatomic) BOOL is4x4;
#property (nonatomic) int numberOfDoors;
#end
so here is where it gets interesting. i want to create another class that allocates those objects but i want the "type" of vehicle to be determined in the init method but use the same #property variable. so for example (and again, this is all garbage code just to give a visual representation)
Road.h
#import "Car.h"
#import "Truck.h"
#interface Road : NSObject
#property (strong, nonatomic) NotSureWhatToUseHereToMakeThisWork *myRide;
// doesn't work: #property (strong, nonatomic) id myRide;
// doesn't work: #property (strong, nonatomic) Vehicle *myRide;
- (id)initWithCars;
- (id)initWithTrucks;
#end
Road.m
#implementation Road
- (id)initWithCars
{
//standard init code...
myRide = [[Car alloc] initWithNumberOfWheels:4];
myRide.convertable = NO;
}
- (id)initWithTrucks
{
//standard init code...
myRide = [[Truck alloc] initWithNumberOfWheels:6];
//yes, some trucks have more than 4 wheels
myRide.is4x4 = YES;
}
#end
the bottom line is if i use the superclass in the #property it doesn't get the subclass properties obviously. basically i want to keep all this as generic and reusable as possible. it doesn't make since to make a special "road" class just for cars & one for trucks. a road is a road after all. is there anyway to do what i am after? is there a better way to do something like this? the primary purpose is to have objects that inherit specific properties for specific situations only. the reason i don't want to make extra #properties is i don't want those visible if they aren't applicable to the situation.
edit:
i added a couple extra snippets to show what i tried before even posting this question that didn't work.
answer: the correct "answer" if anyone is curious is located in CRD's response in the "Addendum". the reason this works is the type "id" can only call methods and does not inherit properties. so rather the workaround (i say it that way, as i was researching this, came to the conclusion this is not good programming and should probably be avoid if possible) would be to use the accessor methods to get/set the property.
id mySomethingObject = [[SomeClass alloc] init...];
[mySomethingObject setPropertyMethod]...; //sets value
[mySomethingObject propertyMethod]...; //gets value
rather than trying to use...
mySomethingObject.property = ; //set
mySomethingObject.property; //get
as stated in the correct answer, if your class you allocated "id" to does not respond to that method your program will crash.
You appear to be confusing a number of issues.
First there is the type of an instance vs. the type of variables which hold references to instances. When an object is created is it of some specific type and that types does not change[*]. Variables also have a type, and that does not change either. Subtyping/inheritance allows you to store a reference to an object of some type, T, in a variable of some other type, S, provided S is a supertype of T.
Second there is static vs. dynamic typing. While Objective-C uses dynamic typing, where the actual type of objects used in some operation is determined at run time, the compiler itself uses static typing, where types are determined during compilation, to aid in writing correct programs. Sometimes the compilers static checking will just produce warnings, but in other cases the compiler will refuse to compile something. In particular property references are compiled based on static typing.
In your example this means you cannot directly reference a property of Car on an object referenced by a variable of type Vehicle *, even if you know the referenced object is a Car - as at compile time all that is known is that is it a Vehicle.
The solution is to first test the actual type of the referenced object and then introduce a local variable of the more precise type, or use a lot of casts. For example:
// (a) create an object of type Car (for a Reliant Robin ;-))
// (b) create a variable of type Car and store in it a reference to the created Car
Car *myCar = [[Car alloc] initWithNumberOfWheels:3];
// Create a variable of type Vehicle and store in it the reference stored in myCar
// The created instance is *still* a Car
Vehicle *myRide = myCar;
// See if myRide is a Car and then do something
if ([myRide isKindOfClass:Car.class])
{
// create a variable of type Car to avoid having to continually cast myRide
Car *myCarRide = (Car *)myRide; // due to if above we know this cast is valid
if (myCarRide.isConvertible) ...
To do this without the intermediate variable you use a cast:
...
// See if myRide is a Car and then do something
if ([myRide isKindOfClass:Car.class])
{
if (((Car *)myCarRide).isConvertible) ...
Which shows why the intermediate variable approach is better!
As a final example, you write your initWithTrucks method like this:
- (id)initWithTrucks
{
//standard init code...
Truck *myTruck = [[Truck alloc] initWithNumberOfWheels:6];
//yes, some trucks have more than 4 wheels
myTruck.is4x4 = YES;
// Store the reference to the created Truck in myRide
myRide = myTruck;
}
HTH
Addendum
From your comments it seems you may be looking for dynamic typing and do not wish to the compiler to perform any static typing. This is (partially) supported, but not using the dot notation for properties - you must use the getter and setter methods directly.
First, in Road you declare myRide to be type id:
#interface Road : NSObject
#property id myRide;
The id type means two things (a) any object reference and (b) do not statically check a method exists on the object. However the compiler must know that a called method exists on some object, and it will still perform static type checks on the arguments to the method - so its not complete dynamic typing (however you could pass id typed expressions or declare your methods to take arguments of type id of course...).
Second you make all references to properties use the getter or setter methods directly and do not use the dot notation (for non-property methods you just call them as usual). E.g.:
- (id)initWithTrucks
{
//standard init code...
myRide = [[Truck alloc] initWithNumberOfWheels:6];
//yes, some trucks have more than 4 wheels
[myRide setIs4x4:YES];
}
If you make a call such as [myRide setIs4x4:YES] and myRide is referencing a Car object then you will get a runtime error.
The general recommendation is to stick as much as possible with the compiler's static typechecking.
[*] We will ignore any runtime magic, there be dragons. In normal code objects never change type.
You have to use the type "Vehicle" and then cast your object with "Truck" or "Car" to get the specific properties
the most generic architecture would be to create a VehicleProtocol, that any class could implement. you still could have a Vehicle class that implements the protocol and subclass from it (similar to NSObject implementing the NSObject protocol), or let independent classes implement it. the road would have a property #property (strong) id<VehicleProtocol> myRide.
A complete example of the later architecture: no vehicle super class, but all a VehicleProtocol
#import <Foundation/Foundation.h>
#protocol VehicleProtocol <NSObject>
#property (nonatomic) NSUInteger wheels;
#end
#interface Car : NSObject <VehicleProtocol>
#property (nonatomic) BOOL convertible;
#property (nonatomic) NSUInteger wheels;
-(id)initWithNumberOfWheels:(NSUInteger) numberOfWheels;
#end
#implementation Car
-(id)initWithNumberOfWheels:(NSUInteger) numberOfWheels
{
if (self = [super init]) {
_wheels = numberOfWheels;
}
return self;
}
#end
#interface Truck : NSObject <VehicleProtocol>
#property (nonatomic) BOOL is4x4;
#property (nonatomic) int numberOfDoors;
#property (nonatomic) NSUInteger wheels;
-(id)initWithNumberOfWheels:(NSUInteger) numberOfWheels;
#end
#implementation Truck
-(id)initWithNumberOfWheels:(NSUInteger) numberOfWheels
{
if (self = [super init]) {
_wheels = numberOfWheels;
}
return self;
}
#end
#interface Road : NSObject
#property (strong) id<VehicleProtocol> myRide;
#end
#implementation Road
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSArray *vehicles = #[[[Car alloc] initWithNumberOfWheels:4], [[Car alloc] initWithNumberOfWheels:3], [[Truck alloc] initWithNumberOfWheels:10]] ;
for (id v in vehicles) {
if ([v isKindOfClass:[Truck class]]) {
[v setIs4x4:YES];
}
}
Road *road = [[Road alloc] init];
road.myRide = vehicles[0];
NSLog(#"%#", road.myRide);
road.myRide = vehicles[2];
NSLog(#"%#", road.myRide);
NSObject *obj = [[NSObject alloc] init];
road.myRide = obj; // warning in this line
NSLog(#"%#", road.myRide);
}
return 0;
}
Sure it might have more lines of codes than with "classical subclassing", but there are less dependencies. Instead the classes agree on a contract to fulfill. Here the contract only requires the objects to have any number of wheels.
Note that I create a Road and assign first a car and than a truck (I also show how to identify cars and trucks via -isKindOfClass:), both works without any warning or error, as Car and Truck completely fulfill the contract. Than I assign a plain NSObject. Here the compiler warns, as he recognizes that NSObject does not implement the protocol. Though it is not an compiler error, as the compiler does not know, if you will use any protocol specific method on that object.
In case of a plain NSObject assigned to myRide, this line
NSLog(#"%# %ld", road.myRide, (unsigned long)road.myRide.wheels);
will lead to a runtime crash (as an NSObject instance does not respond to wheel) — but at compile time it will not even trigger a warning.
Storing a Car in a variable of type Vehicle * does not remove the object's Car properties — the Car will still be able to access all of its state normally — it just means that you can't access the properties through that variable.
But that's the basic idea here, isn't it? You want this class to be able to handle all Vehicles, and that's what it's doing — it's only showing you the functionality available to all Vehicles. So you can have the interface necessary for interaction with a generic Vehicle in the Vehicle class, and implement the methods in your subclasses to do the class-appropriate behavior when called, and everything will work.
If the issue is specifically creating new instances of a specific class that you want to treat generically from that point on, you can use a statically typed local variable and assign to the generically typed variable once it's set up.
For example, let's say we have a game where there are human players and AI players, and the human player can give himself an advantage by making AI players take more damage. We could do this:
#interface Combatant : NSObject
#property(nonatomic, strong) NSString *name;
#property(nonatomic) int hitPoints;
- (void)takeDamage:(int)damageAmount;
#end
#implementation Combatant
- (void)takeDamage:(int)damageAmount {
self.hitPoints -= damageAmount;
}
#end
#interface HumanCombatant : Combatant
#property(nonatomic, strong) UserID *userID;
- (id)initWithUserID:(UserID *)theID;
#end
#implementation HumanCombatant
- (id)initWithUserID:(UserID *)theID {
if ((self = [super init])) {
_userID = [theID retain];
}
}
- (void)takeDamage:(int)damageAmount {
[super takeDamage: damageAmount];
NSLog(#"Human took %d damage, has %d health remaining", damageAmount, self.hitPoints);
}
#end
#interface AICombatant : Combatant
#property(nonatomic) double damageMultiplier;
#end
#implementation AICombatant
- (void)takeDamage:(int)damageAmount {
int modifiedDamage = damageAmount * self.damageMultiplier;
[super takeDamage: modifiedDamage];
NSLog("AI took %d damage, has %d health remaining", modifiedDamage, self.hitPoints);
}
#end
Then, in most of our game code, we can use a variable typed as a Combatant *, and when you send it takeDamage:, it will do the right thing for the type of combatant it is. Our external code that calls the object a Combatant * will not be able to directly access an AICombatant's damageMultiplier property, because the other code doesn't know whether the Combatant is an AICombatant, but the object will still have that property and will behave correctly for its class.
Make it a Vehicle* and make each class implement type to return a constant indicating that class's type.
#property (nonatomic, strong) Vehicle* yourRide;
...
if (yourRide.type == VehicleConstant_Truck) {
Truck* yourTruck = (Truck*) yourRide;
NSLog(#"This truck %s a 4x4", yourTruck.is4x4 ? "is" : "isn't");
}
To make #vikingosegundo happy, an alternative approach is to do:
if ([yourRide isKindOfClass:[Truck class]]) {
instead of the if statement above.

What is the difference between the areas where you can declare instance variables in Objective-C? [duplicate]

Ever since starting to work on iOS apps and objective C I've been really puzzled by the different locations where one could be declaring and defining variables. On one hand we have the traditional C approach, on the other we have the new ObjectiveC directives that add OO on top of that. Could you folks helps me understand the best practice and situations where I'd want to use these locations for my variables and perhaps correct my present understanding?
Here's a sample class (.h and .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
#end
and
#import "SampleClass.h"
// 4) what goes here?
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
#implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
#end
My understanding of 1 and 4 is that those are C-style file-based declarations and definitions that have no understanding whatsoever of the concept of class, and thus have to be used exactly how they would be used in C. I've seen them used for implementing static variable-based singletons before. Are there other convenient uses I'm missing?
My take from working with iOS is that ivars have been alost completely phased out outside of the #synthesize directive and thus can be mostly ignored. Is that the case?
Regarding 5: why would I ever want to declare methods in private interfaces? My private class methods seem to compile just fine without a declaration in the interface. Is it mostly for readability?
Thanks a bunch, folks!
I can understand your confusion. Especially since recent updates to Xcode and the new LLVM compiler changed the way ivars and properties can be declared.
Before "modern" Objective-C (in "old" Obj-C 2.0) you didn't have a lot of choices. Instance variables used to be declared in the header between the curly brackets { }:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#end
You were able to access these variables only in your implementation, but not from other classes. To do that, you had to declare accessor methods, that look something like this:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
#end
// MyClass.m
#implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
#end
This way you were able to get and set this instance variable from other classes too, using the usual square bracket syntax to send messages (call methods):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
Because manually declaring and implementing every accessor method was quite annoying, #property and #synthesize were introduced to automatically generate the accessor methods:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#synthesize myVar;
#end
The result is much clearer and shorter code. The accessor methods will be implemented for you and you can still use the bracket syntax as before. But in addition, you can also use the dot syntax to access properties:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
Since Xcode 4.4 you don't have to declare an instance variable yourself anymore and you can skip #synthesize too. If you don't declare an ivar, the compiler will add it for you and it will also generate the accessor methods without you having to use #synthesize.
The default name for the automatically generated ivar is the name or your property starting with an underscore. You can change the generated ivar's name by using #synthesize myVar = iVarName;
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#end
This will work exactly as the code above. For compatibility reasons you can still declare ivars in the header. But because the only reason why you would want to do that (and not declare a property) is to create a private variable, you can now do that in the implementation file as well and this is the preferred way.
An #interface block in the implementation file is actually an Extension and can be used to forward declare methods (not needed anymore) and to (re)declare properties. You could for instance declare a readonly property in your header.
#property (nonatomic, readonly) myReadOnlyVar;
and redeclare it in your implementation file as readwrite to be able to set it using the property syntax and not only via direct access to the ivar.
As for declaring variables completely outside of any #interface or #implementation block, yes those are plain C variables and work exactly the same.
First, read #DrummerB's answer. It a good overview of the whys and what you should generally do. With that in mind, to your specific questions:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
No actual variable definitions go here (it's technically legal to do so if you know exactly what you're doing, but never do this). You may define several other kinds of things:
typdefs
enums
externs
Externs look like variable declarations, but they're just a promise to actually declare it somewhere else. In ObjC, they should only be used to declare constants, and generally only string constants. For instance:
extern NSString * const MYSomethingHappenedNotification;
You would then in your .m file declare the actual constant:
NSString * const MYSomethingHappenedNotification = #"MYSomethingHappenedNotification";
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
As noted by DrummerB, this is legacy. Don't put anything here.
// 3) class-specific method / property declarations
#end
Yep.
#import "SampleClass.h"
// 4) what goes here?
External constants, as described above. Also file static variables can go here. These are the equivalent of class variables in other languages.
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
Yep
#implementation SampleClass
{
// 6) define ivars
}
But very rarely. Almost always you should allow clang (Xcode) to create the variables for you. The exceptions are usually around non-ObjC ivars (like Core Foundation objects, and especially C++ objects if this is an ObjC++ class), or ivars that have weird storage semantics (like ivars that don't match with a property for some reason).
// 7) define methods and synthesize properties from both public and private
// interfaces
Generally you shouldn't #synthesize anymore. Clang (Xcode) will do it for you, and you should let it.
Over the last few years, things have gotten dramatically simpler. The side-effect is that there are now three different eras (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). So when you see the older code, it can be a little confusing. Thus confusion arising from simplicity :D
I'm also pretty new, so hopefully I don't screw anything up.
1 & 4: C-style global variables: they have file wide scope. The difference between the two is that, since they're file wide, the first will be available to anyone importing the header while the second is not.
2: instance variables. Most instance variables are synthesized and retrieved/set through accessors using properties because it makes memory management nice and simple, as well as gives you easy-to-understand dot notation.
6: Implementation ivars are somewhat new. It's a good place to put private ivars, since you want to only expose what's needed in the public header, but subclasses don't inherit them AFAIK.
3 & 7: Public method and property declarations, then implementations.
5: Private interface. I always use private interfaces whenever I can to keep things clean and create a kind of black box effect. If they don't need to know about it, put it there. I also do it for readability, don't know if there are any other reasons.
This is an example of all kinds of variables declared in Objective-C. The variable name indicate its access.
File: Animal.h
#interface Animal : NSObject
{
NSObject *iProtected;
#package
NSObject *iPackage;
#private
NSObject *iPrivate;
#protected
NSObject *iProtected2; // default access. Only visible to subclasses.
#public
NSObject *iPublic;
}
#property (nonatomic,strong) NSObject *iPublic2;
#end
File: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
#interface Animal(){
#public
NSString *iNotVisible;
}
#property (nonatomic,strong) NSObject *iNotVisible2;
#end
#implementation Animal {
#public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
iPrivate = #"iPrivate";
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
_iPublic2 = #"iPublic2";
iNotVisible = #"iNotVisible";
_iNotVisible2 = #"iNotVisible2";
iNotVisible3 = #"iNotVisible3";
}
return self;
}
#end
Note that the iNotVisible variables are not visible from any other class. This is a visibility issue, so declaring them with #property or #public doesn't change it.
Inside a constructor it's good practice to access variables declared with #property using underscore instead self to avoid side effects.
Let's try to access the variables.
File: Cow.h
#import "Animal.h"
#interface Cow : Animal
#end
File: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
#implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
//iPrivate = #"iPrivate"; // compiler error: variable is private
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
self.iPublic2 = #"iPublic2"; // using self because the backing ivar is private
//iNotVisible = #"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = #"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = #"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
#end
We can still access the not visible variables using the runtime.
File: Cow.m (part 2)
#implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:#"iNotVisible" value:#"iMadeVisible"];
[self setIvar:#"_iNotVisible2" value:#"iMadeVisible2"];
[self setIvar:#"iNotVisible3" value:#"iMadeVisible3"];
NSLog(#"\n%# \n%# \n%#",
[self getIvar:#"iNotVisible"],
[self getIvar:#"_iNotVisible2"],
[self getIvar:#"iNotVisible3"]);
}
#end
Let's try to access the not visible variables.
File: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:#selector(blindAccess)];
}
}
This prints
iMadeVisible
iMadeVisible2
iMadeVisible3
Note that I was able to access the backing ivar _iNotVisible2 which is private to the subclass. In Objective-C all variables can be read or set, even those that are marked #private, no exceptions.
I didn't include associated objects or C variables as they are different birds. As for C variables, any variable defined outside #interface X{} or #implementation X{} is a C variable with file scope and static storage.
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.

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

Do I need to declare a property in the instance variables section, too? What do I gain?

I read some tutorials here about properties ,but i still have some doubts to clarify, is there a difference between
#interface MyClass : NSObject {
}
#property(nonatomic,retain) NSString *temp;
#end
AND
#interface MyClass : NSObject {
NSString *temp;
}
#property(nonatomic,retain) NSString *temp;
#end
The difference is that in the first version, the compiler will automatically create an instance variable (IIRC, it will be named _temp but I don't know for sure). This is only supported on iOS and Mac 64 bit.
In the second example, you provide the variable.
There's actually a way to tell the compiler which variable to use for the property, which I use a lot:
#interface MyClass : NSObject {
NSString *temp_;
}
#property(nonatomic,retain) NSString *temp;
#end
#implementation MyClass
#synthesize temp = temp_;
#end
This way the variable and the property have different names and you can't confuse them (e.g. by forgetting to prefix self.).
Minor side-note: it's often desirable to use copy instead of retain for NSString *, since you might assign an NSMutableString * to the property. Now if you would change that mutable string unexpected things might happen.
Does the first one even work? If there is no instance variable its a bit hard to have a property to access it.
#properties are meant for you, so you can be lazy, they write the following 2 methods for you ( if not set to readonly ):
- (void)setYourVariable:(id)new;
- (id)yourVariable;
it also allows you to use "someClass.itsVariable;" instead of "[someClass itsVariable];"
Another thing, when you create your header files make sure that the biggest variables ( like pointers ) are on the top and the smallest on the bottom, this saves ram.
thus:
NSObject *someObject;
NSObject *someOtherObject;
int anInt;
short aShort;
BOOL fakeBool;
instead of:
BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;
This has to do with the compiler, you can check this by using sizeof()
In the modern runtime (Objective-C 2.0) it is the same because the compiler will generate the variable for you. See Question about #synthesize
Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:
There are differences in the behavior of accessor synthesis that
depend on the runtime:
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance
variable of the same name as the property exists, and if its type is
compatible with the property’s type, it is used—otherwise, you get a
compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is
used.
The practical difference that I've found is that the debugger doesn't appear to show you the value of properties, just instance variables.
Therefore, your first example, which (assuming you use the #synthesize directive to create your getter/setter) automatically creates the ivar, will not have a value that you can easily retrieve during debug. You'll end up having to send a lot of NSLog messages, rather than just looking at the values while stepping through your code.
As an aside, which seems to relate to this topic, I typically prepend my ivars with "iv" and change my color settings in XCode preferences so that I'm never unsure whether I'm accessing a property or an ivar.
Example
#interface MyClass : NSObject {
NSString *ivName;
NSString *ivTitle;
}
#property (nonatomic, copy) NSString *Name;
#property (nonatomic, copy) NSString *Title;
#end
Now, this then requires a small trick (to tie the two together) when synthesizing the properties, which I show below:
#implementation MyClass
#synthesize Name = ivName;
#synthesize Title = ivTitle;
This way, it's always very easy for me to know exactly what's going on at a glance. Yes, context can also tell you whether you're accessing an ivar/property, but why not make it easier?

Objective C: Request for member XXX in something not a structure or union

I hit the error (stated in the subject) when trying to run the following code (snippet). The error is pointing to my 3rd and 4th lines of the code below.
id shape[3];
shape[0] = [[Circle alloc]init];
shape[0].fillColor = kRed;
shape[0].shapeBounds = bound0;
Prior to this set of code I had defined the enum and struct for ShapeColor and ShapeBoundary as below
typedef enum
{
kRed,
kBlue,
kGreen,
kPurple
}ShapeColor;
typedef struct
{
int x;
int y;
int width;
int height;
}ShapeBoundary;
Also, I have defined my interface and implementation of a "Circle" class
#interface Circle : NSObject
{
ShapeColor fillColor;
ShapeBoundary shapeBounds;
}
#property ShapeColor fillColor;
#property ShapeBoundary shapeBounds;
#end
#implementation Circle
#synthesize fillColor;
#synthesize shapeBounds;
#end
I used #property and #synthesize to define my getter and setter methods for "fillColor" and 'Shapebounds". Is there something wrong with the way I am using property and synthesize to cause the error in the subject? Or is there anything I am missing out. Any advise on this is greatly appreciated.
Thanks and Regards
Zhen Hoe
In order to use dot notation for properties, the class of the variable must be statically typed or cast. That is, your code must declare the class of the object instead of using id. If you used Circle *shape[3];, or ((Circle*)shape[0]).fillColor then your errors would go away. When you want your variable to be dynamically typed (using id), you need use the equivalent methods to get the properties:
id shape[3];
shape[0] = [[Circle alloc] init];
[shape[0] setFillColor:kRed];
[shape[0] setShapeBounds:bound0];
Also make sure you include the header for the Circle class in the file where you are doing this.