Can someone confirm that you cannot access instance variables defined in an Objective C #implementation block from within C style functions of the same class? The compiler is throwing errors saying "XXX undeclared' where XXX is the instance variable name.
Here's an example of what I am explaining:
#interface FontManager : NSObject {
CGFontRef fontRef;
}
static int CstyleFunction() {
NSUInteger emSize = CGFontGetUnitsPerEm(fontRef);
}
I want to verify that I cannot use "fontRef" from withing "CstyleFunction".
Any insight would be greatly appreciated.
A "C style method" doesn't really deserve the name "method", I'd call it a "function" instead as in C.
A C function has no self, so it cannot implicitly access ivars as a method can. If you pass an instance to the C function as a parameter, you can access ivars in the same manner you would access a field in a struct pointer.
#Anomie and #jlehr are correct, the C function has no concept of the FontManager object and its current state, it just happens to live in the same file.
However, if FontManager is a singleton and you make fontRef a property (or create an accessor for it), then it would be possible to access the value within your C class:
static int CstyleMethod() {
FontManager *fm = [FontManager sharedManager];
NSUInteger emSize = CGFontGetUnitsPerEm(fm.fontRef);
}
Bottom line, you can mix-and-match C and ObjC syntax within C functions & ObjC methods. But because C functions have no default reference to self (and the object's associated instance variables), you can only reference ObjC objects that are singletons, stored in a global variable, or passed in as parameters.
That's correct. You seem to be mixing up methods and functions though. Methods exist only in Objective-C. What you're referring to as a 'C style method' is really just a C function.
C is not an object-oriented programming language. Since there's no such thing as an object in C, there's also no such thing as an instance variable in C, so the fontRef instance variable would not be visible in the function you posted, nor for that matter in any other C function in your program.
Related
According to this comment:
C functions inside #implementation blocks have the unique property of
being able to access private and protected ivars directly. Thus, from
my own experience, it's become a strong idiom to place C functions
that "belong" to a class inside the corresponding implementation.
My code, defining a private instance variable in the implementation only as suggested by this answer:
With the brackets:
#implementation ViewController{
MyTest *tt;
}
void testf(){
NSLog(#"hello back from c++ into obj c land");
[tt testcf: 5];
}
...
Will not build; the compiler indicates that tt in testf is undeclared. If I remove the brackets, then the C function works fine.
But... if I remove the brackets, do I understand that actually this is no longer an instance variable, but sneakily it is a global variable, disconnected from the class, despites its placement in the #implementation? It would appear that this is indeed true, since I can do this as the end:
#end
void testf2(){
NSLog(#"hello back from c++ into obj c land");
[tt testcf: 5];
}
And the compiler does not contain about tt being out of scope. So -- how to declare a private instance variable in an implementation and have it truly be an instance variable, but also have a C function be able to access it? For the purposes of this question, I am trying to get this to work based on the linked comments/answers without using the id pointer of the object itself.
You will need to pass a reference to self to the C-function:
void testf(ViewController *vc){
NSLog(#"hello back from c++ into obj c land");
[vc->tt testcf: 5];
}
and call it like this:
- (void)someMethodInViewController
{
testf(self);
}
However it's not clear why you are using C-functions at all.
Can someone confirm that you cannot access instance variables defined in an Objective C #implementation block from within C style functions of the same class? The compiler is throwing errors saying "XXX undeclared' where XXX is the instance variable name.
Here's an example of what I am explaining:
#interface FontManager : NSObject {
CGFontRef fontRef;
}
static int CstyleFunction() {
NSUInteger emSize = CGFontGetUnitsPerEm(fontRef);
}
I want to verify that I cannot use "fontRef" from withing "CstyleFunction".
Any insight would be greatly appreciated.
A "C style method" doesn't really deserve the name "method", I'd call it a "function" instead as in C.
A C function has no self, so it cannot implicitly access ivars as a method can. If you pass an instance to the C function as a parameter, you can access ivars in the same manner you would access a field in a struct pointer.
#Anomie and #jlehr are correct, the C function has no concept of the FontManager object and its current state, it just happens to live in the same file.
However, if FontManager is a singleton and you make fontRef a property (or create an accessor for it), then it would be possible to access the value within your C class:
static int CstyleMethod() {
FontManager *fm = [FontManager sharedManager];
NSUInteger emSize = CGFontGetUnitsPerEm(fm.fontRef);
}
Bottom line, you can mix-and-match C and ObjC syntax within C functions & ObjC methods. But because C functions have no default reference to self (and the object's associated instance variables), you can only reference ObjC objects that are singletons, stored in a global variable, or passed in as parameters.
That's correct. You seem to be mixing up methods and functions though. Methods exist only in Objective-C. What you're referring to as a 'C style method' is really just a C function.
C is not an object-oriented programming language. Since there's no such thing as an object in C, there's also no such thing as an instance variable in C, so the fontRef instance variable would not be visible in the function you posted, nor for that matter in any other C function in your program.
Trying to make sense of MTAudioProcessingTap sample code from WWDC 2012.
This structure is used by the Tap to pass data around.
typedef struct AVAudioTapProcessorContext {
...
void *self; //Note use of word self
} AVAudioTapProcessorContext;
The word self here is used apparently as a standard variable name even though Xcode highlights it in pink. Is this just a code parsing oversight in Xcode?
Later, the Tap management class passes a reference to itself to this variable.
//Setting up Tap callbacks:
callbacks.clientInfo = (__bridge void *)self,
//And then storing it in the above struct when it's passed by the callback:
static void tap_InitCallback(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut)
{
AVAudioTapProcessorContext *context = calloc(1, sizeof(AVAudioTapProcessorContext));
...
context->self = clientInfo;
*tapStorageOut = context;
}
And the confusion starts again in a later function (another Tap callback). Once again, the word self is used to refer to the Tap management class reference. Note that this occurs in a function defined after #end of the Tap management class implementation.
AudioFFTTapProcessor *self = ((__bridge AudioFFTTapProcessor *)context->self);
self has a special meaning only in the context of an Objective-C method. In all other contexts, it's just an ordinary identifier. You can think of Objective-C methods as being rewritten to take a hidden parameter with the name self (and a second hidden parameter named _cmd that's not relevant for this discussion), e.g.:
#implementation MyClass
- (void)doSomething:(int)param1 withThis:(NSString *)param2
{
// 'self' refers to the MyClass instance in this function
...
}
#end
could be imagined as if it were rewritten like this:
void MyClass_doSomething(id self, SEL _cmd, int param1, NSString *param2)
{
// 'self' refers to the MyClass instance in this function
...
}
Outside of Objective-C methods, you can use self as any other kind of identifier, whether it be a local variable, a struct member, a global function, or type name, etc., though the latter uses should be highly discouraged due to high potential for confusion.
So yes, XCode highlighting the self instance in pink in the struct definition is just a parsing anomaly.
self is not a keyword in C. It's a keyword for Objective-C, which is probably why it's getting highlighted.
self does not mean anything special as a C struct field name. Objective-C uses it as the equivalent of most other OO languages' this, which is why Xcode highlights it specially.
Do variables declared in methods get erased after the method call is done? Ie If i have the method "someMethod" and every time it is called i want to return a different NSString from a stack property will the method return the next object on the stack or will it keep returned the first index since x is erased at the end of the method call. I know if C that variables are erased after function calls, is it the same in objective c? Would using a seperate property for the variable x some this problem? Thanks
(Double) someMethod{
int x;
[self.stack objectAtIndex:x];
x++;
}
After reading the comments I tried creating a property to replace x and here is what I wrote but I get an error warning stating "local declaration of "_location" hides instance variable" What does this mean?
#property (nonatomic) int location;
#synthesize location=_location;
-(int) location{
if(!_location){
int _location = 0;
//warning is here
return _location;
}
_location++;
return _location;
}
(Double) someMethod{
int x;
[self.stack objectAtIndex:self.location];
x++;
}
Do variables declared in methods get erased after the method call is done?
Yes
Objective C methods are implemented "on top" of C functions, so the same rules apply. In particular, your code exhibits undefined behavior (reading of uninitialized variable).
To fix this issue, add an instance variable x in place of the automatic variable that your code snippet currently declares.
automatic is the "official" name of "stack" variables, i.e. variables that you declare inside your methods / functions.
Yes, the lifetime of local variables is limited to the time the enclosing function is executing (with exceptions for blocks, but you're not using those in this case).
Your counter x is probably best as an object property, if you want to maintain its value between calls to someMethod.
Answering to your question about the warning...
It is just saying that when you declare inside your if in method location()
int _location = 0;
this local variable has the same name as the property you created earlier
#syntenshize location = _location
Thus it gets confusing (for the programmer) to know which one he is using at the moment.
The compiler will understand that inside the if _location is an int ... and outside the if _location is your property.
Just when I think I'm getting comfortable with Objective-c the mentioned symbols totally throw me down a rabbit hole...
** a double pointer??
& what sort of things can I do with &reference, is a #property? a full on object? weird pointer razzledazzle?
± I see both a + or a - before method declarations; I've seen Java annotate some datatype declarations by manually typing the + and the magic of compiling in Eclipse would change them to a -
I'm likely asking repetitious questions and/or way outta the ballpark on my guesses; thanks for answers/edits.
You're getting into the C portion that objective-c is built on top of.
** is a pointer to a pointer. Since functions in C take arguments by value, it means you can't change the value of the argument in that function. But, by providing a level of indirection and passing a pointer to the pointer, you can change the value.
& means it's a reference. If an argument takes a ** and you have a * variable, pass a reference to it.
Foo *foo;
[self changeFoo: &foo];
- (BOOL)changeFoo: (Foo **)foo
{
// dereference the double pointer and assign a val = alloc init returns a *
*foo = [[Foo alloc] init];
return YES;
}
A common usage in objective-c / cocoa is NSError. It's essentially an out argument.
NSError *err;
BOOL success = [self doSomething:#"Foo" error:&err];
- (BOOL)doSomething:(NSString*)withData error:(NSError**)error
{
}
As you might know, a pointer points to the address of an object and is the way you reference an object. A double pointer is sometimes used in Objective-C, mainly for returning NSErrors, where you want to get back the address, i.e. a pointer, to an error object (NSError) if an error occurred, thus you pass in a pointer assigned to null and the caller can change that pointer so that it points to the address of another pointer which in turn points to an NSError object.
The ampersand (&) is mostly used by the lower level C APIs, e.g. Core Graphics. They are used to reference things, like the current context. As long as most of your code uses square brackets around its method calls you won't see these very often.
Using a + or a - before a method declarations is used to differentiate between class (+) and instance (-) methods. A class methods is called on the class itself (such as alloc), while a instance method is called on an instance of that object (such as init).
- and + before a method declaration designate an instance method and a static class method. To use an instance method you have to create an object of your class before you can call its method, a static method can be called directly from a class type