Why I can call a free function before it's defined in Objective-C? - objective-c

I find some code like below worked as expected.
In my opinion, a C function must be declared or forward declared before use.
I didn't find any related description about this usage in LLVM.
Any one could give me some explanation or spec link? Thanks in advance.
#implementation MyObject
- (void)foo {
bar(); // Worked properly. Why no warning like "Implicit declaration of function 'bar' is invalid in C99" occurs here?
}
static void bar(void) {}
#end

Related

Objective C class method error ''Use of undeclared identifier"

Hopefully not a ridiculous question as I'm a self taught programmer, but I found some code which looked like it might help me do something I wanted to. Basically I want to enhance the NSLog() function in one of my apps, and would like to call my method in the same way as NSLog(). It's very difficult to google 'void function()' because nothing seems to be relevant, I'm used to methods that are constructed like this:
-(void)RLog(NSString*)statement;
But the sample suggested using:
void RLog(NSString *statement,...);
This seems to work, and lets me call it with 'RLog(#"My message")', however using it this way the method ignores the class variables, and seems I can't use 'self' either ...
Logging.h
#import <UIKit/UIKit.h>
#import Foundation.NSString;
#interface Logging : NSObject
#property (nonatomic) BOOL enabled;
void RLog(NSString *statement,...);
#end
Logging.m
#import "Logging.h"
#implementation Logging
#synthesize enabled;
void RLog(NSString *format,...) {
/* something that uses 'enabled' throws 'Use of undeclared identifier enabled' */
/* something else that uses '[[self class] session]' throws 'Use of undeclared identifier self' */
}
#end
Hopefully I've included enough information to explain my issue, and not removed too much to make it hard to understand!
Thanks in advance.
Plasma
void RLog(NSString *format,...)
... is not an Objective-C method; it's just a C function.
C functions are global and free-standing. There is no self here and no connection with Logging's enabled. As far as this function is concerned, the Logging class might as well not exist at all.
After a bit more investigation I found a way around this using the information here.
I added a class variable called thisClass and then assigned 'self' to it during my class init stage.
#implementation Logging
id thisClass;
- (id) init
{
if (self = [super init])
{
thisClass = self;
}
return self;
}
From inside the C function I can now call methods in my Logging class using:
[thisClass log:#"Testing"];
Without having to send "self" in as a parameter, I've moved the rest of the code which needs the local variables in to my 'log' method and simply use the C method to call it in a simplified way.
Plasma

Where do I program a variable in an objective c class so all its methods can use it?

I need to have 5 of my methods use a common variable, but I don't know where to declare it in my .m file. I know this is basic, but I'm quite new and I forgot where to put it. Please help me.
#implementation {
// instance variables here <---
int foo
float bar;
}
// methods here
#end

Don't understand the reason for "Expected a type" compilation error in a method declaration, when the type is defined

This code won't compile and generates the error message "Expected a type". As the type is declared right above I don't understand why.
enum TMyType
{
Etype1,
Etype2
};
#interface Factory : NSObject
+ (void) foo: (TMyType) actionType;
#end
To define a custom type, the correct way is with a typedef.
Try...
typedef enum
{
Etype1,
Etype2
} TMyType;
EDIT:
Not long after this question was asked and answered, Apple came out with a new way to do enumerated data types. Here's an in-depth article on it.
typedef NS_ENUM(NSInteger, TMyType) {
Etype1,
Etype2
};
+ (void) foo: (enum TMyType) actionType;
or use .mm (and retag question with objective-c++).

Objective-C: Should I declare private methods?

I've been declaring private methods in class extensions, according to Best way to define private methods for a class in Objective-C.
But, I just realized that, in Xcode 4, if I leave out the declaration of a private method altogether and just implement it, the app compiles and runs without warning or error.
So, should I even bother declaring private methods in class extensions?
Why should we have to declare methods anyway? In Java, you don't... neither in Ruby.
A method definition only needs to be defined if the caller is declared before the method. For consistency I would recommend defining your private methods in the extension.
-(void)somemethod
{
}
-(void)callermethod
{
//No warning because somemethod was implemented already
[self somemethod];
}
-(void)callermethod2
{
//Warning here if somemethod2 is not defined in the header or some extension
[self somemethod2];
}
-(void)somemethod2
{
}
This answer has already been correctly answered by Joe for Xcode prior to v4.3. However, in v4.3 and above, not only do private methods not need to be declared, but declaration order is now irrelevant. For details, see:
Private Methods in Objective-C, in Xcode 4.3 I no longer need to declare them in my implementation file ?
This will compile and run fine without declaration:
- (void)foo {
}
- (void)bar {
[self foo];
}
But last I checked, this will give a warning:
- (void)bar {
[self foo];
}
- (void)foo {
}
In other words, it's just like in C: a declaration is not necessary if the definition comes before any use. C requires this to avoid having to add an extra pass to the compiler (one to find the functions and then one to actually parse them). As for whether you should declare them when not necessary, it's really up to the style of the codebase you're working with.
As for other languages that don't require declarations, some just go ahead with the extra pass, while others don't need to know the number and types of the arguments or the return type at compile time (they look up functions at runtime instead, or they don't have strongly-typed variables to begin with so it doesn't "matter") so they can just skip it.

Is it possible to declare a method as private in Objective-C?

Is it possible to declare a method as private in Objective-C?
If you're working in Objective-C 2.0, the best way to create methods that are "hard" for others to call is to put them in a class extension. Assuming you have
#interface MyClass : NSObject {
}
- (id)aPublicMethod;
#end
in a MyClass.h file, you can add to your MyClass.m the following:
#interface MyClass () //note the empty category name
- (id)aPrivateMethod;
#end
#implementation MyClass
- (id)aPublicMethod {...}
- (id)aPrivateMethod {...} //extension method implemented in class implementation block
#end
The advanage of a class extension is that the "extension" methods are implemented in the original class body. Thus, you don't have to worry about which #implementation block a method implementation is in and the compiler will give a warning if the extension method is not implemented in the class' #implementation.
As others have pointed out, the Objective-C runtime will not enforce the privateness of your methods (and its not too hard to find out what those methods are using class dump, even without the source code), but the compiler will generate a warning if someone tries to call them. In general, the ObjC community takes a "I told you not to call this method [by putting it in a private class extension or category or just by documenting that the method is private] and you called it anyways. Whatever mess ensues is your fault. Don't be stupid." attitude to this issue.
No, any object can send any message to any other object. You can, however, put the method in a category that's part of the class's implementation file. That way, you'll get a "Class may not implement this method" warning if you try to call it anywhere else. That's the normal way of making a method "private."
There is nothing that will prevent the method being called (since objective-c is message based anything can be sent any message), but you can declare them outside of the header so they are not visible and the compiler will generate warnings if used.
This works for both class and instance methods.
E.g.
#import "SomeClass.h"
// Interface for hidden methods
#interface SomeClass (hidden)
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod;
#end
Note: Do NOT declare variables like this or they will become class-variables - e.g. only one variable will be used by all instances.
You can do so by using categories. I've got a fuller description in my answer to this SO question.
As has been said, you can't stop anyone sending a message to a selector, but by using categories you can reduce the visibility of these functions.
Also, you can have more than one category extending a class. So, by using informative category names you can group private functions into related blocks, improving the self-documenting nature of your code.
As others mentioned, you can't have code that's
a method, and
impossible to call from outside a class.
Folks have already pointed out that you can abandon point 2, and get a method that's hard-but-not-impossible to call. Alternatively, why not abandon point 1?
static id myPrivateMethod(MyObject *me, int arg1, id arg2) { ... }
Now the code can only be called from within same file. You don't get any of the magic private-member access you can get with a method, so this is by no means a perfect solution. But there's no better way to achieve privacy.
To implement hidden methods (instance and/or class)
// ===========================
// = File: SomeClass.m
// ===========================
#import "SomeClass.h"
// =================================
// = Interface for hidden methods
// =================================
#interface SomeClass (hidden)
-(void) hiddenInstanceMethod;
#end
// ================================
// = Implementation for SomeClass
// ================================
#implementation SomeClass
-(void) hiddenInstanceMethod
{
printf( "Hidden instance method\n" );
}
-(void) msg
{
printf("Inside msg()...\n");
[self hiddenInstanceMethod];//private method calling
}
#end
http://macdevelopertips.com/objective-c/private-methods.html
reffer this link it will be helpful .