warning: incompatible Objective-C types assigning superClass to subClass - objective-c

Assume a valid super class, and a valid subclass ie the classes work.
the following line in a constructor of the subclass
self = [super init] ;
throws the following warning
// warning: incompatible Objective-C types assigning 'struct Animal *', expected 'struct Cat *'
Any ideas on how to fix this and remove the warning ?
Cheers

Do you provide a custom init-Method in your superclass?
Check the return type of this method. Is it (Animal *)? If so, change this to (id).
Init methods should return (id)

Related

Protocol or class specific selector in objective-c

Using a selector to call a method that exists in more that one class (but with different signatures on return or argument types) causes an Multiple methods named [method name] found... error.
This has been already settled in other questions:
Defeating the "multiple methods named 'xxx:' found" error
Issue with "Multiple methods named...."
Multiple methods named "count" found with mismatched result, parameter type or attributes
A related problem happens if the repeated method is in a protocol. Having a strongly typed protocol object is still ambiguous for the compiler since the object could also be an instance of other classes implementing the same-ish signature method:
#protocol ExistingMethodProtocol <NSObject>
// This method also exists in UIView, but with a different return type
- (NSString*)contentMode;
#end
#interface ImplementingClass : NSObject <ExistingMethodProtocol>
#end
#implementation ImplementingClass
- (NSString*)contentMode {return nil;}
- (void)problematicCall
{
// Multiple methods named... error
[self performSelector:#selector(contentMode)];
id<ExistingMethodProtocol> idOfProtocol = self;
// Multiple methods named... error too, even casted
[idOfProtocol performSelector:#selector(contentMode)];
}
#end
An alternative is to create the selector separately and then perform, thus bypasing the compiler check but causing a warning:
SEL selector = #selector(contentMode);
// Warning: PerformSelector may cause a leak because its selector is unknown
[object performSelector:selector];
What other alternatives could work here for checking and performing a method when a protocol has a method colliding with a same-ish signature?
my 2 cents. Use Runtime reference. In which case it bypasses the compiler warnings/error. Looks like there are several ways to do this, here is my solution.
#import <objc/message.h>
struct objc_method *method = class_getInstanceMethod([self class], #selector(contentMode));
id answer = method_invoke(self, method);
This should prevent errors from selectors in different protocols named the same. But I am a little unsure how this behaves with methods with different implementations in base and super classes.

objective C Warning that I Don't Understand

Can anyone explain to me why I get these warnings:
Conflicting parameter types in implementation of 'setCardsSelected': 'NSMutableArray *' vs 'NSUInteger' (aka 'unsigned long')
Conflicting return type in implementatin of 'setCardsSelected': 'void' vs 'NSMutableArray *'
I'm just trying to pass in an NSUInteger to a function. Why does this not work? Is my method declaration wrong? Thanks!
- (NSMutableArray *) setCardsSelected:(NSUInteger) index
{
if (!_cardsSelected) _cardsSelected = [[NSMutableArray alloc] init];
return _cardsSelected;
}
edit:
the problem is you have defined the property cardsSelected and the associated setter is setCardsSelected: (which is of course -(void)setCardsSelected:(NSMutableArray*)array).
You will have to change your method name (what abut selectCards:?) or declare your property with a different setter, like this:
#property ( nonatomic, strong, setter=setterSelector: ) NSMutableArray * cardsSelected
I think renaming your method is preferable.
Yes, your method declaration is wrong.
I guess you are overriding a method setCardsSelected: in a subclass; in the superclass (or adopted protocol) I guess it's -(void)setCardsSelected:(NSMutableArray*)array

Objective-C implicit conversion of obj-c pointer to autoreleasing id<protocol> error

I'm having a very specific problem, I'm working with a DAO (data access object) that takes varius states, these states are passed into an init method and are then used.
Now the problem that I'm having is that I can't seem to pass a concrete state into the init method, I always get an
implicit conversion of an objective-c pointer to __autoreleasing id is disallowed with ARC
The code:
-(DAOObject *)makeSpecificDataAccessObject{
SQLiteState* localstate = [[SQLiteState alloc] initWithTableName:#"TableName"];
DAOObject* specificDAO = [[DAOObject alloc] initWithLocalState:localstate]; //where error happens
return specificDAO;
}
#interface DAOObject : NSObject <SettingsListenerProtocol>
-(id)initWithLocalState:(id<StateProtocol> *)LocalState;
#end
#interface SQLiteState : NSObject <StateProtocol>
-(id)initWithTableName:(NSString *)tableName;
#end
Remove the star * in
-(id)initWithLocalState:(id<StateProtocol> *)LocalState;
id is already defined as a pointer to an instance of a class.

Suppress Xcode incompatible pointer type for subclass of UIViewController

I have a subclass of UIViewController called SurveyQuestion. I use an array of these for my app. I get the currently visible controller with this line:
SurveyQuestion *currentQuestionController = [self.navigationController visibleViewController];
Everything works, but Xcode gives me a warning of
Incompatible pointer types initializing 'SurveyQuestion *__strong' with an expression of type 'UIViewController *'
I know this is because visibleViewController returns a UIViewController, but it works because SurveyQuestion IS a UIViewController. Is there any way to suppress this error? Or should I be doing it a different way?
You can use cast like
SurveyQuestion *currentQuestionController = (SurveyQuestion *)[self.navigationController visibleViewController];

Semantic issue with unrelated object in Objective-C

I have a UIViewController subclass that implements a message to init the controller with a custom model:
- (id)initWithUser:(FacebookFriend *)user;
When I use this to init my controller:
ProfileViewController *profileViewController = [[ProfileViewController alloc] initWithUser:friend];
The compiler complains about sending a message to NSUserDefaults' message of the same name:
- (id)initWithUser:(NSString *)username;
warning: incompatible Objective-C types 'struct FacebookFriend *', expected 'struct NSString *' when passing argument 1 of 'initWithUser:' from distinct Objective-C type
I don't quite understand why it's notifying me of this as I don't think UIViewController inherits from NSUserDefaults anywhere. Is there a way to disable this error? Could this cause a problem? Should I just rename my class' initializer to avoid confusion?
The problem is you have an ambiguous selector. Because alloc returns the generic (for Objective C) type id, the call to initWithUser: has become ambiguous, and so it gets confused with the NSUserDefaults method initWithUser:. The compiler thinks you're trying to use that one.
You can remove the ambiguity by casting:
ProfileViewController *profileViewController = [(ProfileViewController*)[ProfileViewController alloc] initWithUser:friend];
Have you tried directly casting the result of -alloc? Something like this:
ProfileViewController *profileViewController = [(ProfileViewController *)[ProfileViewController alloc] initWithUser:friend];