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

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?

Related

Objective-C: Assigning a value to a static remains nil?

I have the following defined in a header file:
static NSArray *knownPrinters = nil;
In a test case:
knownPrinters = [NSArray new];
I have a breakpoint before and after that single line and the value of knownPrinters remains nil despite being assigned. There is only the main thread and I running only one unit test.
Am I going crazy or is there a legitimate reason why this would occur?
I defined your global variable by using extern keyword as rmaddy suggested and it is allocated in a unit test under the same conditions you described. Here is the code
// Header file
#import <Foundation/Foundation.h>
extern NSArray *knownPrinters;
#interface DummyObject : NSObject
#end
Here is the implementation file
#import "DummyObject.h"
NSArray *knownPrinters = nil;
#implementation SingletonObject
#end
And test file,
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "DummyObject.h"
#interface SOStaticAssignTests : XCTestCase
#end
#implementation SOStaticAssignTests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testExample {
knownPrinters = [NSArray new];
NSLog(#"For debugging");
}
#end
I hope it solves your problem.

Getting a "Method Definition not found error" and don't know why

I am going through Apple's Programming with Objective-C and doing the very simple exercises along the way. For some reason I am getting an error saying that a Method Definition cannot be found. I've checked for spelling and caps and the method is both in the .h and .m files. Can't figure out why it's doing it.
Specifically it is saying that the method definition for 'Say Something' cannot be found. Here is the code:
.h
#import <Foundation/Foundation.h>
#interface XYZPerson : NSObject
#property NSString *firstName;
#property NSString *lastName;
#property NSDate *dateOfBirth;
- (void)saySomething;
- (void)sayHello;
- (void)sayShutUp;
- (void)sayHola;
+ (id)person;
#end
and the .m
#import "XYZPerson.h"
#implementation XYZPerson
- (void)saySomething:(NSString *)greeting {
NSLog(#"%#", greeting);
}
- (void)sayHello {
[self saySomething:#"Hello, World!"];
}
- (void)sayHola {
[self saySomething:#"Hola, Amigos!"];
}
- (void)sayShutUp {
[self saySomething:#"Shut up!"];
}
+ (id)person {
return [[self alloc]init];
}
#end
A method named saySomething: is different than a method named saySomething. The former takes an argument, and the latter does not. You'll have to change the declaration in your header file to include an argument. i.e. change:
- (void)saySomething;
to:
- (void)saySomething:(NSString *)greeting;
So that it matches your implementation.

Objective C - My code doesn't see declared #property - Property not found in object of type

I'm new to ObjectiveC and Xcode and I'm having a strange behavior:
This is the Packet class header: Packet.h
#import <Foundation/Foundation.h>
#interface Packet : NSObject
{
short index;
NSData *packetData;
short totalChunks;
}
#property (nonatomic) short index;
#property (strong, nonatomic) NSData *packetData;
#property (nonatomic) short totalChunks;
#end
And this is Packet.m
#import "Packet.h"
#implementation Packet
#synthesize index;
#synthesize packetData;
#synthesize totalChunks;
-(id)init
{
self = [super init];
return self;
}
#end
The problem is i can't use getter and setter although it seems to me that properties are declared and synthesized correctly!
for example:
#import "TransferManager.h"
#implementation TransferManager
-(void)sendAckPacket
{
Packet *packet = [[Packet alloc] init];
packet.index; //ERROR HERE: Property not found on object of type Packet *
}
#end
I know there is no TransferManager.h attached becaues I don't want to write useless stuff, but it imports "Packet.h". Otherwise i should have error during the initialization of *packet.
I'm stuck... Any Help? :)

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

Objective-C dot syntax or property value?

I keep reading that dot syntax is possible but I keep getting errors that the struct does not contain members I am referencing. Perhaps its not the dot syntax so I have included details of what I am doing in hopes of a solution:
// MobRec.h - used as the objects in the MobInfo array
#import <Foundation/Foundation.h>
#interface MobRec : NSObject {
#public NSString *mName;
#public int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
// MobDefs.h - array of MobRecords
#interface Mobdefs : NSObject {
#public NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo; // is this the right property?
-(void) initMobTable;
#end
// MobDefs.m
#import "Mobdefs.h"
#import "Mobrec.h"
#implementation Mobdefs
#synthesize mobInfo;
-(void) initMobTable
{
// if I use traditional method I get may not respond
[mobInfo objectAtIndex:0 setmName: #"doug"];
// if I use dot syntax I get struct has no member named mName
mobInfo[1].MName = #"eric";
}
// main.h
MobDefs *mobdef;
// main.m
mobdef = [[Mobdefs alloc] init];
[mobdef initMobTable];
although both methods should work I get erros on both. What am I doing wrong? My best thoughts have been that I am using the wrong #property but I think I have tried all. I am performing alloc in main. Ideally I would like to for this use dot syntax and cant see why its not allowing it.
A couple of things: (edit: original point #1 removed due to error)
Although the dot syntax is supported, the array index syntax for NSArray is not. Thus, your call to mobInfo[1] will not be the same as [mobInfo objectAtIndex:1]; Instead, mobInfo will be treated as a simple C-style array, and that call would be almost guaranteed to result in a crash.
You should not define variables in your header file as you do in main.h. The line MobDefs *mobdef; belongs somewhere in main.m.
edit: Here is how it should look:
MobRec.h
#interface MobRec : NSObject {
NSString *mName;
int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
MobRec.m
#implementation MobRec
#synthesize mName;
#synthesize mSpeed;
#end
MobDefs.h
#interface MobDefs : NSObject {
NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo;
-(void) initMobTable;
#end
MobDefs.m
#import "MobDefs.h"
#import "MobRec.h"
#implementation MobDefs
#synthesize mobInfo;
-(void) initMobTable
{
// option 1:
[(MobRec*)[mobInfo objectAtIndex:0] setMName:#"doug"];
// option 2:
(MobRec*)[mobInfo objectAtIndex:0].mName = #"eric";
// option 3:
MobRec *mobRec = [mobInfo objectAtIndex:0];
mobRec.mName = #"eric";
}
main.m
MobDef *mobdef = [[MobDefs alloc] init];
[mobdef initMobTable];
...
[mobdef release]; // don't forget!
You need to either cast the object returned by -objectAtIndex:, or use a method call on it:
[[mobInfo objectAtIndex: 0] setMName: #"doug"];
or
((Mobrec *) [mobInfo objectAtIndex: 0]).MName = #"doug";
[mobInfo objectAtIndex:0 setmName: #"doug"];
There is no objectAtIndex:setmName method, so you're going to have to explain what you think this is even supposed to do.
mobInfo[1].MName = #"eric";
Use objectAtIndex to look something up in an NSArray object.