Semantic issue with unrelated object in Objective-C - 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];

Related

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];

Warning "Instance method '-methodname' not found (return type defaults to 'id')" while it exist and works fine

I found some similar questions belonging this warning, but they are not answered or not really precisely asked.
My AppDelegate has an instance variable named AppModel* iVarModel.
The App Delegate has a declared Property and meanwhile even a separate getter for it, like:
AppDelegate.h
AppModel* iVarModel;
#property (nonatomic, retain) AppModel* iVarModel;
- (AppModel*) getAppModel;
AppDelegate.m
#synthesize iVarModel;
- (AppModel*) getAppModel {
return iVarModel;
}
In a different class
I like to access this via the singleton application object:
FarFarAwayClass.h
import "AppDelegate.h"
...
FarFarAwayClass.m
//get a pointer to the application object
UIApplication* thisApp = [UIApplication sharedApplication];
// get a pointer to the application's delegate
id<UIApplicationDelegate> theDelegateObject = [thisApp delegate];
// >(1)< access AppModel's property iVarModel
AppModel* iVarModel_byProp = [theDelegateObject iVarModel];
// >(2)< access AppModel's iVarModel via getter
AppModel* iVarModel_byGet = [theDelegateObject getAppModel];
Independently how I try to access it >(1)< or >(2)< it works, but I do get this warning:
Instance method '-iVarModel' not found (return type defaults to 'id')
Instance method '-getAppModel' not found (return type defaults to 'id')
Why does the compiler thinks those methods would not exist, even while he can use them correctly?
By the way it does make no difference if I skip the getter or the declared property I do always get this warning.
The compiler is warning you because you told the compiler this local variable 'theDelegateObject' is of type 'id'. In other words, you said it is "some NSObject that implements the UIApplicationDelegate protocol". You didn't say anything about it being an instance of your particular AppDelegate class.
If you do this instead the compiler will know what you're doing:
MyAppDelegate* theDelegateObject = (MyAppDelegate*) [thisApp delegate];
This gives the compiler the type information it needs to know that this object should respond to your own methods you wrote.
As for why this works fine as is at runtime, remember message passing is dynamic, the compiler doesn't need to bind to this method at compile time. It just dutifully writes the method call you asked for. At runtime, this works out because the application's delegate turns out to be an actual instance of your AppDelegate class.
Hope that makes sense?
I had a similar issue to this recently and discovered that (goodness knows how) my project had duplicate AppDelegate.h and AppDelegate.m files in different places. I was editing one and the compiler was using the other which meant it couldn't see the instance methods I was adding! Removing the duplicate files resolved the issue.
This error can occure if the instanciation of your class have the same name that the class itself
MyClassSample *MyClassSample = [[MyClassSample alloc] init];
To solve this you can simply modify the instanciation name ( M -> m )
MyClassSample *myClassSample = [[MyClassSample alloc] init];
I found it on my own. To let you know it and let others find the solution here it is:
As trying to be precisely I used:
FarFarAwayClass.m (1st version)
id<UIApplicationDelegate> theDelegateObject = [thisApp delegate];
Means providing the compiler with the information "I need a object here which adopts the protocol UIApplicationDelegate". But this seems to confuse the compiler. Just using id avoids the warning.
FarFarAwayClass.m (2nd version - to get rid of the warning named in original question)
id theDelegateObject = [thisApp delegate];
All warnings are gone :-)

warning: incompatible Objective-C types assigning superClass to subClass

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)