Class creation unrecognized selector - objective-c

I'm learning Objective-C.
I'm at the point of creating a simple class but when compiling, after the expected result, I get this errors.
2014-05-08 10:15:47.998 ClassCreation[978:903] This is a method call in the new object!
2014-05-08 10:15:48.007 ClassCreation[978:903] -[Employee setName:]: unrecognized selector sent to instance 0x10010c850
...
terminate called after throwing an instance of 'NSException'
(gdb)
Here it is the Employee.h
#import <Foundation/Foundation.h>
#interface Employee : NSObject
// properties
#property NSString *name;
#property NSDate *hireDate;
#property int employeeNumber;
-(void) someMethod;
#end
Here it is the Employee.m
#import "Employee.h"
#implementation Employee
// matching the method definition that is defined in the interface
-(void) someMethod {
NSLog(#"This is a method call in the new object!");
}
#end
Here it is the main.m
#import <Foundation/Foundation.h>
#import "Employee.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
// inside here, I instantiate a new object of my new employee class
Employee *fred = [[Employee alloc] init];
// call a method of our new object
[fred someMethod];
// change a property of new object
[fred setName:#"Fred Smith"];
}
return 0;
}
I'm on 10.6.8 with Xcode 4.2

With XCode 4.2 you need to add the line
#synthesize name,hireDate,employeeNumber;
to your Employee.m file after the #implementation line
Auto synthesis of properties only became available with XCode 4.4 - http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html
You should look at upgrading your XCode version

Related

Property issue in Objective C, 'score' not found on object of type pointer

I just started out programming in Objective C. This is very simple stuff but im wondering what im missing on my knowledge of properties, as far as I understand this should work but it gives me the error:
Property 'score' not found on object of type 'Player *'
I have a Player class and the code as follows below, each bolded is a separate file
Player.h has:
#import <Foundation/Foundation.h>
#interface Player : NSObject
#property int score;
#end
Player.m has:
#import "Player.h"
#implementation Player
- (id)init {
self = [super init];
if (self){
_score = 5000;
}
return self;
}
#end
main.m has
#import <Foundation/Foundation.h>
#import "Player.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
Player *firstPlayer = [[Player alloc] init];
NSLog(#"The default score is %i", [firstPlayer score]);
}
return 0;
}
Player.h is missing the following line which should go between the #import and #property lines:
#interface Player : NSObject
Where NSObject may be a different class, but needs to be whatever you intend to be subclassing.

creating an object from category class

I want to create a new object, one of the property is (readonly).
Here is my code:
1/ My class (.h + .m)
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#property (readonly) NSString* myProperty;
#end
#import "MyClass.h"
#implementation MyClass
#end
2/ My class extension (.h)
#import "MyClass.h"
#interface MyClass ()
#property (readwrite) NSString* myProperty;
#end
3/ MyClassCategory (.h + .m)
#import "MyClass.h"
#interface MyClass (MyClassCategory)
+ (MyClass*) creatNewObject:(NSString*) mypro;
#end
#import "MyClass+MyClassCategory.h"
#import "MyClass_MyClassExtension.h"
#implementation MyClass (MyClassCategory)
+ (MyClass*) creatNewObject:(NSString*) mypro {
MyClass* newObject = [[MyClass alloc] init];
newObject.myProperty = mypro;
NSLog(#"New object have been created%#", newObject);
return newObject;
}
#end
#import <Foundation/Foundation.h>
#import "MyClass.h"
#import "MyClass+MyClassCategory.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
MyClass* newObject1 = [MyClass creatNewObject:(#"I am the new object!")];
NSLog(#"New object have been created%#", newObject1);
}
return 0;
}
after running the code in the main method, I got
2014-09-25 21:53:52.204 MyClass[2811:303] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyClass setMyProperty:]: unrecognized selector sent to instance 0x100109e10'
014-09-25 22:36:05.746 MyClass[2989:303] -[MyClass setMyProperty:]: unrecognized selector sent to instance 0x100200130
I want to be enables edits to the properties of an existing class instance from category.
Can you help me please?
Thank you.
In MyClass.m, you also need to include the extension header.
#import "MyClass_MyClassExtension.h"
Otherwise the compiler won't see myProperty is redeclared as a read-write property while generating the implementation of MyClass.

Having trouble with class extension in Objective C, mac OS. Getting error 'NSInvalidArgumentException', no visible #interface declares the selector

I'm working on exercise 3 on page 76 in Apple's developer pdf in the class categories and extensions section, "Programming with Objective C", found here: (https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html)
my XYZPerson header looks like this:
#import <Foundation/Foundation.h>
#interface XYZPerson : NSObject
#property (readonly) NSNumber *height;
#property (readonly) NSNumber *weight;
-(NSNumber *)measureHeight;
-(NSNumber *)measureWeight;
#end
My implementation file looks like this:
#import "XYZPerson.h"
#property (readwrite) NSNumber *height;
#property (readwrite) NSNumber *weight;
#end
/////////////////////
#implementation XYZPerson
-(NSNumber *)measureHeight{
if(!_height){
_height = [[NSNumber alloc] init];
}
return _height;
}
-(NSNumber *)measureWeight{
if(!_weight){
_weight = [[NSNumber alloc] init];
}
return _weight;
}
#end
And then in my main file I have:
#import <Foundation/Foundation.h>
#import "XYZPerson.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
XYZPerson *aPerson = [[XYZPerson alloc] init];
[aPerson setHeight: [NSNumber numberWithInt:72] ];
[aPerson setWeight: [NSNumber numberWithInt:190] ];
NSLog(#"%# %#",[aPerson measureHeight],[aPerson measureWeight]);
}
return 0;
}
There might be more than one error unrelated to the issue I brought up, I'm a huge novice at Objective C right now. The exact compiler error I am getting is on the line that says,
[aPerson setHeight: [NSNumber numberWithInt:72] ];
The compiler error reads, "ARC Semantic Issue. No visible #interface for 'XYZperson' declares the selector 'setWeight:'.
Oh doh.
You will not be able to call that method from OUTSIDE of your class implementation.
Overriding properties in class extensions in the .m file doesn't expose that to the world.
At least not to the compiler.
That's the whole point.
It's for when you want properties that are readonly to the world outside of that object, but internally to the object you still want to be able to conveniently do things.
You declared the property read-only in the header file, so to everything outside of the class, the properly is read-only, and thus a setHeight: method doesn't exist.
You have made he properties height and weight read only. Then in the main function you are using setWeight and setHeight.
You can't do that as that would be writing the weights but you explicitly set them to read only.
Place your properties in .m with class extension:
#interface XYZPerson ()
#property (readwrite) NSNumber *height;
#property (readwrite) NSNumber *weight;
#end
See Apple docs about class extension:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

Objective-C error "No visible #interface for 'XYZPerson' declares the selector 'saySomething'

I am really new to Objective-C and when I was practicing the book exercises, I really am stuck here. Please help me solve this and I have been thinking what could cause this error for more than three hours. Still I didn't get it!
Best regards,
Raj.
Thanks in advance !
main.m
#import <Foundation/Foundation.h>
#import "XYZPerson.h"
#import "XYZShout.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
//XYZPerson *some = [[XYZPerson alloc]init];
XYZShout *some = [[XYZShout alloc]init];
[some sayHello];
// insert code here...
// NSLog(#"Hello, World!");
}
return 0;
}
XYZPerson.h
#import <Foundation/Foundation.h>
#interface XYZPerson : NSObject
#property NSString *firstName;
#property NSString *secondName;
#property NSDate *dob;
-(void) saySomething;
-(void) sayHello;
#end
XYZPerson.m
#import "XYZPerson.h"
#implementation XYZPerson
-(void) sayHello {
[self saySomething:#"Hello all"];
}
-(void) saySomething:(NSString *)greet {
NSLog(#"%#", greet);
}
#end
XYZShout.h
#import "XYZPerson.h"
#interface XYZShout : XYZPerson
// -(void) saySomething;
#end
XYZShout.m
#import "XYZShout.h"
#implementation XYZShout
-(void) saySomething:(NSString *)greet {
NSString *upperGreet = [greet uppercaseString];
[super saySomething:upperGreet]; // this is where I get the error mentioned above
}
#end
Got it working ! Thanks to #MatthewD , #trojanfoe , #JFS for your big help :)
It looks like you are testing inheritance so I will assume that XYZShout is supposed to be derived from XYZPerson. If so follow the suggestion from #JFS and make sure it does actually derive:
XYZShout.h:
#import <Foundation/Foundation.h>
#import "XYZPerson.h"
#interface XYZShout : XYZPerson
- (void)saySomething:(NSString *)greet;
#end
And also correct the definition of saySomething in XYZPerson (you missed off the parameter):
XYZPerson.h:
#import <Foundation/Foundation.h>
#interface XYZPerson : NSObject
#property NSString *firstName;
#property NSString *secondName;
#property NSDate *dob;
- (void)saySomething:(NSString *)greet;
// ^^^^^^^^^^^^^^^^^
- (void)sayHello;
#end
(Moved from comments into an answer...)
MatthewD: What happens if you change - (void) saySomething; in XYZPerson.h to - (void) saySomething:greet;?
Raj0689: Why does it run when I change it to saySomething:greet and not saySomething ? Since greet is defined only along with saySomething !!
When you call a method, the compiler needs to locate the signature of that method so it can verify that the method is being called correctly. The signature includes the method name and the number and types of parameters. The usual way of providing method signatures is by importing the header file that defines those signatures.
So, in XYZShout.m where you call:
[super saySomething:upperGreet];
The compiler searches XYZShout.h, which is imported by XYZShout.m, and XYZPerson.h, which is imported by XYZShout.h. In XYZShout.h, the following method was being found:
-(void) saySomething;
This matches the called method in name, but not in parameters, so the compiler does not consider this a match. No other definitions of saySomething are found anywhere, so it gives an error instead.
Please make sure to set the XYZShout.h interface to #interface XYZShout : XYZPerson?

EXC_BAD_ACCESS when synthesizing a 'global' object

this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and will then in the end post the error message i get when building.
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue];
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4];
return self;
}
#end
when i build it, i get the following error: EXC_BAD_ACCESS in this line:
#synthesize DATAMODEL;
of DBFactoryClass.m
What #synthesize does is to automatically generate implementations of the accessors for a property. EXC_BAD_ACCESS there means that you're accessing garbage when one of the accessors is executed.
That's probably happening here:
[self setDATAMODEL:[[DBDataModel alloc]init ]];
Make sure that DBDataModel's implementation of init actually returns a legitimate object.
As far as I can tell, your DBFactoryClass class is never stored anywhere, and therefore released right after the allocation if you use ARC (Since you use the strong keyword I assumed you do).
- (BOOL)...didFinishLaunching... {
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
// If you use ARC this might be released right afterwards
return YES;
}
If you want the factory to be a singleton, use something like this
+ (id)sharedInstance {
static dispatch_once_t once;
static MyFoo *instance;
dispatch_once(&once, ^{
instance = [[self alloc] init];
});
return instance;
}