I have an XCode project I am working on that has multiple views controlled by a tabBar that is throwing multiple instances of the error:
"cannot find interface declaration for '~my sub view name~', superclass of '~my sub view name~'
These sub views were created after the original project as new files. Each has a line of code like this:
#interface meViewAndEdit : meViewAndEdit
I see no #import statements either. The project fails to build and I am not sure what i should be setting these to. Should I be referencing my App delegate as the superclass? what is missing here?
UPDATE: (updated)
I changed the interface statements for each of my header files for the views i created as follows
#interface friends : UIView
BUT, it seems that i have a new issue that i'll have to research:
"UIView" may not response to "initWithNibName.bundle"
This is now present in each of the .m files for the views I created.
still learning, thanks in advance for your input.
When declaring a class in Objective-C, you need to specify the class name, as well as the superclass. In your code #interface meViewAndEdit : meViewAndEdit, you are essentially declaring a class that is a subclass of itself. Since you are trying to create a subclass of UIView, the class declaration should look as follows: #interface meViewAndEdit : UIView.
Also, in a comment in another answer, you asked whether or not you need to #import the app delegate in every class. The answer to this is usually no, unless you specifically need to access something involving your specific app delegate class.
I will also make note that it is conventional to give classes a capitalized name. For example, it should be MeViewAndEdit, rather than meViewAndEdit. You only should keep the first letter lowercase if it is the name of a variable or function.
EDIT: The reason that you are encountering the errors in your update is that you are trying to subclass UIViewController, not UIView. On top of this, instead of subclassing either one, you are subclassing the app delegate. Change your line of code #interface subviewname : my_app_delegate to #interface subviewname : UIViewController. You are trying to create a subclass of UIViewController, not my_app_delegate.
On another conventional note, it is never good to put underscores in a class name. Always name classes in camel case like MyAppDelegate, not my_app_delegate.
You need to #include the .h header files in all classes in which you are using them.
Related
I am relatively new to Objective-C.
I have come to a code on the web that has something like this on rootViewController.m (this is a navigationController based app).
#interface RootViewController (CManagerDelegate) <CManagerDelegate>
#end
#interface RootViewController (PViewDelegate) <PViewDelegate>
#end
two questions:
what are these lines doing in the beginning of rootViewController.m
what are these lines doing in code? Please explain the stuff in parenthesis and between <> in this particular case.
thanks.
In one sentence: The code you posted makes the RootViewController class privately conform to some delegate protocols.
Delegate protocols are used to let a class declare the fact that it understands the messages from another class's objects. For example, a view controller can declare that it understands a gesture recognizer's delegate messages.
The fact that the class internally uses the gesture recognizer is often an implementation detail not relevant to other clients of the class. It is best not to publish this fact in the public interface but put it into the implementation (.m file).
Categories (and class extensions) let you do exactly this: Make a class conform to a protocol without changing the main #interface.
A nice and elegant solution!
Read up on Categories:
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
And Protocols:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/chapters/ocProtocols.html
In fact, read all of Apple's Objective-c documentation before going any further:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/objectivec/Introduction/introObjectiveC.html
Good luck.
I'm getting the following error
Property 'navigationController' not found on object of type
I've inherited this project and not sure what's going on.
In my m file in didSelectRowAtIndexPath I have
[self.navigationController pushViewController:nextController animated:YES];
It wasn't a problem before as I was accessing app delegate navigation controllers, which were outlets. However, I've had to move away from this approach as it's causing me problems. I've converted the rest of my project. But in this circumstance, where the project isn't using a normal table view, the navigation controller doesn't look to be available. I have this issue in 7 other views. Hoping I could have fixed this, and keep this cleaner code?
I'm really puzzled by this, I think this is occuring as SetsStyleSectionController isn't a view controller but is NSObject.
However, even with this set to UIViewController, the code runs, but doesn't push either.
Changing SetsSectionController from NSObject to UIViewController isn't available.
I'm not sure how to proceed?
I'm in the process of moving away from pushing from app delegate.
Edit: Screenshot 2 discussed below
I see a couple of issues here. You have a misunderstanding about protocols and classes, and you also have an application that interface with a protocol that while well-intentioned is actually making your life much harder than it needs to be.
The first issue you're dealing with is some troubles grokking the difference between protocols and classes, and between adopting a protocol and inheriting from a class. Which is totally fine, this stuff isn't easy. Basically, a protocol is just an interface to an object, and a class provides both an interface and an implementation. In other words, a protocol is just a list of methods that can be called, and a class is both a list of methods and the code to execute those methods. To get a more complete explanation, perhaps you'll be better off going straight to the source - Apple's "The Objective-C Programming Language" will probably help you, so please read about classes and protocols there. I think having done that you'll see why you're not having success giving your id<SetSectionController> instance a navigationController property without explicitly defining one. But do let me know if you have specific questions about this afterwards.
The problem that's harder to fix is this SetSectionController protocol. It has several issues and describing them all is outside the scope of this answer. Here's the thing - the implementation basically requires objects that implement this protocol to know which navigation controller is associated with the table view. This has been up to now provided deus ex machina by coupling them to the application's delegate, and you are right to remove this coupling. But now you have to find another way to get the right data populated into the view controller to push it on the navigation stack.
I think you should move the push logic into the view controller, and for now have the section controller provide an interface that gives the view controller the information it needs. So say the section controller has an implementation like this pseudocode:
- (void)...didSelectRow...
{
id detailsForIndexPath = self.dataForRows[indexPath.row];
DetailViewController *vc = [DetailViewController new];
vc.details = detailsForIndexPath;
[APPDELEGATE.navigationController push:vc];
}
Then I'd add a method to SetSectionController called something like -dataForRow: , the implementation of which would be like the first line of the method above. Then, in your view controller, implement ...didSelectRow... like this:
- (void)...didSelectRow...
{
id<SetSectionController> sc = self.sectionControllers[indexPath.section];
id details = [sc dataForRow:indexPath.row];
DetailViewController *vc = [DetailViewController new];
vc.details = details;
[self.navigationController push:vc];
}
If your section controller is doing anything else useful in ...didSelectRow... make sure to either move it to the view controller or forward ...didSelectRow... on to the section controller for now.
While I do appreciate trying to make complex table sections easier to manage through polymorphism, this protocol wasn't the right way to do it. It blindly copies methods out of UITableViewDelegate and UITableViewDataSource without consideration of whether those are the right questions to be asking something responsible for a single section of a single table. If you still want to use it, I think it will take some significant refactoring to get it into a shape that actually makes your life easier rather than harder. Depending on the complexity of the per-section logic deviation, I might just scrap it altogether. But that's a whole other question really. Hope this helps!
What do you mean it "isn't available"? Do you mean you don't want to/aren't allowed to subclass UIViewController, or are you getting a compiler error? From your comment on your question:
SetsSectionController.h:12:34: Cannot find protocol declaration for 'UIViewController'
you are changing the wrong thing to alter your subclass. As an example:
#import <Foundation/Foundation.h>
#protocol foo <NSObject>
- (void) bar;
#end
#interface lolcats : NSObject <foo>
#end
To change your superclass you change the class name after the colon. Ex.
#interface lolcats : NSObject <foo>
becomes
#interface lolcats : UIViewController <foo>
and you're off and running. However, if you accidentally change the protocol requirement for the protocol
#protocol foo <NSObject>
to
#protocol foo <UIViewController>
instead, or change the protocol you adhere to to <UIViewController>, you'll end up getting the EXACT error you got. You might be confused because the protocol says the object adhering to it must also adhere to the NSObject protocol, and NSObject is also a type of object. The object and protocol are separate things, and all objects inherit from NSObject, and thus inherit the protocol. Basically, it's saying "objects using this protocol must be objects."
Why did you expect this to work? The object is just a standard NSObject that states it adheres to a protocol containing a few methods. Why would it have a navigation controller property? It hasn't inherited it from anything. Regardless, based on your error, you probably just changed the wrong thing. Make sure you change the superclass class name after the colon.
easy question to ask, but not really sure what to search for to find an answer for this one.
do I have to declare the method
- (void) applicationWillResignActive:(NSNotification *) notification;
in my header file? I'm trying to build my first app and im just going through trying to clean up my code.
Thanks!
No you don't have to. These are methods that will allow you to perform certain actions in some conditions, in the case of this one is when your application is about to go to the background. If you don't implement it nothing will happen. It is the same as with "viewWillAppear" and so on.
Also those methods only have to be implemented in the .m file since they come from the parent class. Since you are probably placing it in an object that comes from an UIViewController subclass.
The method applicationWillResignActive: is an optional method in the UIApplicationDelegate protocol. Your app delegate should already have declared that it conforms to that protocol in its header. So since it is already declared you don't have to declare it again.
In my app there are numerous view controllers which have their own purposes. However, underneath they do share some need for common maintenance work that could use the same method code instead of each having its own copy of the code, literally pasted in.
Is there a way to share the code of these common methods ? I see two possibilities:
1) either one copy of code truly shared in memory as in a special maintenance object of methods
or
2) written once in a block of code but allocated many times as needed by each view.
Which of these is the correct path or what is the correct path, and HOW would it be implemented in the most simple manner ?
Kindness pls, new coder in the room.
Thanks.
-Ric
Note: This is an old question/answer reflective of Apple practices at the time, and answered for a new coder looking for a simple solution they can understand (as requested in the question). There are better and more testable ways to achieve this, using composition.
The best way to achieve what you want is to create a common parent class for your view controllers. So instead of inheriting directly from UIViewController, each of your custom classes will inherit from SomeFeatureViewController (where SomeFeature describes the common feature provided), this class inherits from UIViewController. Now, each of your actual view controllers will inherit from SomeFeatureViewController and any common methods (also any common instance variables used by these methods) can be placed in this parent class.
#interface SomeFeatureViewController : UIViewController
{
int common_iVars;
}
- (void)commonMethods;
#end
#interface ActualViewController : SomeFeatureViewController
{
int specific_iVars;
}
- (void)specificMethods;
#end
The way I see it you should do a class with all the common methods and then subclass it. Say you have MyCommonViewController : UIViewController and then for each different view controller do MySpecificVIewController : MyCommonViewController
As well stated by jhabbott, a subclass of UIViewController is one good solution.
If that's not an option (e.g. you can't change the class hierarchy), another option is to create a category on UIViewController to add the methods and properties you need. This will make your methods available on every UIViewController, including all the standard subclasses, without any extra work on your part. With this solution you cannot directly add ivars, although you can fake it up well enough using associative references.
Well, what I ended up doing was to create a Singleton object and put all my common methods there. This meant that all my View Controllers could utilize the common methods of the Singleton. Maybe this is a bit too open if the project was being developed by a team of programmers but as it is just me I know that all the controllers have similar requirements in processing. So the Singleton approach seemed to work.
It also fit the project because at the time of the question all the View Controllers had been created and to make them a subclass of a parent class seemed to be a retrofit, though I agree that if part of an initial design, it may be a better approach. I do thank the 3 who gave the time to answer.
I'm looking at the source for: https://github.com/intabulas/ipivotal/blob/master/Classes/iPivotalAppDelegate.m
It looks like the "main" file for an iphone app, since it has a reference to the UIApplication, am I correct?
How is it that there is a .h file and in the .m file there is another block of code for the #interface with the same name?
I guess its allowed to redefine or continue the declaration of an interface?
You're basically correct, -[<UIApplicationDelegate> applicationDidFinishLaunchingWithOptions:] is the entry point for an application's custom code (the real entry point is actually UIApplicationMain(), but I wouldn't try re-implementing that if I were you).
The "second #interface" in the .m file is a category, which allows you define extra methods that aren't defined in the class's main interface. This can be used either to break a class over multiple files, to add functionality to an existing class or (as here) to keep some method definitions private.
In general, yes, the AppNameAppDelegate class is where you put all the application-level code.
What happens below the covers is that the main() function calls the Cocoa framework's initialization function, which loads a NIB that contains the app delegate. The UIApplication object (supplied by the framework) will invoke methods of the app delegate at appropriate times.
You can continue defining the #interface in the .m file in a private category, this is commonly done to have private methods and properties you do not wish to expose.