I was playing around with objective C. This is my code for a class I wrote , arithmetic.h:
#import <Foundation/Foundation.h>
#interface arithmetic : NSObject
#property int cur;
-(id)initWithNumber:(int)number;
#end
#implementation arithmetic
#synthesize cur;
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(#"Yo, all works :D ");
}
return self;
}
-(id)initWithNumber:(int)num{
self = [super init];
if(self){
[self setCur:8] ;
}
return self;
}
#end
Note the #property int cur. I was excepting objective c to create a setCur and a getCur method as accessors and mutators for my class. However, when I run this:
arithmetic *test = [[arithmetic alloc] initWithNumber:89];
[test setCur:534];
NSLog("%i",[test getCur ]);
The first two lines work. But the last line says
No visible interface for arithmetic declares the selector 'getCur'
What is the problem ?
It is because when you declare like this in your #implementation:
#synthesize cur;
it will create getter
-(int)cur {
return _cur;
}
and also it will create a setter
-(void)setCur:(int)newCur {
_cur = newCur;
}
In summary, Objective-C getter/setter is having a pattern of propery/setPropery respectively, unlike Java that uses getProperty/setProperty.
And Objective-C getter/setter is accessed via dot(.) notation. For example
int x = obj.cur;
obj.cur = 100;
Related
As a foray into new programming languages, I build well known data structures to familiarize myself with the syntax and the basic ins & outs of the language. In this case, I examine the stack in Objective-C. From Apple's Working with Objects we read about the keyword 'id'
...This is a special keyword used in Objective-C to mean “some kind of object.” It is a pointer to an object, like (NSObject *), but is special in that it doesn’t use an asterisk.
By using the keyword 'id', it seems possible to create a stack data structure that holds differing types of Obj-C objects; however, I am not sure if this as intended. Is it better to create the various class methods for each potential data type rather than attempting a generic method and make sure each stack adheres to a single Object type?. Here is what I have so far
XYZNode.h
#import <Foundation/Foundation.h>
#interface XYZNode : NSObject
#property id value;
#property XYZNode *next;
-(instancetype)initWithValue:(id)aValue next:(XYZNode *)aNext;
-(instancetype)init;
// Class factory methods should always start with the name of
// the class (without the prefix) that they create, with the
// exception of subclasses of classes with existing factory methods.
+(XYZNode *)nodeWithValue:(id)aValue nextNode:(XYZNode *)aNext;
#end
XYZNode.m
#import "XYZNode.h"
#implementation XYZNode
-(instancetype)initWithValue:(id)aValue next:(XYZNode *)aNext {
if (self = [super init]) {
_value = aValue;
_next = aNext;
} return self;
}
-(instancetype)init {
return [self initWithValue:nil next:nil];
}
+(XYZNode *)nodeWithValue:(id)aValue nextNode:(XYZNode *)aNext {
return [[self alloc] initWithValue:aValue next:aNext];
}
#end
XYZStack.h
#import <Foundation/Foundation.h>
#interface XYZStack : NSObject
-(void)pushValue:(id)aValue;
-(id)popValue;
-(BOOL)isEmpty;
-(instancetype)init;
-(instancetype)initWithValue:(id)aValue;
+(XYZStack *)stackWithValue:(id)aValue;
#end
XYZStack.m
#import "XYZStack.h"
#import "XYZNode.h"
// The extension hides how the values are stored
#interface XYZStack ()
#property XYZNode *lastNodeAdded;
#end
#implementation XYZStack
// Default initializer
-(instancetype)initWithValue:(id)aValue {
if (self = [super init]) {
_lastNodeAdded = nil;
}
if (aValue) {
[self pushValue:aValue];
}
return self;
}
// Call default initializer
-(instancetype)init{
return [self initWithValue:nil];
}
-(BOOL)isEmpty{
return ([self lastNodeAdded] == nil);
}
-(void)pushValue:(id)aValue {
[self setLastNodeAdded:[XYZNode nodeWithValue:aValue nextNode:[self lastNodeAdded]]];
}
-(id)popValue {
id temp = [[self lastNodeAdded] value];
[self setLastNodeAdded:[[self lastNodeAdded] next]];
return temp;
}
+(XYZStack *)stackWithValue:(id)aValue {
return [[self alloc] initWithValue:aValue];
}
#end
Any comments would be appreciated.
I'm working on this assignment I found online (Intermediate App Development Using iOS). I'm stuck on part c and d, don't know exactly what its asking me to do.
I know how to print int (%i) and object (%#), but %# print all data? Any help or suggestion will be appreciated.
Part 6
a) Implement class A with properties a1, a2, and a3 (int, string, int).
b) New objects are automatically initialized to 1, "hello", 1
c) Also provide initializer to any data and constructor (called without alloc) to do the same.
d) Make sure %# object of A will print all data.
Here is what I have done so far:
// classA.h
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
// Part 6a
#property int a1;
#property NSString *a2;
#property int a3;
-(ClassA *) initWithA1: (int) x andA2: (NSString *) s andA3: (int) y;
#end
//classA.m
#import "ClassA.h"
#implementation ClassA
-(ClassA *) initWithA1:(int)x andA2:(NSString *)s andA3:(int)y {
self = [super init];
if (self) {
self.a1 = x;
self.a2 = s;
self.a3 = y;
}
return self;
}
// part 6b
-(ClassA *) init {
if (self = [super init]) {
self.a1 = 0;
self.a2 =#"hello";
self.a3 = 0;
}
return self;
}
#end
In reference to part "b" of your question:
As a general rule, only 1 initializer should be doing the "real" work. This is often referred to as the designated initializer. So, your init method should probably read something like:
- (id) init
{
return [self initWithA1:1 andA2:#"hello" andA3:1];
}
As #orbitor wrote, your class should have one designated initialiser.
So, your init method should probably read something like:
- (id) init
{
return [self initWithA1:1 andA2:#"hello" andA3:1];
}
In order to print all object you should implement custom description method:
- (NSString *) description
{
return [NSString stringWithFormat:#"a1 = %d, a2 = %#, a3 = %d", self.a1, self.a2, self.a3];;
}
According to c:
Class method new just calls alloc and init methods so you should only make sure that you wrote properly all initialisers.
I am having trouble accessing an int property from another class. I know this question has been asked quite a few times however none of the solutions posted in previous questions seem to work. My knowledge in xcode is basic, and I am using this project to develop my skills.
The two classes I have are: HelloWorldLayer and ClassOne. Where ClassOne states the value of int. Both are Cocos2d CCLayer classes (probably not the best class to practice inter-class value access).
ClassOne.h
#interface ClassOne : CCLayer {
int ageClass;
}
#property (nonatomic, readwrite)int ageClass;
#end
ClassOne.m
#implementation ClassOne
#synthesize ageClass = _ageClass;
-(id)init{
if((self=[super init])){
_ageClass = 10;
}
return self;
}
#end
HelloWorldLayer.h
#import "ClassOne.h"
#interface HelloWorldLayer : CCLayer <...> {
ClassOne *agePointer;
}
#property (nonatomic,assign)ClassOne *agePointer;
+(CCScene*)scene;
#end
HelloWorldLayer.m
#import "HelloWorldLayer.h"
#import "AppDelegate.h"
#import "ClassOne.h"
#implementation HelloWorldLayer
#synthesize agePointer = _agePointer;
+(CCScene*)scene...
-(id)init{
if((self=[super init])){
_agePointer.ageClass = self;
NSLog(#"ClassOne int = %#",_agePointer);
}
return self;
}
...
#end
Output Result:
"ClassOne int = (null)"
or "0" if i use "%d" token and "int = x", where the line "int x =_agePointer.ageClass;"
is used.
The result I am after is for the HelloWorldLayer NSLog to display "10", the int value defined in ClassOne.
Any wisdom and corrections on my use of language is greatly appreciated.
Ok Try This:
-(id)init
{
if((self=[super init])){
_agePointer = [[ClassOne alloc] init];
NSLog(#"ClassOne int = %d",_agePointer.ageClass);
}
return self;
}
First of all, when outputting int, always use %d instead of %# in your NSLog.
Second of all, if you are expecting to output 10, you should've instantiated the class first in your HelloWorldLayer.m:
-(id)init{
if (self = [super init]) {
_agePointer = [[ClassOne alloc] init];
NSLog(#"ClassOne int = %#",_agePointer);
}
return self;
}
I'm trying to take a C-style vector and convert it into an NSMutable array object.
Here's the function:
+(NSMutableArray*)arrayFromPoints:(vector<Point2f>&)points
{
NSMutableArray* pointArray = [[NSMutableArray alloc] init];
for (int i=0;i<points.size();i++)
{
Point2f point = points[i];
JBPoint* point2 = [[JBPoint alloc]initWithX:point.x andY:point.y];
[pointArray addObject:point2];
}
return pointArray;
}
Custom point class:
#implementation JBPoint
float _x;
float _y;
-(id) initWithX:(float)x andY:(float)y
{
if (self=[super init])
{
_x = x;
_y=y;
}
return self;
}
-(float)x{ return _x;}
-(float)y {return _y;}
#end
Test output:
for (JBPoint* pnt in array)
{
NSLog(#"%f, %f", pnt.x, pnt.y);
}
I except it to output the array, but every time it just gives me the last value! does anyone know why?
I thought that they were maybe pointing to the same object, but they have different memory addresses.
So I figured out the problem. float _x;
float _y; where being treated like class variables instead of instance variables. Changed the class to:
#interface JBPoint()
{
float _x;
float _y;
}
#end
#implementation JBPoint
-(id) initWithX:(float)x andY:(float)y
{
if (self=[super init])
{
_x = x;
_y=y;
}
return self;
}
-(float)x{ return _x;}
-(float)y {return _y;}
#end
if you wrote
#property (nonatomic, readonly) float x;
#property (nonatomic, readonly) float y;
in your header file you wouldn't need to declare the instance variables (and would have avoided the issue here) and you could delete the getter methods your wrote as that would all be generated by the compiler for you and your custom init method would continue to work (with the most recent compiler).
Its a good idea to do this because:
less code
your intent is clear - 2 variables that are readonly for clients
follows language conventions
If you are using an older compiler (an older version of Xcode) then you would also have to #synthesize the accessors like this:
#synthesize x = _x;
Some interesting asides:
With the most recent complier you didn't need the class extension.
#implementation{
float _x;
float _y;
}
would also have worked.
As referenced in WWDC 2012 session video 413, the current recommended pattern to write an init method is:
...
self = [super init];
if (self) {
...
}
return self;
I have a Class that runs the following method (a getter):
// the interface
#interface MyClass : NSObject{
NSNumber *myFloatValue;
}
- (double)myFloatValue;
- (void)setMyFloatValue:(float)floatInput;
#end
// the implementation
#implementation
- (MyClass *)init{
if (self = [super init]){
myFloatValue = [[NSNumber alloc] initWithFloat:3.14];
}
return self;
}
// I understand that NSNumbers are non-mutable objects and can't be
// used like variables.
// Hence I decided to make make the getter's implementation like this
- (double)myFloatValue{
return [myFloatValue floatValue];
}
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput;
}
#end
When I mouse over the myFloatValue object during debugging, it does not contain a value. Instead it says: "out of scope".
I would like to be able to make this work without using #property, using something other than NSNumbers, or other major changes since I just want to understand the concepts first. Most importantly, I would like to know what mistake I've apparently made.
I can see a couple of mistakes:
The line #implementation should read #implementation MyClass
The function setMyFloatValue is missing a closing ] and } —it should read:
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput];
}
}
I've just tested it in Xcode and it works for me with these changes.
Why not just set property in interface and synthesize accessors in implementation?
#interface MyClass : NSObject {
float *myFloat
}
#property (assign) float myFloat;
#end
#implementation MyClass
#synthesize myFloat;
#end