Use of undeclared identifier - iphone

I'm trying to use this project which is a synthesizer for Objective-C for an iPhone application I'm building. However, I'm having trouble with the MHAudioBufferPlayer class.
In the MHAudioBufferPlayer.m class, I'm getting a bunch of Use of undeclared identifier errors for _gain, _playing, and _audioFormat. This makes sense, as those identifiers are never declared with an underscore in front of them. However, they are declared in the MHAudioBufferPlayer.h class without the underscores.
I'm sort of confused by this as I'm new to Objective-C. Does an underscore denote a special action to be taken? Is it supposed to be translated into self.gain, self.playing, etc.? How can I fix this? Or is this code just buggy?
- (id)initWithSampleRate:(Float64)sampleRate channels:(UInt32)channels bitsPerChannel:(UInt32)bitsPerChannel packetsPerBuffer:(UInt32)packetsPerBuffer
{
if ((self = [super init]))
{
_playing = NO;
_playQueue = NULL;
_gain = 1.0;
_audioFormat.mFormatID = kAudioFormatLinearPCM;
_audioFormat.mSampleRate = sampleRate;
_audioFormat.mChannelsPerFrame = channels;
_audioFormat.mBitsPerChannel = bitsPerChannel;
_audioFormat.mFramesPerPacket = 1; // uncompressed audio
_audioFormat.mBytesPerFrame = _audioFormat.mChannelsPerFrame * _audioFormat.mBitsPerChannel/8;
_audioFormat.mBytesPerPacket = _audioFormat.mBytesPerFrame * _audioFormat.mFramesPerPacket;
_audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
_packetsPerBuffer = packetsPerBuffer;
_bytesPerBuffer = _packetsPerBuffer * _audioFormat.mBytesPerPacket;
[self setUpAudio];
}
return self;
}

If you are using new compiler that comes with Xcode4.4 onwards, then for each of your property it creates an automatic synthesize with _(underscore) as prefix.
Like, if you have created #property.... playing;
then the compiler creates #synthesize playing=_playing;
If you are in older versions of Xcode, this need to be done manually.

#synthesize generated by Xcode => 4.4 as the default. The generated private instance variable, ivar, created for you by Xcode has a leading underscore '' if you don't explicitly create your own #synthesize statement. You MUST include the leading '' when sending messages to this
property (typically UI element as an outlet from your controller.m file).
That is
#property textField;
[_textField setStringValue: #"foo"]; if you DON'T write the '#synthesize'.
The compiler's done this for you, and has made a private instance variable by synthesizing the getter/setters. The convention is to make the private ivar the name of the property prepended by the leading underscore.
OR
#synthesize textField;
#property textField;
[textField setStringValue: #"foo"]; if you DO write your own '#synthesize' or are < Xcode 4.4.
Here, the complier has NOT done it for you, your ivar name/property name are the same and can be used w/o the leading '_'.
Good luck.

Depending on what version of XCode you are using, and compiler there are different ways of doing it. I don't know how familiar you are with OOP, if you are not I suggest you read up a bit on setters and getters and objects as it is the basis of almost everything you will do from now on.
Some examples, Old school style, will create an ivar. In your .h:
#interface TheViewController : UIViewController{
NSString *theString;
}
A bit new style, will create setter and getter In your .h.
#interface TheViewController : UIViewController
#property (nonatomic, weak) NSString *theString;
In your .m file:
#implementation TheViewController
#synthesize theString = _theString;
Can be accessed by _theString or self.theString
The new way of doing it. In your .h file:
#property (nonatomic, weak) NSString *theString;
The compiler Will create everything the above way did.
Hope that helps you a bit.

Related

Declaration/definition of variables locations in ObjectiveC?

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.

Difference between _property and self.property

I'm slightly confused as to the proper conventions when dealing with properties. I'll illustrate my question through an example. So from the example below I know that functionally "self.loan = self.loan + 250.00;" is the same as "_loan = _loan + 250.00;" or is it not? I see numerous tutorials all over the web that may or may not use both methods to access a property. So what exactly is the difference between using _loan and self.loan (I know that self.loan is the same as [self setLoan:])
//ClassA.h
#interface ClassA: UIViewController
#property double loan;
#end
//ClassA.m
#implementation ClassA
#synthesize loan = _loan;
-(void)doSomething{
self.loan = self.loan + 250.00; //Exhibit A
_loan = _loan + 250.00; // Exhibit B
}
_loan is a variable and assigning a value to it has no particular side effect.
self.loan = self.loan + 250.00 is essentially the same as writing [self setLoan:[self loan] + 250.00] in that methods are called that may do other things than simply set or get the value of a variable. The extra things those methods do depend on whether you write custom versions of them (the setters and the getters) or use #synthesize to create them and, if you use #synthesize, what attributes you apply in the #property declaration.
When you write out #synthesize loan = _loan; it is basically shorthand to say that what you are synthesizing is = to a private member it would be similar to the verbose way of coding it below:
//ClassA.h
#interface ClassA: UIViewController {
double _loan;
}
#property double loan;
#end
//ClassA.m
#implementation ClassA
#synthesize loan = _loan;
It is good practice to write it out this way so you can clearly have a '_' to signify your private members within your class code but when exposing this as a property to other classes that shouldn't be shown.
You should never use direct reference to a variable when accessing a property. Always go for self.property in your code.
If you use _property you are not making use for your getters and setters. In this case you are just wasting #synthesize use.
self.loan = self.loan + 250.00; //Exhibit A
This should be right approach.

Is there a way to do lazy initialization of a atomic property without having to write setter and getter by hand?

Apparently it's not possible to use #synthesize when overwriting an atomic property accessor. Xcode 4 will produce a warning.
Now, is there another way of using lazy initialization of atomic properties while still letting Xcode synthesize both getter and setter automatically, without overwriting any of them?
What you need to do is write both the setter and the getter. You can still #synthesize to get the storage. e.g.:
//.h
#property (strong) id x;
//.m
#synthesize x = _x;
- (id)x
{
#synchronized(self)
{
if (!_x)
{
_x = [[MyX alloc] init];
}
return _x;
}
}
- (void)setX:(id)x
{
#synchronized(self)
{
_x = x;
}
}
You may need to do additional memory management without ARC and may want to create a different lock (instead of self) or use a different synchronisation method, but it'll give you the gist.

Class not setting as expected

Icon is set as #property (nonatomic, retain) AHGridIcon *icon;
Usually i just do:
-(void)setIcon:(AHGridIcon *)iconLocal {
icon = iconLocal;
}
But i read a guide to getters setters and properties online which has lead me to believe that instead, this is right:
-(void)setIcon:(AHGridIcon *)iconLocal {
if (iconLocal != self.icon)
{
NSLog(#"local: %#", iconLocal);
NSLog(#"self.icon 1: %#", self.icon);
[iconLocal retain];
[icon release];
icon = iconLocal;
NSLog(#"self.icon 2: %#", self.icon);
}
}
The problem is, the original icon is staying put, it's not being replaced with the new icon. What am i doing wrong? Should i just revert to the usual way i do it?
You should use '#synthesize' unless you really need custom setter behavior.
like I posted in my comment:
the best way is to use #synthesize which will create a getter and a setter to with respect to the properties you wrote in your property (nonatomic, retain) => not threadsafe but fast getter and setter and a retaining (and also releasing) setter. If you dont need sophisticating stuff to do in your setter then you should not override the setter.
.h:
#property (nonatomic, retain) AHGridIcon *icon;
.m:
#implementation Something
#synthesize icon;
...
#end
The code you posted in your setter is nearly the same as the compiler would produce when only using synthesize.
Your usual way is not really nice because in your header is defined (in your property) that the setter is retaining but in your implementation you are overriding that correct setter which doesn't retain. It is nearly the same as the compiler would produce with an (nonatomic, assign) property.
But if you want to override your setter then it should look like the same as you wrote. For me it is working fine.
first retaining the new object
then releasing the old one
then assigning the local pointer to your new object
you can even omit your if but then it is really important that you first retain the new and then release the old objects (like you did - just want to mention that).
For solving your problem with an overriten setter: Your setter looks ok in my eyes. Have you also overriten the getter? If yes then post it here (you use it by calling self.icon in your log-call).
I've done a small test-program
#synthesize str;
- (void)setStr:(NSString *)localStr
{
if(str != localStr)
{
NSLog(#"old : %#", self.str);
NSLog(#"new1: %#", localStr);
[localStr retain];
[str release];
str = localStr;
NSLog(#"new2: %#", self.str);
}
}
and the output is fine:
old : (null)
new1: Hello
new2: Hello
old : Hello
new1: World
new2: World

Property vs. instance variable

I'm trying to understand how strategies some folks use to distinguish instance vars vs. properties. A common pattern is the following:
#interface MyClass : NSObject {
NSString *_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#end
#implementation MyClass
#synthesize myVar = _myVar;
Now, I thought the entire premise behind this strategy is so that one can easily distinguish the difference between an ivar and property. So, if I want to use the memory management inherited by a synthesized property, I'd use something such as:
myVar = #"Foo";
The other way would be referencing it via self.[ivar/property here].
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Thanks.
Properties are just setters and getters for ivars and should (almost) always be used instead of direct access.
#interface APerson : NSObject {
// NSString *_name; // necessary for legacy runtime
}
#property(readwrite) NSString *name;
#end
#implementation APerson
#synthesize name; // use name = _name for legacy runtime
#end
#synthesize creates in this case those two methods (not 100% accurate):
- (NSString *)name {
return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
[value retain];
[_name release];
_name = value;
}
It's easy now to distinguish between ivars and getters/setters. The accessors have got the self. prefix. You shouldn't access the variables directly anyway.
Your sample code doesn't work as it should be:
_myVar = some_other_object; // _myVar is the ivar, not myVar.
self.myVar = some_other_object; // works too, uses the accessors
A synthesized property named prop is actually represented by two methods prop (returning the current value of the property) and setProp: (setting a new value for prop).
The self.prop syntax is syntactic sugar for calling one of these accessors. In your example, you can do any one of the following to set the property myVar:
self.myVar = #"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: #"foo"]; // handle retain/release
_myVar = #"Foo"; // does not release old object and does not retain the new object
To access properties, use self.propname. To access instance variables use just the instance variable's name.
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Because the variable myVar is undeclared.
That statement uses the syntax to access a variable, be it an instance variable or some other kind. As rincewind told you, to access a property, you must use either the property-access syntax (self.myVar = someOtherObject) or an explicit message to the accessor method ([self setMyVar:someOtherObject]).
Otherwise, you're attempting to access a variable, and since you don't have a variable named myVar, you're attempting to access a variable that doesn't exist.
In general, I name my properties the same as my instance variables; this is the default assumption that the #property syntax makes. If you find you're fighting the defaults, you're doing it wrong (or your framework sux, which is not the case for Cocoa/Cocoa-touch in my opinion).
The compiler error you're getting is because property use always has to have an object reference, even inside your own class implementation:
self.stuff = #"foo"; // property setter
[stuff release]; // instance variable
stuff = #"bar"; // instance variable
return self.stuff; // property getter
I know that many Cocoa programmers disagree, but I think it's bad practice to use properties inside your class implementation. I'd rather see something like this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
[stuff release];
stuff = [theStuff copy];
// do something else
}
than this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
self.stuff = theStuff;
// do something else
}
I prefer to do memory management as explicitly as possible. But even if you disagree, using the self.stuff form will clue in any experienced Objective-C programmer that you're calling a property rather than accessing an instance variable. It's a subtle point that's easy for beginners to gloss over, but after you've worked with Objective-C 2.0 for a while, it's pretty clear.
Don,
According to the "rules", you should call Release for every Copy, Alloc, and Retain. So why are you calling Release on stuff? Is this assuming it was created using Alloc, Copy, or Retain?
This brings up another question: Is it harmful to call Release on a reference to an object if it's already been released?
Since Apple reserves the _ prefix for itself, and since I prefer to make it more obvious when I am using the setter and when I am using the ivar, I have adopted the practive of using a prefix of i_ on my ivars, so for example:
#interface MyClass : NSObject {
NSString *i_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#synthesize myVar = i_myVar;
i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]
Since it is quite important to know when you are using the setter and when you are using the ivar, I find the explicitly different name is safer.
In your question, it should be:
self.myVar = #"Foo"; // with setter, equivalent to [self setMyVar:#"Foo"]
and
_myVar = some_other_object; // direct ivar access - no memory management!
Remember that you should not use setters/getters in init/dealloc, so you need to do your direct ivar access (and careful memory management) iin those methods.
what's wrong with simply using
#interface MyClass : NSObject
#property NSString *prop;
#end
nonatomic and retain are not required, retain is the default, and atomic/nonatomic isn\t important unless XCode tells you with a warning.
it is NOT necessary to declare the iVar, one will be created for you named _prop, if you really want to use one (i don't see why to be honest)
#synthesize is NOT required.
when (and you should) using ARC you don't have to bother with retain and release either.
keep it simple !
furthermore, if you have a method like this one
- (void)aMethod:(NSString*)string
{
self.prop = string;
// shows very clearly that we are setting the property of our object
_aName = string;
// what is _aName ? the _ is a convention, not a real visual help
}
i would always use properties, more flexible, easier to read.