Objective C class method error ''Use of undeclared identifier" - objective-c

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

Related

Create categories, inherance or delegate?

I am having a little problem. My scenario is: I will build a project with a lot of target. I want have the "public code" (for all target) and "specific code". The problem is: In "public code", I NEED call function at "specific code".
My first try was using categories. I create "public.h" then "public+specific.h" codes using categories. The class that will use this class will need to:
#import "public+specific.h"
...
public *myClass = [[public alloc] init];
[myclass doSomething];
To use another specific class, i only need to change the #import and nothing more. The unique problem is that in "public class" i will need create a false function, like.
//public.h
#interface public : NSObject {}
...
- (void) doSomething {return };
//public+specific.h
#interface public (specific)
...
- (void) doSomething { //do what it really have to do };
The other problems is intrinsic to categories: I can't create local class variable, all will have to be declared in "public.h". I want have all specific things IN specific class...
Ok, so I try in another way: use Inheritance with delegates. In the classes "public.h" and "public+specific.h" it work very well, no need to use fake function, all was fine. BUT, (aways a but), I always will have to alloc the specific class, and if I don't want this, I can create a fake function only to call the delegate, so I have the same problem above. This is a sample:
//In public.h
#protocol publicDelegate
-(void)doSomething;
#end
#interface public : NSObject {
id <publicDelegate> myDelegate;
}
-(id)initWithDelegate (id <publicDelegate>)initDelegate{
myDelegate = initDelegate;
[myDelegate doSomehing];
}
//public+specific.h //The '+' isn't correct here :P
#include public.h
#interface public_specific : public <publicDelegate> {}
- (id)init{
return [super initWithDelegate:self];
}
- (void) doSomething { //do what it really have to do };
Like I say, the problem here is how I create this object
#import "public+specific.h"
...
public_specific *myClass = [[public_specific alloc] init];
[myClass doSomething];
With this, I will have to create a lot of #if defined , #elif defined... every time that I need to create a object call. With categories, I only need to do this with the "#include".
To solve this problem, I can have things like this:
//in "public.h"
- (void) doSomething {
return [myDelegate doSomehing]
};
Another time I will create fake function. And worst, for every new function in "public+specific.h" I will have to create another fake function.. zzz.. (in categories, i have to do this only with function with "public.h" call in "public+specific.h")
So, anyone have another idea to this problem?? It's a little problem, but I want to make my code good, easy to develop and clean...
in many cases, composition would serve you well.

Clang generating warning "method '-init' not found" for very simple class

I just came across Clang/LLVM today, and decided to try it out.
My system is FreeBSD8.1-Release.
The default system compiler is GCC4.2.1, which is what I have been using to compile my Objective-C project up until now.
I'm playing around with the Static Analyzer, and would like to know how to eliminate one of the warnings that is being generated.
MyClass.h
#import <objc/Object.h>
#interface MyClass: Object {
}
-(MyClass*) init;
#end
MyClass.m
#import "MyClass.h"
#implementation MyClass
-(MyClass*) init {
self = [super init];
if (self) {
// do stuff
}
return self;
}
#end
The warning:
%clang --analyze MyClass.m
MyClass.m:7:9: warning: method '-init' not found (return type defaults to 'id')
self = [super init];
^~~~~~~~~~~~
1 diagnostic generated.
I take it that the analyzer does not know how to determine super's type (Object, in this case). Is there any way to eliminate this warning (other than by suppression)? I looked into casting super, but it looks like that is not allowed.
Thanks!
Max
Update
Thanks to Dave and bbum for pointing me in the right direction for eliminating the warning. Now I'm trying to figure out why the warning occurs in the first place.
If anyone has any ideas or leads, I love the hear them.
Thanks,
Max
Two issues:
You should be inheriting from NSObject, not Object.
Your init method should return id, not MyClass*.
The warning is saying that it does not know of any method named -init at all in scope at that point. You need to import a header file that declares -init, which is probably Foundation.h or something, depending on what system you're using.

ViewController may not respond to'method' problem

I know it is a common problem, I googled a lot and seems get no luck to solve my problem.
I have a #interface TestViewController:UIViewController
and in its implementation file I have a method defined:
-(void)method1 {
do something;
[self method1];//here I need to call the method itself if a statement is true and this line is where the warning TestViewController may not respond to'method1' I got
}
-(void)method2{
[self method1] //But there is no problem with this line
}
Can anyone help me?
Thanks in advance!
Your method declarations are missing in the header.
Just add
-(void)method1;
-(void)method2;
to your TestViewController.h file
Update:
The reason why you don't get a warning about the second call ([self method1] within method2) is, that the compiler already knows about method1 at that point. (because the implementation occurs before method2)
Objective-C just as C uses a single pass compiler to gather all known symbols. The result is that you can only reference methods and variables that has been declared above the current scope.
You can solve this particular problem you give an example of in three ways:
Add method1 to the public interface in the header file, just as #weichsel suggested.
If you want method1to be private then you can add it to your class by declaring an unnamed category at the top of you implementation file. Like this:
#import "Foo.h"
#interface Foo ()
-(void)method1;
#end
#implementation Foo
// ... lots of code as usual ...
#end
The third option could be regarded as hack by some, but it really a feature of the Objective-C language. Just as all methods get an implicit variable named self that is the instance the method was called on, so do all method alsa get the implicit variable named _cmd, that is of type SEL, it is the selector that was used to call this method. This can be used to quickly call the same method again:
-(void)method1 {
if (someContition) {
[self performSelector:_cmd withObject:nil];
} else {
// Do other stuff...
}
}
This is most useful if you want to make sure that a particular method is always performed on the main thread:
-(void)method {
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
return;
}
// Do stuff only safe on main thread
}

objective-c delegate

i working with geocoding at the moment. The geocoding service allways works with delegates.
So let's say, I've got a
AskingClass and AnsweringClass(geocoding)
The AskingClass calls a function in the AnsweringClass to return the adress of the current location.
AnsweringClass should handle and capsulate the geocoding stuff. My Problem is, with all these delegates, I do not manage to come back to the orginal function, which the asking class has called. So I cannot give easily the adress back:
AskingClass.Adress= [AnsweringClass giveAdress];
I managed it, doing it with delegates, so the result comes back in a delegate function (somewhere) in the askingClass. But I'm not happy with that. It's seems oversized and complex.
with best regards
Klaus-Dieter
It is unclear why you are using a delegate pattern at all. Why not just use straight up classes?
Something like this (assuming that you are using a PCH file for your header files or otherwise importing 'em as needed):
AnsweringClass.h
#interface AnsweringClass:NSObject
- (MyAnswer *)answerThisDude;
#end
AskingClass.h
#class AnsweringClass; // just in case you including AskingClass.h before AnsweringClass.h
#interface AskingClass : NSObject
// {
// declare the ivar if you need support for 32 bit "classic" ABI
// AnsweringClass *theThingThatAnswers;
// }
#property(retain) AnsweringClass *theThingThatAnswers;
#end
Then you can do this:
AskingClass.m
#implementation AskingClass
#synthesize theThingThatAnswers;
- (void) setUpMyStuff // probably invoked by your designated initializer or app launch handler
{
self.theThingThatAnswers = [AnsweringClass new];
MyAnswer *theFirstAnswer = [self.theThingThatAnswers answerThisDude];
}
// don't forget a -dealloc if you aren't running GC'd
#end
No delegation necessary.

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 .