avoid warning when doing class extention - objective-c

I want to do the following :
#interface UINavigationController ()
-(void)removeFromNavigationStack:(Class)aClass;
#end
and in .m file
#implementation UINavigationController
-(void)removeFromNavigationStack:(Class)aClass {
}
but in the .m file there are a lot of warning like "Method definition for 'initWithRootViewController:' not found"
how can I avoid this ? I've tried including but still have the warnings
Thanks

Since you're dealing with UINavigationController, a UIKit class, you probably want to go with a category, instead. Extensions need to be defined within the main #implementation block of the class's implementation, and you don't have access to that for UINavigationController
From the docs:
Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main #implementation block for the corresponding class. Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension.

Add your class extension in your .m file.

Related

Error: Property implementation must have its declaration in '<classname>' interface or one of its extensions

I have a Swift extension as follows:
#objc
protocol Themeable: class {
#objc var themeGradient: Gradient { get set }
}
In Objc, I have some view controllers adopting that protocol, using #synthesize for the property.
#import "MyProject-Swift.h"
#interface MyObjcViewController () <Themeable>
#end;
#implementation MyObjcViewController
#synthesize themeGradient;
...
#end;
When building I'm getting this error in the #synthesize line:
Error: Property implementation must have its declaration in interface
'MyObjcViewController' or one of its extensions
Is it possible to synthesize properties defined in Swift protocols?
Well, this is a bit embarrassing. While working on this, I contemplated the idea of delaying this protocol in Objc, and I had this left over somewhere in the code:
#protocol Themeable
#end;
This declaration was on a header file, and was not triggering a "Redeclaration" error :(
Removing the above declaration made the #synthesize work as intended.

Are methods declared in categories visible to other classes

Suppose I have the following
FileName : DBManager.h
#import <Foundation/Foundation.h>
#interface DBManager : NSObject
//Notice no method is declared here
#end
Now its implementation file looks like this
FileName: DBManager.m
#import "DBManager.h"
#interface DBManager()
+ (DBManager*) SomeMethod;
#end
#implementation DBManager
+ (DBManager*) SomeMethod
{
....
return SomePtr;
}
#end
Now in some other class method if I do the following
[DBManager SomeMethod] ; //Error No known class method for selector 'SomeMethod'
However if SomeMethod is declared inside the .h file inside of category then this works fine. I wanted to know if this was a limitation of categories that the methods are not visible to other classes ?
First, #interface DBManager() is not a category, it's a class extension. There's no identifier between the parentheses.
Second, the issue isn't visibility based on whether the method is declared in a class, category, or class extension, it's whether it was declared in the same translation unit.
A translation unit is a source file after the preprocessor has included/imported the header files (or whatever other files have been included/imported).
The error is telling you that the declaration of +SomeMethod was not declared in the translation unit. If it were, there'd be no error, regardless of whether it were declared in the class interface, a category, or a class extension.
It follows that if you declare the interface of a category in a header file and include the header file in a source file, you can use the methods declared by that category in that source file.

Declaring in Objective-C

I am very new to Objective-C programming, and I have a question that has always puzzled me: why do you have to declare your variables in the header file, like this?
#interface MyViewController : UIViewController
{
NSString *myString;
}
Why not just declare them here (in the .m file):
#implementation MyViewController
- (void)viewDidLoad
{
NSString *myString;
}
The first declaration is a instance variable available to all instance methods. The second is local to the one method.
However it is possible to declare instance variables in the .m file:
#implementation MyViewController {
NSString *myString;
}
In fact this is the preferred way to declare instance variables that do not need to be exposed. Only declare things in the .h file that need to be available to other classes.
There are two different questions going on here.
To put it simply, the header file (.h) is a public gateway for everything else to see what your class is about without having to know anything about your implementation. Your header file should contain everything that you would want other classes to know about (i.e. public methods, properties).
You could easily declare things in the implementation file but then other classes would not know about them.
Secondly, in the example you provided you have put NSString *myString; in the viewDidLoad method. This means that such a variable would be only available in the scope of that method. Nothing else would be able to access it.

Declaring method prototypes in header and implementation

I am learning object orientated programming from the online Stanford courses there is a part I am unsure of regarding declarations. I thought that you must always declare the prototype in the header and then write the code in the implementation file, but the professor wrote a method in the implementation without a declaration prototype in the header file, how come?
Also, may someone please clear the difference between private and public and if the method without a prototype is public or private? The method without a prototype is not from a super class.
That is a perfectly legal way to declare methods that are not to be used outside the class implementation itself.
The compiler will find methods in the implementation file as long as they precede the method in which they are used. However that will not always be the case, as the new LLVM compiler allows methods to be declared in any order and referenced from a given file.
There are a couple of different styles for declaring methods inside an implementation file:
//In the Header File, MyClass.h
#interface MyClass : NSObject
#end
//in the implementation file, MyClass.m
//Method Decls inside a Private Category
#interface MyClass (_Private)
- (void)doSomething;
#end
//As a class extension (new to LLVM compiler)
#interface MyClass ()
- (void)doSomething;
#end
#implementation MyClass
//You can also simply implement a method with no formal "forward" declaration
//in this case you must declare the method before you use it, unless you're using the
//latest LLVM Compiler (See the WWDC Session on Modern Objective C)
- (void)doSomething {
}
- (void)foo {
[self doSomething];
}
#end
If you write the method in you header file it is public and accessible for other classes / objects. If you do not declare it in the header file the method is a private method meaning that you can access it internally in you class but no other class can use this method.

Cocoa: Build Warning that s Forward Declared Class's and #interface May not Exist

I am trying to build the Clustering Plug in my project under Leopard. I have following two questions.
In the project an interface class is defined as
#interface ClusteringController : NSWindowController
{
.......
.....
....
}
#end.
And this class is used in implementation class using forward declaration:
#class ClusteringController;
then in one function it is used as:
- (long) filterImage:(NSString*) menuName
{
ClusteringController *cluster = [[ClusteringController alloc] init];
[cluster showWindow:self];
return 0;
}
When I build this project it produces the warning:
warning: receiver 'ClusteringController' is a forward class and corresponding #interface may not exist
Also there is one more warning produced:
warning: no '-updateProxyWhenReconnect' method found
This warning is coming for the following line of code:
if(delegate) [delegate updateProxyWhenReconnect];
Can anybody help me to overcome these warnings?
A forward declaration is used when the header file will be imported after the interface. It looks to me that you've used the #class directive after the interface for the class itself.
The normal use of a forward class declaration looks like this:
#import "SomeSuperClass.h"
#class Forwardclass;
#interface SomeClass : SomeSuperClass
{
Forwardclass anIvar;
}
#property Forwardclass anIvar;
#end
#import "SomeClass.h"
#import "ForwardClass.h"
#implementation SomeClass
#synthesize anIvar;
-(void) setAnIvar:(ForwardClass *) aForwardClass;
#end
The #class directive is never used in an implementation (.m) file.
That's not what #class is for.
You use #class in the header file for another class, to tell the compiler that the class you're declaring does exist. Without it, the compiler would not know that that's a class name, and when you declare a variable as holding a pointer to an instance of that class, the compiler would think that you're just making up words. Using #class is called forward-declaring the class.
Your situation is different. You're in the implementation file for that class.
What the compiler needs from you now is the class's #interface. The warning is telling you that the compiler needs an #interface, but you haven't given it one (so, as far it knows, the #interface “may not exist”).
Normally, you would have written the #interface in a header file; how now to get it into the implementation file?
That's where the preprocessor comes in, with its #import directive. At the top of the implementation file (ClusteringController.m), import the header file:
#import "ClusteringController.h"
The preprocessor will replace this with the contents of that file, then hand the preprocessed code to the compiler, which will see the #interface there.