project-Swift.h compiler errors - objective-c

Im having an issue with the auto-generated Project-Swift.h file when I try to import it.
In the -Swift.h file:
SWIFT_CLASS("_TtC7ProjectName20InviteToComposer")
#interface InviteToComposer : NSObject <MFMessageComposeViewControllerDelegate *>
- (nonnull instancetype)initWithRecipient:(NSArray<NSString *> * _Nonnull)recipient name:(NSString * _Nonnull)name OBJC_DESIGNATED_INITIALIZER;
- (void)messageComposeViewController:(MFMessageComposeViewController * _Nonnull)controller didFinishWithResult:(MessageComposeResult)result;
#end
when attempting to compile, i get two errors from this class:
"unknown type name 'MFMessageComposeViewControllerDelegate'; did you mean 'MFMessageComposeViewController'?
and "expected a type" in regards to "(MessageComposeResult)"
I tried including #nonobjc in front of the class and function names so that it wouldn't include them in the -Swift.h file, but apparently you can't do that to a class and the function itself that has the error gives me
"Type 'InviteToComposer' does not conform to protocol 'MFMessageComposeViewControllerDelegate'" then states "protocol is not #objc but requires it."

In your -swift add #protocol MFMessageComposeViewControllerDelegate before your class declaration.
It's an apple "you probably should be using swift/we don't care enough about you to fix it" thing.
Also thing with my fix is that every time you clean the project or switch a build device, it will clear up the code and you have to add it again.
A permeant workaround is create a sub protocol of the MFMessageComposeViewControllerDelegate in objective-c and reference it from there.

Related

Mutual include breaks types

I have two classes, Entity, and EntityHandler.
EntityHandler has a method, AddEntity. This method adds the Entity to an NSMutableArray.
Entity has a method called subscribe. It assigns a reference to EntityHandler to a variable for later usage.
Upon the inclusion of both header files in each other the project breaks. For example,
-(void) addEntity: (Entity *) mob;
returns the error
Expected a type
How can I fix this?
You're looking to employ forward declarations for your ObjC types, in order to break the cyclic header dependency.
It would look something like:
// EntityHandler.h
#class Entity; // << the forward declaration. not #import.
#interface EntityHandler : NSObject
-(void) addEntity:(Entity *) mob;
#end
This tells the compiler that there is an ObjC class named Entity.
Then you #import when you need more than a typename (likely in EntityHandler.m).

Expected identifier or '(' error on private instance variables

I'm using Cocos2D for the first time and trying to set up my initial scene. I just followed this tutorial http://www.raywenderlich.com/15267/how-to-make-a-platform-game-like-super-mario-brothers-part-2 and got it working perfectly. I even copied the code for the GameLayer over to use as a template for my Level0, changing the appropriate value to fit.
I'm getting an error in my private interface `Expected identifier of '(' before '{' token
#import "Level0.h"
#import "Player.h"
#interface Level0 ()
{ /// this is where I'm getting the error
CCTMXTiledMap* map;
Player* player;
CCTMXLayer* walls;
CCTMXLayer* portalWalls;
BOOL gameOver;
}
#end
#implementation Level0
....
I've coded private interfaces a million times and it even looks identical to the tutorial project. Does anyone know of reasons why this would flag an error?
The bad syntax is actually in one of those header files. You may be able to track it down by compiling the troublesome header itself rather than just including it. Comment out the #includes, then in Xcode's file inspector change the "File Type" from "Default - C header" to "Objective-C" source:
and add it to your target as a member:
Then compile. You might get some linker errors too, but you should also get this same "Expected identifier" error, now pointing somewhere near the actual site of the problem.
Don't forget to switch those settings back afterwards.

Method parameter wihout type?

What did I do here? Can method parameters be typeless?
In a recent project which works fine, the App is in the store already - no issues so far, I did the following in a .h file:
#property (strong, nonatomic) NSManagedObject *myPerson;
- (HKPersonPicker*) initWithPerson:person;
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate;
I meant to do it this way but did not:
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person;
- (HKPersonPicker*) initWithPerson:(NSManagedObject*)person delegate:(id <HKPersonPickerDelegate>)delegate;
The corresponding part of the .m file:
- (HKPersonPicker*) initWithPerson:person
{
self = [super init];
if(self){
self.myPerson = person;
}
return (self);
}
- (HKPersonPicker*) initWithPerson:person delegate:(id <HKPersonPickerDelegate>)delegate
{
self = [self initWithPerson:person];
if(self){
self.delegate = delegate;
}
return (self);
}
As you can see I did not do anything special with this person object, just assigned it to the property myPerson. As I did not call any of the object's methods or accessed its data, the compiler did not need to know anything about that object. But what is it from the compiler's point of ivew? Type id? Just something? Is there any default type?
As you see, I do not have any real problem. I am just curious. Hope this question does not break any SO rule.
With C the default type is int, but with Objective-C it's id.
Missing type declarations in methods default to id. IIRC, you can see a fair number of methods without return types in Apple's runtime library.
There is no definitive problem with what you are doing, but its not really kosher at the same time. You should still have a type declaration for the sake of clarity, and maintaining good and consistent Cocoa-like code styling.
So it should really be like:
- (GSPersonPicker*) initWithPerson:(id)person;
And you should really change the property declaration:
#property (strong, nonatomic) id *myPerson;
If that is not changed, then your code is confusing. You KNOW the type that will be coming in. So let the compiler help you with meaningful warnings/errors by using types. You should also probably be using the type 'HKPerson' or whatever you have named your entity, so the compiler doesn't think its ok for you to pass in an 'HKPlace' (they will both be of type 'id' and 'NSManagedObject', which does you no favors)
More importantly, you should not be using the dynamic type (id) unless you have a reason. The compiler is there to help you. Errors and warnings are your friend, they tell you that you messed up, not the computer. When you use 'id', the compiler just goes, Oh, anything can go in here!!! And it will not detect an error where you sent that method a type that will break everything.
Now lets say that you are going to use polymorphism. IE, Lets declare a generic protocol for multiple classes to adhere to, which defines our person:
#protocol GSPerson
-(NSUInteger)age;
#end
So now lets define a couple classes, and have them subscribe to the protocol (the GSPerson thats between carrots markdown is killing me atm lol):
#import "GSPerson.h"
#interface GSSpecialPerson <GSPerson>
// code
#end
#import "GSPerson.h"
#interface GSWeirdPerson <GSPerson>
// code
#end
Then lets redefine our method signature to adhere to the protocol:
- (GSPersonPicker*) initWithPerson:(id<GSPerson>)person;
And our property declaration:
#property (strong, nonatomic) id <GSPerson> *myPerson;
Now the compiler knows that anything i pass into that method should conform to the GSPerson protocol I defined above (ie they need a method that returns the persons age). If i try to pass anything else in, it will throw compiler warnings, WHICH IS GOOD.
Even better, it will throw warnings on your polymorphic classes if they are missing their required methods.

Newbie question -multiple parameters

I am trying to implement a private method which takes an NSMutableDictionary and a Player object as its parameters. As it is a private method, the only place that it exists is in the ".m" file.
It is declared as
-(void) incrementScore: (NSMutableDictionary*) scoreboard forPlayer: ( Player* ) player {
and I call it as follows :
[ self incrementScore:deuceScore forPlayer:p];
However,it won't compile - I get
may not response to message -incrementScore:forplayer
I'm not sure where my error lies - do I need to declare the method in the ".h" file, or elsewhere in the ".m" file, or have I just got the syntax completely wrong?
The compiler needs to find a declaration for your method somewhere before you use it. This be done in three way:
Declare the method in the (public) #interface for the class in its .h file .
Declare the method in a class extension (a semi-private #interface, usually at the top of the .m files).
Define the method somewhere in the #implementation before your first use of it.
This is only a warning not a compile error... (if you changed preferences to treat all warnings like error it'll be a compile error).
Probably the line calling the method is above (in the .m file) the declaration method. Move the method just below #implementation directive, or above the method with the calling line. The warning/error should disapper.

"warning: '<CLASS>'may not respond to '<[-|+]FUNCTION>'" Objective C/Xcode Compiler Warnings

I figured this one out, yet thought it worthy of its own question answer pair.
I'm new to Xcode and Objective C, and getting to know its varied eccentricities. For instance, the compiler warning "warning: ''may not respond to '<[-|+]FUNCTION>'" appears when I try to compile the following code, which all appears in my implementation file since I desire to create a private static utility function for this class:
// Here's the function declaration in the implementation file (I don't want it in the header)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
...
// Later on, here's a call to that same function:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
...
When compiled, this produces the warning above. Next, I'll post my resolution. Feel free to contribute your ideas as well!
If what you really want is a private method, that is, you don't want the method to be in the header file, then I like to use a Category to accomplish this. I just define the category above my implementation.
// Enforce private methods by putting them in a category.
#interface YourClass (PrivateMethods)
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse;
#end
#implementation YourClass
+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
...
}
#end
Now, it doesn't matter what the order of your methods in your implementation is which is nice so you can properly "#pragma mark"
The problem is with your method call:
[CnaCalendarController authenticationredirectTo:formActionURL WithRelayState:relayState AndSAMLResponse:SAMLResponse];
Note that the first 'r' in "authenticationredirectTo:..." is lower case, but you've declared it as "authenticationRedirectTo:...", with a capital 'R'. Given that, it's no surprise that the compiler complains that it can't find a declaration for the method you're calling. The code will likely crash on that line, too, since the method with the lower-case 'r' isn't defined.
What i think the problem is, you are declaring the function after the call to this function. And while compiling it just could not find it.
OK, here's my solution as promised:
Problem 1: Xcode will generate erroneous warnings when a function declaration or implementation appears after the call in processed source code. In my case, they are in the same file so I was able to move to function implementation above the call.
Also check the order of your imports to ensure such a function is imported before an import that calls it. I didn't see this but saw other posts where this was the case.
Problem 2: It seems Xcode has some limitations on the LENGTH of function names. Shortening my function name as shown in the snip below resolved the issue. I'll obviously pick something more meaningful.
// Here is the warning function commented out and a *shorter* name in place.
//+(void)authenticationRedirectTo:(NSURL *)url WithRelayState:(NSString *)relayState AndSAMLResponse:(NSString *)samlResponse {
+(void)X:(NSURL *)url Y:(NSString *)relayState Z:(NSString *)samlResponse {
Hope this helps you with your troubles. Don't forget to vote this answer if it is useful.