Java keyword this in Objective C - objective-c

First day learning Objective-C but have a java background. I'd like to use the same variable name for my parameter that I do for my instance variable. In java we do it like this
public class Person
{
private String name;
private String age;
public void setName(String name)
{
this.name = name;
}
public void setAge(String age)
{
this.age = age;
}
}
In objective c so far I have this
#interface Person : NSObject
{
int age;
int name;
}
-(void) setAge:(int) age;
-(void) setName:(int) name;
-(int) getAge;
-(int) getName;
#end
#implementation Person
-(void) setName:(int) w
{
weight = w;
}
-(void) setAge:(int) a
{
age = a;
}
-(int) getName
{
return name;
}
-(int) getAge
{
return age;
}
#end

In Objective-C, you can define your own accessors or use #syntehsize to create them automatically for you.
In the case where you want to define accessors manually, setters are declared like this:
- (void)setName:(NSString *)name {
self.name = name;
}
- (void)setAge:(NSInteger)age {
self.age = age;
}
For getters, you simply declare them as follows:
- (NSString *)name {
return self.name;
}
- (NSInteger)age {
return self.age;
}

Objective-C programmers don't like typing, so we do it like this:
#interface Person : NSObject
#property(nonatomic, copy) NSString *name;
#property(nonatomic, assign) int age;
#end
#implementation Person
#end
You may want to start by reading Apple's Objective-C Programming Language introduction.

in ObjectiveC the way to refer to 'this' is 'self'

You have this in ObjectiveC because you are using C style variables. If you declare that variables as ObjectiveC properties and use the correct synthesize instruction:
#property (int) age;
#synthesize age;
Then you can refer to them through self.age
self.age = age;
in the implementation file. This will internally call the -(void)setAge:(int)age method and the -(int) age methods which will be defined automatically.
Finally since an ObjectiveC object is nothing more than a pointer to a C struct you can access variables by skipping ObjectiveC by using the syntax to refer to fields of a pointer to a struct: self->age = age

Related

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.

Is it possible to send a struct in a block?

I am creating a Universal Class, for SQLite and I am trying to send a block of sqlite3_step, to be processed.
In sqlite3_step, I am passing the struct object statement. But, it seems I need to use pointers.
How can I possibly do ir?
Yeah, something like this should work:
typedef struct
{
int data;
}MyStruct;
#interface Foo()
#property (nonatomic, copy) void (^myBlock)(MyStruct);
#end
#implementation Foo
- (void) someMethod {
self.myBlock = ^(MyStruct theStruct) {
NSLog(#"Value of data in the struct %i", theStruct.data);
};
MyStruct theStruct;
theStruct.data = 5;
self.myBlock(theStruct);
}
#end

Classes in Objective-C

I have a class named person, with two values: age and weight.Why can't I access these two values in the main function like this:
int a=[chuck age];
int b=[chuck weight];
What is the best way to do that? Using properties is the correct way?
Header file:
#import <Foundation/Foundation.h>
#interface person : NSObject
{
int age;
int weight;
}
-(void) print;
-(void) setAge;
-(void) setWeight;
#end
Implementation file:
#import "person.h"
#implementation person
-(void) print
{
printf("Your age is %d and your weight is %d.", age, weight);
}
-(void) setAge
{
printf("Write age: ");
int v;
scanf("%d", &v);
age=v;
}
-(void) setWeight
{
printf("Write weight: ");
int g;
scanf("%d", &g);
weight=g;
}
#end
Are you working from some kind of a tutorial or book? That is an odd place to start for learning to write OS X or iOS apps.
In any case, the issue is that you've colluded getter/setter stuff with methods that implement other functionality.
I would suggest that your Person class be declared as:
#interface Person : NSObject
#property NSInteger age;
#property NSInteger weight;
#end
With Person.m:
#implementation Person
- (id) init {
self = [super init];
if (self) {
// preposterous initial values so we know if they weren't set.
_age = -1;
_weight = -1;
}
return self;
}
#end
That is, a Person only holds information about a single person. It does not do any kind of I/O, etc...
Then, your main.m would look something like:
#import <Foundation/Foundation.h>
#import "Person.h"
NSInteger ScanIntegerWithPrompt(NSString *prompt) {
printf("%s: ", [prompt UTF8String]);
int v;
scanf("%d", &v);
return (NSInteger) v;
}
int main(...) {
#autoreleasepool {
Person *p = [[Person alloc] init];
p.age = ScanIntegerWithPrompt(#"Enter age:");
p.weight = ScanIntegerWithPrompt(#"Enter weight:");
printf("Your age is %d and your weight is %d", p.age, p.weight);
}
return 0;
}
Structuring the code this way separates the Model -- the data container -- from the Control layer. There isn't much of a View layer here.
If you really wanted to keep the I/O / parse logic with the Person object, then add something like this to the Person object:
...
- (NSNumber)readIntegerWithPrompt:(NSString*)prompt
{
... same code as function above ...
}
- (void)readAgeFromStandardInput
{
self.age = [self readIntegerWithPrompt:#"Enter age: "];
}
- (void)readWeightFromStandardInput
{
self.weight = [self readIntegerWithPrompt:#"Enter weight: "];
}
...
Then you'd call those methods from your main.
Your problem is You're trying to access private age and weight ivars, which aren't accessible this way.
The good way to do this is to use ObjC properties, but this is not required for your example.
You need to create two methods to access the private ivars, call them age and weight, they should look like this in the class interface:
- (int) age;
- (int) weight;
and the implementation is:
- (int) age{
return age;
}
- (int) weight{
return weight;
}
Now in your main.m you can easily access the data needed like this:
#import <Foundation/Foundation.h>
#import "person.h"
int main(int argc, char *argV[]) {
#autoreleasepool {
person *andrew = [[person alloc]init];
[andrew setAge];
[andrew setWeight];
NSLog(#"Age:%d, Weight:%d",[andrew age], [andrew weight]);
}
return 0;
}
If you want to know how it's done with properties please let me know and I can update the answer :)
In your header file :
#property int age;
#property int weight;

How to write a correct setter method in Objective-C

There's a setter method in Employee class
-(void)setAge:(int)age{
self.age = age;
}
I know that I should use _age instead of self.age. Is there any other problems in this setter method?
I guess maybe I should check the age because if age < 0 is not correct for Employee
This is infinite recursive loops. Because it calls again and again...like this...
[self setAge:age];
So you should do like that..
#synthesize age = _age;
- (void)setAge:(int)age
{
_age = age;
}
This will create infinite loop.
Add in your header file.
#property (readwrite, assign) NSInteger age;
You don't need to use #synthetize in new versions of the xcode.
After you can use the property:
self.age = 15;
or
[self setAge:15]
NSLog(#"Age is %d", self.age);
And you can also modify the setter
-(void)setAge:(NSInteger)age {
_age = age;
// your code
}

Error: Accessing unknown getter method?

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.