Error: Accessing unknown getter method? - objective-c

Error: Accessing unknown getter method?
Thanks...
#import <Foundation/Foundation.h>
#interface puppy : NSObject {
int mack;
int jack;
}
-(puppy *) waldo: (puppy *) f;
-(void) setMack: (int) m;
-(void) setJack: (int) j;
#end
///////////////////////////////////////////////////
#import "puppy.h"
#implementation puppy
-(void) setJack: (int) j{
jack = j;
}
-(void) setMack: (int) m{
mack = m;
}
-(puppy*) waldo: (puppy *) f{
return (f.jack + f.mack); // Error: <-- Accessing unknown "jack" getter method
// Error: <-- Accessing unknown "mack" getter method
}

You have not specified getter method for jack and mack. Instead of writing own getter/setter you can use property for them.
#interface puppy : NSObject {
int mack;
int jack;
}
-(puppy *) waldo: (puppy *) f;
// use property
#property (nonatomic, assign) int mack;
#property (nonatomic, assign) int jack;
#end
#implementation puppy
#synthesize jack, mack;
-(puppy*) waldo: (puppy *) f{
return (f.jack + f.mack);
}
#end
You do not need those set methods now. Both getters and setter are synthesized for you. And not asked in the question, you should return int from method waldo.

You haven't implemented the methods jack and mack.
- (int) jack { return jack; }
- (int) mack { return mack; }
But I'd recommend just using #property and #synthesize with no ivar.

When you do f.jack, it translates to [f jack]. You need to add a - (int)jack method to your interface for this to work. Poorly worded perhaps, I also meant the method needs to be implemented. Same is the case of mack
But that said, dot notation is for properties. Isn't apt.
It would be easier if you defined properties for mack and jack and synthesized those methods.

Related

How can I declare user defined setter, getter method?

guys.
How can I access the variable which I made by #property instruction?
I learned that prefix _ makes possible to access when I use my own getter/setter in an objective-c course.
//Person.h
#import <Foundation/Foundation.h>
#interface Person : NSObject
#property NSInteger age;
// getter
- (NSInteger)age;
// setter
- (void)setAge:(NSInteger)age;
#end
// Person.m
#import "Person.h"
#implementation Person
// getter
- (NSInteger)age {
return _age;
}
// setter
- (void)setAge:(NSInteger)age {
_age = age;
}
#end
But that code gave me errors Use of undeclared identifier '_age'.
How can I fix that?
Thanks!
You should add explicit synthesize for ivar, as below
#implementation Person
#synthesize age=_age;

Why method is not getting called

I'm trying to learn how to make a class and object and how to call methods in Objective-C. My small program creates an object of the City class, allows to name that object, set an age, population, and get these values to print. But when I call a method to set these values, I get a (null) and zeros in result. Here's my code:
City.h
#import <Foundation/Foundation.h>
#interface City : NSObject
-(void) setName:(NSString *)theName Age:(int)theAge Population:(int)thePopulation;
-(void) getName;
-(void) getAge;
-(void) getPopulation;
-(void) nextDay;
#end
City.m
#import "City.h"
#implementation City
{
NSString *name;
int age;
int population;
}
-(void) setName:(NSString *)theName Age:(int)theAge Population:(int)thePopulation
{
theName = name;
theAge = age;
thePopulation = population;
}
-(void) getName
{
NSLog(#"Name is %#", name);
}
-(void) getAge
{
NSLog(#"Age is %d", age);
}
-(void) getPopulation
{
NSLog(#"Population today is %d", population);
}
main.m
int main()
{
City *moscow = [[City alloc] init];
[moscow setName:#"Msk" Age:120 Population:1000];
[moscow getName];
[moscow getAge];
[moscow getPopulation];
}
the result of the running is:
Name is (null)
Age is 0
Population today is 0
Program ended with exit code: 0
what am I doing wrong?
The problem is that the instance variables of City is never set. The code in setName:Age:Population: assigns the values of the instance variables (name, age, and population) to the arguments variables (theName, theAge, and thePopulation). Swapping these will cause the setter to assign the arguments to the instance variables:
name = theName;
age = theAge;
population = thePopulation;
That said, it's more idiomatic Objective-C to use properties—instead of instance variables and manual getters and setters—and to use an initializer to set the initial values. With those changes the City class would look something like this:
City.h
NS_ASSUME_NONNULL_BEGIN
#interface City : NSObject
#property (copy) NSString *name;
#property (assign) NSInteger age;
#property (assign) NSInteger population;
- (instancetype)initWithName:(NSString *)name
age:(NSInteger)age
population:(NSInteger)population;
#end
NS_ASSUME_NONNULL_END
City.m
#import "City.h"
#implementation City
- (instancetype)initWithName:(NSString *)name
age:(NSInteger)age
population:(NSInteger)population
{
self = [super init];
if (self) {
_name = [name copy];
_age = age;
_population = population;
}
return self;
}
#end
Two things to note about this code:
The string is copied—both in the initializer and in the property—to protect against having a NSMutableString is passed and later be mutated (which would mutate the value of name as well. For the common case where an immutable NSString is passed, the copy is equivalent to a "retain".
The synthesized instance variables are used when assigning values in the initializer. This is to protect against having a subclass override any of these properties and have a custom setter method run before the object is fully initialized (have all its variables set to their initial values). This only applies to initializers, custom setters, and dealloc. Everything else should use the properties to access and modify these values.

How to use enum in init method?

I have the following code which has an init method that takes an enum as an attribute, but I'm getting an error for an elected identifier.
typedef NS_ENUM(NSUInteger, ActivtyLevel) {
kActivityLevelSedentary,
kActivityLevelLight,
kActivityLevelModerate,
kActivityLevelHeavy,
kActivityLevelExtreme
};
#interface DFUserProfile ()
#property (nonatomic, strong) NSNumber *weight;
#property (nonatomic, strong) NSNumber *bodyFatPercentage;
#end
#implementation DFUserProfile
- (id)initWithWeight:(NSNumber *)iWeight bodyFat:(NSNumber *)iBodyFat andActivityLevel:(NSUInteger)iActivtyLevel {
if (self = [super init]) {
_weight = iWeight;
_bodyFatPercentage = iBodyFat;
ActivtyLevel = iActivtyLevel;
}
return self;
}
#end
The typedef declares a type called ActivityLevel, you need a variable or property with that type.
For example you might declare the property:
#property (nonatomic) ActivityLevel activityLevel;
and then declare your method as:
- (id)initWithWeight:(NSNumber *)iWeight
bodyFat:(NSNumber *)iBodyFat
andActivityLevel:(ActivityLevel)iActivtyLevel // note use of the enumeration type
{
...
_activityLevel = iActivityLevel;
You need to have a variable of the type of the enum, you can't store it directly into the enum, that is a type. Add this:
#property (nonatomic) ActivityLevel activityLevel;
then in your init method:
_activtyLevel = iActivtyLevel;

In Objective-C, how do I pass a property as an argument for a function and then call the setter/getter methods?

The code is probably the best way to see what I am trying to do:
AcInfo.h:
#interface AcInfo : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString *registrationNumber;
#end
AcInfo.m:
#implementation AcInfo
#dynamic registrationNumber;
#end
AnotherClass.h:
#interface AnotherClass : NSObject {
}
#property (nonatomic, retain) AcInfo *detailItem;
#property (nonatomic, retain) IBOutlet UITextField *registrationNumberTextField;
- (void)setDetailItemValueFromUIElement:(id *)uiElement forAcInfoTarget:(id *)acInfoTarget;
#end
AnotherClass.m:
#import "AcInfo.h"
#implementation AnotherClass
#synthesize detailItem, registrationNumberTextField;
- (void)viewDidLoad
{
[super viewDidLoad];
registrationNumberTextField.text = #"Test";
// I expect this to set detailItem.registrationNumber to the value of
// registrationNumberTextField.text (Test) but it doesn't change anything!
setDetailItemValueFromUIElement:registrationNumberTextField forAcInfoTarget:detailItem.registrationNumber;
}
- (void)setDetailItemValueFromUIElement:(id *)uiElement forAcInfoTarget:(id *)acInfoTarget
{
if ([(id)uiElement isKindOfClass:[UITextField class]]) {
// This doesn't do anything when it returns!
(NSString *)acInfoTarget = (UITextField *)uiElement.text
return;
}
}
#end
In short, I want acInfoTarget to call the getter [detailObject registrationNumber] and the setter [detailObject setRegistrationNumber] in the setDetailItemValueFromUIElement: function...
You can set or read properties by name using
// setter
NSString *propertyName = #"myProperty";
[object setValue:newValue forKey:propertyName];
// getter
id value = [object valueForKey:propertyName];
This is slower than using the normal dot notation, though, and it's frequently (though not always) a sign of poorly-designed code.
Also note that id is a pointer type, so you probably don't actually mean "(id*)".
Your code wants to look something like this, I think:
- (void)setDetailItemValueFromUIElement:(id)uiElement forAcInfoTarget:(NSString*)acInfoTarget {
if ([(id)uiElement isKindOfClass:[UITextField class]]) {
NSString *newValue = ((UITextField*)uiElement).text;
[self.detailItem setValue:newValue forKey:acInfoTarget];
}
}
Properties are just syntax sugar for a couple of accessor methods. They are not, in essence, variables so you shouldn't treat them as such. If you want to affect a property, then what you wanting to do is call a method. So you should pass a id and selector parameter and not pointer to a variable type.

getting an error in Objective C

I am getting an error in the following code. I could not guess what mistake i have done for such error to come up.
remote.h
struct RMH_REQUEST_SESSION_MSG //Message Data
{
int uDeviceID;
int uProtocolVersion;
int uReserved[5];
};
RS232MsgRequestSession.m
#implementation RS232MsgRequestSession
-(id)init
{
if (self = [super init]) {
struct RMH_REQUEST_SESSION_MSG st;
}
return self;
}
#end
xyz.h
#import "RS232MsgRequestSession.h"
#implementation xyz
-(void)Open{
RS232MsgRequestSession* pMsg = [[RS232MsgRequestSession alloc]init];
pMsg->st.uProtocolVersion = RS232_VERSION; //error
pMsg->st.uDeviceID = RS232_PROTOCOL_DEVICE_ID; //error
memset(pMsg->st.uReserved,0x00,sizeof(pMsg->st.uReserved)); //error
}
#end
Error:'struct RS232MsgRequestSession' has no member named 'st'
Put iVar declaration in class's #interface block. In your code st is just a local variable in init method:
#interface RS232MsgRequestSession : NSObject{
...
#public
struct RMH_REQUEST_SESSION_MSG st;
}
...
#end
You are defining st as a local variable in the init function.
Move struct RMH_REQUEST_SESSION_MSG st; to the class definition in RS232MsgRequestSession.h
What you forgot to do was include the struct in your #interface as a public instance variable:
#interface RMH2532MsgRequestSession : NSObject {
#public
struct RMH_REQUEST_SESSION_MSG st;
}
- (void) Open;
#end
And your #implementation should be empty:
#implementation RS232MsgRequestSession
#end
PS - The reason why you must use #public here is because in xyz, you were doing a direct dereference of the object using the member operator ->. This is not allowed by default when working with Objective-C objects. However, if the instance variables are under a #public attribute, then you will not have any problems doing this.
As you might have guessed by now, using #public is a Very Bad Idea -- usually. It breaks encapsulation and opens a pandora's box of potential problems that you wouldn't have otherwise had if you had used proper encapsulation.