Reputation: 7776
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
Upvotes: 2
Views: 5773
Reputation: 18363
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!
Upvotes: 2
Reputation: 11841
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.
Upvotes: 1