this is my class
#import "Year2011.h"
#implementation Year2011
- (void)Men:(double)speed{
if (ramspeed <= 180000) {
cal = 0;
}
here i have HelloViewController class how can i call Year2011 class and Men mathod.
now i tried like this.
#class Year2010;
IBOutlet Year2010 *Year2010;
calling
double speed=([anualIncome.text doubleValue]);
[Year2010 Men:income];
this one is showing unrecognized selector sent to classerr.guide me i'm new to objective c.
[Year2010 Men:income];
From the code you've shown us, the Year2010 class doesn't have a method Men:. Why would you expect to be able to call it?
Maybe change the type of the variable Year2010 to Year2011?
Also, dear god, don't name your instances the same as your classes. This will be impossible to read and understand when you come back from lunch, let alone months from now.
You are mixing up Class name and Instance name. You also seem to have problems understanding the scope of an instance.
-1- change your instance name to lowercase initial - that is IBOutlet Year2010 *year2010;
-2- change your method names to lowercase initial - that is - (void)men:(double)speed
The compiler currently assumes that Men is a static class method, but you never defined it as such, hence the error.
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).
Actually I am from java background and I am learning objective c.I am very confused about strange behaviour of objective C."Please Read 3rd Question its important one."
Questions are provided in sequence so please give answers in sequence as its understandable to me and others.
Question 1
I have two classes derived from NSObject: A and B:
#interface A : NSObject
#end
#interface B : NSobject
-(void)display; // It displays "I am class B"
#end
Now if I do this:
A *a = [[B alloc]init]; // Show warning not error (it must be illegal)
[a display]; // prints "I am class B"
It calls the display method of class B. I don't think that it should happen because:
A doesn't have the method display. By polymorphism.
This could be a security threat as I am creating reference of any class and passing object of any another class and accessing data by it.
There could be design issues as Dog class instance gets an object of Printer class and now i am calling print method on Dog instance.
I have reference of NSArray and passed object of NSMutableArray and now i am calling NSMutableArray method on this instance.
[nsarr addObject:#:abc]; //Looking very odd
Question 2
If I have Foo protocol and if any class is not confirming it. It should not be allowed to get object of that class in protocol reference.
#protocol Foo
#required
-(void)abc;
#end
If i call:
id<Foo> obj= [[B alloc]init]; // Shows warning ignore it for now as it must be illegal also
[obj display]; // It will call display method which should be illegal
It should not happen, as B is not conforming to protocol Foo and obj is taking B object and calling B instance method. I think its very bad because of polymorphism and security
Question 3
If my class has a class method which returns an object of that class which is not autoreleased, the compiler shows warning. If I pass the object returned by that class (not conforming protocol) method to reference of protocol. (IT SHOULD BE AN ERROR).
id<Foo> obj = [Abc aClassMethodReturnsObjectWhichNotAutoreleased]; //show warning
It shows a warning which is good. Abc did not conform to the protocol Foo
BUT
id<Foo> obj = [NSArray arrayWithObjects:#"abc",#"def",nil]; // It does **not** show a warning as it will return autorelease object. NSArray doesn't conform protocol Foo
Why does the above assignment to the NSArray class not show a warning as it is showing in the previous example.
Thanks in advance.
EDIT
*Answer 3rd Question:*As NSArray returns id object which will allow to pass in "id obj" but in "aClassMethodReturnsObjectWhichNotAutoreleased" case the method returns "ABC *" pointer so that is why compiler giving warning in this case.
Question 1:
A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display]; //prints "I am class B"
Here you are using a static type A for the variable named a. You are then assigning a different type of object (B) to the variable.
Unlike java, Objective-C does not enforce the static typing requirement, however it does warn you when it is being compiled since the compiler detected a difference between the declared type and the actual type of the object. It happily stuffs the B object into your variable though, so a is now pointing to the B object that you created. Once the program is compiled and running (at run-time), A *a is treated the same as id a.
Another feature of Objective-C is that you can send any message to any object at any time. This is part of the dynamic nature of Objective-C. Obviously there are cases where sending the wrong message to an object can cause bad things (tm) to happen so you need to ensure that you only send appropriate messages. There are various functions that can test the class of an object at run-time, or even test to see if it is able to handle a particular message before you send it in order to prevent the bad things. If you are using static typing (like in this example) then the compiler will issue warnings to tell you that you may have made a mistake and should review the code.
Question 2:
This is actually very similar to question 1. The compiler is warning you that you are assigning what appears to be an incorrect value to the variable, however at run-time you can send any message to any object, so it will work on the actual object instead of the "expected" object from the type declaration.
Question 3:
Good question. I would have thought that you would get a warning there too. Maybe someone else can help out on that. My first thought is that this is a bug and should be reported as such, but there may be a reason for it that I'm not aware of....
Objective-C and Java have very different type rules, as you have discovered.
Java is strictly statically typed, which means that types must match, and you can never make an assignment that is not allowed by the type conversion rules.
Objective-C is dynamically typed with optional static types. You can break out of the type system at any time. For some cases, the compiler will emit warnings, but it is still allowed.
This is the reason why you are seeing the behavior. Objective-C is not broken, it just have different rules than the ones you know from Java.
Apple has a lot of documentation of the specific rules, perhaps you would want to read Enabling Static Behavior.
Here are some more resources about dynamic vs static typing for you:
Dynamic type languages versus static type languages and What do people find so appealing about dynamic languages?
A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display]; //prints "I am class B"
Because you initialized variable from B class that have display property.
It's correct
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.
I am not able to find out why am I getting unnecessary warnings like:
"Method 'someMethod' not found"? Though at run time it is executing this method and I am getting the desired results. FYI... The called method resides in separate class which i have already imported in my class.
Usually one of two reasons:
1) You haven't casted the object that you're calling that method on correctly.
[(UITableView*)myTableView setDelegate:self];
2) The method that you're calling may not be in your custom Class' (public) #interface
#interface MyCustomClass : NSObject {
}
- (void)doSomethingReallyImportant;
#end
If you are trying to do something to an object, did you cast your object to the object's class?
If you are trying to access a method in your implementation of a class, do you have that method declared in your .h?
Then you have probably not put that method in the class' #interface. You should if it is a public method.
Being able to compile without warnings is a good thing.
I'm making a game for the iPhone, and I have a class called Robot.
Then I have a class called View, which renders everything.
I want to send a copy of my Robot, which I defined in my ViewController, and I send it to gameView (which is View *gameView), like this:
robot = [Robot new];
[gameView setRobot: [robot copy]];
I tried to make a copy but that didn't work, I could also do it with a pointer to Robot (&robot) but sometimes it just crashes ?
I tried this in my View.h #interface definition:
#property (copy) Robot* robot;
but I get the error
/RobotsAdventure/Classes/View.h:24: error: setter '-robot' argument type does not match property type
:/
Help? I'm pretty new at this, heh.
In order to copy an object, its class has to implement the NSCopying Protocol.
See Memory Management Programming Guide for Cocoa
The simplest way to accomplish what you want is:
View.h
#import "Robot.h"
#property(nonatomic,retain) Robot *robot.
Then set it like so in the view controller:
// myView is of class View.h
myView.robot=self.robot;
By the way, naming a class "View" is simply asking for a naming collision at some point. Worse, you'll never remember what the class does months down the road when you come back to it. Neither will you be able to search for it. Instead use a highly descriptive name e.g. RobotDisplayView_MyProjectName. With autocomplete it doesn't take any longer to type out than a short name.