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

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.

Related

How to overwrite parent properties (redeclaration of parent property as a static variable)?

It is possible to have a type in the parent class that the subclass overwrites?
The idea here would be to have a shape class, with subclasses of rectangles, square, circles, etc. Wondering if it's possible to overwrite the definition of 'shapeType' int property in the parent class. Something like this?
e.g. in globals.h
#define kShapeType_Rectangle = 1
#define kShapeType_Square = 2
#define kShapeType_Triskaidecagon = 13 // try pronouncing this!
in shape.h
#interface shape : NSObject
#property int shapeType;
#property int shapeID;
#property UIColor shapeColor;
#end
....
in rectangle.h
#import globals.h
#interface rectangle : shape
#property static (nonatomic, readonly) int shapeType = kShapeType_Rectangle; // how do I get this working?
#end
So two questions:
1) Is such a thing possible - i.e. redeclaration of parent property as a static variable
2) Yes or No to (1), is this the best coding style for this sort of thing? I'm not experienced in Obj-C patterns, but if one exists, could someone suggest a source for me to look at please?
Thanks a lot!
There is no concept of an Objective-C property being a static variable. An Objective-C property is just a syntax shorthand for declaring two methods, a getter and a setter (or just a getter in the case of readonly properties). You can override either or both of those methods in a subclass and have them get and set the value from/to a static variable/value in the subclass if you want. There's nothing preventing that.
In this case you would do this:
- (int)shapeType
{
return kShapeType_Rectangle;
}
Not to get too philosophical, but having such a property would seem to be creating a redundancy with the type system. Put differently, why have a property that you have to override in every subclass? In this case why have shapeType return kShapeType_Rectangle when you know the instance is a rectangle by virtue of it being of the rectangle class?

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.

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

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.

In Objective-C, why does the variable's type has to be repeated for #property?

For Objective-C, in the following header file:
#interface Peg : NSObject {
char color;
}
#property char color;
I wonder if the member variable is already said to be a char type, then why does the #property has to repeat it? (or else it won't compile). Couldn't the compiler tell that it is char? It couldn't be anything else, could it?
That is because generaly properties don't have to be related to any declared instance variable of your class. You may have a property and not include a variable into your class header. That's why you have to declare it's type.
Using properties instead of variables makes your headers clean, hiding the implementation.
So, you can just declare a property and then #synthesize it
#interface Peg : NSObject
#property char color;
#implementation Peg
#synthesize color;
#end
Actually, it's no longer needed, at least when compiling for x64 with clang. If you omit instance variable, #synthesize will create one for you.
Just use The following
#interface Peg : NSObject {}
#property char color;

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.