There is a problem, I just installed cocos2d for iPhone.
The first problem was that it wasn't recognizing any header like CCDirectory.h for example.
So I turned on user search paths in the project, but this way I could just import the header and have an object pointer without getting any warning, but methods aren't recognized.
It's hard to explain, so see this code:
Header:
#import <UIKit/UIKit.h>
#import <CCMenuItem.h>
#import <cocos2d.h>
Inside applicationDidFinishLaunching:
CCMenuItem* item; // This does not give a warning, except for the "unused variable"
// But the class is recognized
[CCMenuItem setFontName: #""]; // Warning
The warning is:
Class method '+setFontName:' not found (return type default to 'id')
And it doesn't recognize any other method, just NSObject's methods.
Are you sure the methods you are calling exists in that class? CCMenuItem doesn't contain a static method named setFontName. Try changing CCMenuItem to CCMenuItemFont.
[CCMenuItemFont setFontName: #""];
Related
I've looked at a lot of posts on this and it usually seems to revolve around missing an import in the .h or the .m
In my case I am trying to import a swift objective C function but I believe the .h, .m and swift files are configured correctly (as is the generated swift-header).
My Swift class is flagged as #objc and extends NSObject.
When I import the class in the .h using forward declaration, and in the .m using the MyApp.h import, it can see the class. However, it cannot see the method I want and it gives me the error Receiver type 'class' for instance message is a forward declaration.
When I check the generated header file, the method is generated there (and the method is flagged as an #objc and returns an #objc compatible value).
Can you suggest what might be causing this issue?
Here is a reference of what my code is like:
Swift
#objc class ObjcHelper: NSObject {
#objc static let shared = ObjcHelper()
#objc public func getObjcFromNSString(nsString: NSString) -> ObjcType {
return ObjcType()
}
}
In the .h for the objective c file I want to use it in:
#class ObjcHelper
And in the .m I am importing the app header
#import <App-Swift.h>
When I try to use the code in the .m file the compiler can see this part fine:
[ObjcHelper shared] // Compiler sees this fine!
But if I try to call the method it doesn't autocomplete or find it even if I type it in.
If I look in the generated header, I see the method is here like so:
SWIFT_CLASS("_TtC7ObjcHelper")
#interface ObjcHelper : NSObject
SWIFT_CLASS_PROPERTY(#property (nonatomic, class, readonly, strong) ObjcHelper * _Nonnull shared;)
+ (\ObjcHelper * _Nonnull)shared SWIFT_WARN_UNUSED_RESULT;
- (enum ObjcType)getObjcFromNSStringWithNsString:(NSString * _Nonnull)nsString SWIFT_WARN_UNUSED_RESULT;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
#end
The code I expect to work that doesn't is as follow (and which generates the error):
ObjcType value = [[ObjcHelper shared] getObjcFromNSStringWithNsString: #"abc"]];
The issue is rather nuanced but it seems to have been solved.
In my project there are a number of targets and for the ObjcHelper it wasn't targeting one of the targets. I believe what was happening is that even though the bridging objective c helper file was created, there was an issue with a reference missing a 'required' target owner and this error propagates forward as not being able to find the class.
So if you are getting this issue, check to make sure that the Swift class you are trying to bring into objective-c has its target membership set to all the targets it needs (otherwise you might get a misleading error about forward class declaration).
Please see below edit for current (minor) issue
I'm trying to call methods (methods right, not functions?) "between" the MainViewController.m and the FlipsideViewController.m -- from one file/class to another.
I guess this is what's often referred to as "Call methods from another class". There are plenty of such questions around, I know, but I just can't get it to work properly.
In my case, I have several user defined methods/functions in both above mentioned files. Sometimes, I need to call a method from within the FlipsideViewController.m that lies within the MainViewController.m File:
// in MainViewController.m
- (void) calculateDays {
//executes caluculations
// inserts data into labels, etc
}
If I want to call this function simply from within the same file, I just do:
[self calculateDays];
That's easy, however, I want to call this function from within the FlipsideViewController.m file too, as well as vice versa. So how do I do this? This, this and this questions sort of answer it but it doesn't quite work to me. I'll explain why in just a second.
This is what I've tried and think should work:
MainViewController *mvs = [[MainViewController alloc] init]; //alloc init MVC
[mvs calculateDays]; //call "external" function
It gives me the error: "Unknown type name MainViewController". So I assume I have to include/import it somehow for it to work (just like in javascript or PHP). So I include it in the FlipSideViewController.m class:
#import "MainViewController.h"
Great no errors so far. Then I try to compile/build it and runs into another error:
"clang: error: linker command failed with exit code 1 (use -v to see invocation)"
"ld: 3 duplicate symbols for architecture armv7s"
This leads me to think that importing the MainViewController like that isn't the way to go as I then import lots of other stuff that may interfere with some code in the FlipSideViewController class.
I've tried similar solutions but nothing seems to work. Can anyone please explain to me what I'm doing wrong, and perhaps how to do this properly: Call methods between MainViewController.m and FlipsideViewController.m and vice versa.
The proposed solution by H2CO3 did solve most of the issues (XCode bugged for a while and give me random errors which forced me to rebuild the entire project) but there's still this one thing that doesn't quite work: change the content of a UILabel (UIOutlet). Please see if anyone of you can help me with this:
When the method is called from within self (i.e. [self calculateDay]), the value is successfully inserted into the UILabel. When called from FlipsideViewController, the value to be inserted exists and is processed successfully, but can't be inserted into the UILabel. Please se below.
Some loggings:
//method called from within self on viewDidLoad: [self calculateDay];
Processed value to update label with: 26
New value in outlet after having been inserted: 26
//method called from another (FlipsideViewController) class file: [mvs calculateDay];
Processed value to update label with: 26
New value in outlet after having been inserted: (null)
/*
This doesn't work either from that external file:
[[mvs LabelName] setText:#"Hello, update label!"]; no errors but no display either
*/
If you import the header instead, that should give you all the necessary declarations, but you won't have "duplicate symbol" linker errors. This is a "standard"/common practice for writing (Objective-)C code.
#import "MainViewController.h"
^
".h" instead of ".m" -+
(layman's terms) In Objective-C you can only use objects that each file knows about. In this example you are trying to use a MainViewController in the FlipsideController.m file. The FlipsideController.m has no idea what a MainViewController is, so it throws errors because it doesn't know what it is or how to use it. You have two options for telling the Flipsidecontroller what a MainViewController is, you can import the header (#import "MainViewController.h") which will give you full access to everything defined in the FlipSideController.h. (You should probably never import a .m unless you really know what your doing) You can also create a forward declaration - #class FilpsideControllerin the .h and import the file in the .m. This is useful to avoid circular imports etc.
Say we have parent class
ParentViewController.h
#interface ParentViewController
....
#end
ParentViewController.m
#interface ParentViewController()
- (NSArray *)selectedItems;
#end
#implementation ParentViewController
.....
#end
And then we subclass it
ChildViewController.h
#interface ChildViewController : ParentViewController
....
#end
ChildClassViewController.m
#implementation ChildViewController
- (void)doSomething
{
// XCode Warning Flag on this line
NSUInteger count = [self selectedItems];
.....
}
XCode will set Warning flag at the commented line and says that "Instance method '-selectedItems' not found (return type defaults to 'id').
Yes I know that in ObjC there is no such thing as private methods, but using an empty category kind of gives the ability to do so. But somehow it does not get inherited by subclasses.
I usually fix it by moving the method from ParentViewController.m to ParentViewController.h. This feels weird, I loose the ability to make the method private just because I need to subclass it.
Now my question is:
Why does the parent subclass cannot find those methods that is declared in its category at the .m file?
Is there a way to remove the Warning Flag but without losing the ability to keep the method private.
Hopefully someone with more experience will be able to help explain this annoying issue.
First, note that your "empty category" isn't a Category at all, it's a Class Extension. Class Extensions very similar to categories but they're new in Objective C 2.0, and they differ slightly in their use. Primarily, the compiler will warn you if you don't implement a method in a Class Extension, but it won't with a Category. Anyways, on to the issue at hand...
Privacy in Objective-C is all about visibility. If the compiler can't see see the declaration of a method that's being used, you'll get a warning. Note that if you were to implement your subclass in the same file as your Class Extension, the compiler won't warn you because it can see the declaration.
Therefore, If you want to use "private" methods in subclasses, you just need some way of showing the compiler that those methods exist. My favorite pattern is to declare the private methods in a Category in a separate file (like MyClass_private.h). You then only import that interface into the implementation files of the base class and any derived classes that need to see it.
I have a solution, but generally I would advise against it. if you compile the file with -w (suppress all warnings), the warning goes away. I do not know if there is a specific warning flag for this message, if there was, you could use #pragma GCC diagnostic ignored "-Winstance-method-not-found", but I can't find it, sorry.
In my iOS5 app, I have NSObject States class, and trying to init it:
states = [states init];
here is init method in States:
- (id) init
{
if ((self = [super init]))
{
pickedGlasses = 0;
}
return self;
}
But there is error in the line states = [states init];
receiver type "States" for instance message is a forward declaration
What does it mean? What am I doing wrong?
That basically means that you need to import the .h file containing the declaration of States.
However, there is a lot of other stuff wrong with your code.
You're -init'ing an object without +alloc'ing it. That won't work
You're declaring an object as a non-pointer type, that won't work either
You're not calling [super init] in -init.
You've declared the class using #class in the header, but never imported the class.
FWIW, I got this error when I was implementing core data in to an existing project. It turned out I forgot to link CoreData.h to my project. I had already added the CoreData framework to my project but solved the issue by linking to the framework in my pre-compiled header just like Apple's templates do:
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#endif
I got this sort of message when I had two files that depended on each other. The tricky thing here is that you'll get a circular reference if you just try to import each other (class A imports class B, class B imports class A) from their header files. So what you would do is instead place a forward (#class A) declaration in one of the classes' (class B's) header file. However, when attempting to use an ivar of class A within the implementation of class B, this very error comes up, merely adding an #import "A.h" in the .m file of class B fixed the problem for me.
I was trying to use #class "Myclass.h".
When I changed it to #import "Myclass.h", it worked fine.
If you are getting this error while trying to use Swift class or method in Objective C: you forgot one of 2 steps Apple defined on this diagram:
Example:
Error shows up in your Test.m file:
Receiver 'MyClass' for class message is a forward declaration
In Obj-C files:
Step 1: check that Test.h has
#class MyClass;
Step 2: find *-Swift.h file name in Build Settings (look for Objective-C Generated Interface Header Name). Name will be something like MyModule-Swift.h
Step 3: check that Test.m imports the above header
#import <MyModule/MyModule-Swift.h>
In Swift file:
Ensure MyClass (or it's base class) inherits NSObject class.
Ensure #objc is before each method you want call from Obj-C.
Also, check Target Membership section (in File Inspector).
You are using
States states;
where as you should use
States *states;
Your init method should be like this
-(id)init {
if( (self = [super init]) ) {
pickedGlasses = 0;
}
return self;
}
Now finally when you are going to create an object for States class you should do it like this.
State *states = [[States alloc] init];
I am not saying this is the best way of doing this. But it may help you understand the very basic use of initializing objects.
Check if you imported the header files of classes that are throwing this error.
Make sure the prototype for your unit method is in the .h file.
Because you're calling the method higher in the file than you're defining it, you get this message. Alternatively, you could rearrange your methods, so that callers are lower in the file than the methods they call.
There are two related error messages that may tell you something is wrong with declarations and/or imports.
The first is the one you are referring to, which can be generated by NOT putting an #import in your .m (or .pch file) while declaring an #class in your .h.
The second you might see, if you had a method in your States class like:
- (void)logout:(NSTimer *)timer
after adding the #import is this:
No visible #interface for "States" declares the selector 'logout:'
If you see this, you need to check and see if you declared your "logout" method (in this instance) in the .h file of the class you're importing or forwarding.
So in your case, you would need a:
- (void)logout:(NSTimer *)timer;
in your States class's .h to make one or both of these related errors disappear.
my .h file is as follows
#import <Foundation/Foundation.h>
#interface MyClass : NSObject {
}
- (void) addWidget: (Widget*)aWidget;
#end
For sake of example, Widget is just some simple class that only holds a couple of strings. Apparently, either i'm doing something wrong or am just spoiled by Java / C# because when I try building, the compiler tells me that i can't use an object as a parameter to a method.
Does anyone know what I'm doing wrong? Or do objective-c methods not accept complex types? (say it ain't so!)
[UPDATE]
Ok this is odd.. but I just selected "clean" from the Build menu and now the error went away.. ah.. such misdirection on my part.
The only thing wrong with that code is that Widget isn't declared anywhere. You should either #import "Widget.h" or put #class Widget; before the type is used.