Reputation: 1928
I have the following setup in my app:
A UITabbarController with 3 viewcontrollers, with embeded UINavigationControllers. The 3 viewcontrollers inheret/superclass from a UIViewController subclass called "SVC", in order to implement elements which is used in all of the 3. viewcontrollers and prevent duplicated code. In this "SVC" class I have setup a delegate called "dismissDelegate" (which is used to tell when the tabbarcontroller is dimissed).
@protocol ModalViewDelegate <NSObject>
- (void)didDismissModalViewFrom:(UIViewController *)viewController;
@end
@property (weak, nonatomic) id <ModalViewDelegate> dismissDelegate;
My other viewcontroller which segues to the UITabbarController, implements this delegate in order to get information about, when the tabbarcontroller is dismissed.
the SVC class notifies the delegate of dismissal of the tabbar like so:
[self.dismissDelegate didDismissModalViewFrom:self];
I now want to set the delegate of all the viewcontrollers which inherts from the SVC class (all the tabbar viewcontrollers) to this viewcontroller and I try to do this via the prepareToSegue method like so:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"ToTab"]) {
UITabBarController *tabBarController = segue.destinationViewController;
for (UINavigationController *navController in tabBarController.viewControllers) {
for (UIViewController *vc in navController.viewControllers) {
_SubclassVC = (SVC *) vc.superclass;
_SubclassVC.dismissDelegate = self;
}
}
}
}
But I get the following error:
+[SVC setDismissDelegate:]: unrecognized selector sent to class 0xbca68
My questions:
Upvotes: 0
Views: 1094
Reputation: 14068
+[SVC setDismissDelegate:]: unrecognized selector sent to class 0xbca68
See the +
The plus sign idicates that you are calling a class method. You must have tried setting a class variable by a setter. But a property represents instance variables only. Therefore the setters and getters that are automatically generated are intance methods only. (starting with a minus - in error messages like this).
And that is what you do:
_SubclassVC = (SVC *) vc.superclass;
_SubclassVC.dismissDelegate = self;
For whatever reason (probably by mistake or misunderstanding) you take the vc instance and get its superclass
. vc.superclass
returns a class object, not an object (meaning not an instance, in Obj-C class objects are objects too).
Then you typecast it to (SVC *)
just to stop the compiler from throwing errors (or warnings - not sure).
Well, I guess that you wondered yourself why you have to typecast it at all. That's the reason :)
Next, you assign self
to a property dismissDelegate
. The compiler does that because you typecasted it to SVC* which does have a property dismissDelegate
. The compiler will actually call the setter setDismissDelegate
as usual in contructs like this.
BUT at runtime the message (or selector) setDismissDelegate: is not sent to an SVC*
but to a class
object. And the class SVC
does not have a method (or selector) +setDismissDelegate:
and therefore cannot resolve the message. And that is exactly what the error message is telling you.
All right, now we get to your questions. 1. Well, it is not the way I would do it, but that is certainly one way of achiving it. 2. If you want to stick with that unusual approach then do this minor change and you will get rid of the error:
for (SVC *vc in navController.viewControllers) {
vc.dismissDelegate = self;
}
There is no point in fetching the superclass object. If you cannot access the property of a superclass then you did something wrong with the inheritance chain. If you want to be on the save side:
for (UIViewController *vc in navController.viewControllers) {
if (vc isKindOfClass:[SVC class]){ //BTW, this is good usage of the class object
SVC *svc = (SVC*) vc;
svc.dismissDelegate = self;
}
}
Upvotes: 3