Objective C...Define structures? - objective-c

I am new programming and Objective-C in general. Do I declare a struct in the interface and define it in the implementation use a void method ?...
#interface Elements : NSObject {
struct elementZ{
NSString *name;
float molarmass;
}elements[81];
Now that I have declared it..where do I initialize the elements[81] array?

Your code works as is for me. Then you can access the data in your implementation like so:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
elements[2].name = #"hello";
NSLog(elements[2].name);
}
This will print 'hello' to the console.

Do I declare a struct in the interface and define it in the implementation use a void method ?
Yes it is what you think since Objective C is a super set of C. Have a method, that takes no arguments and returns void and initialize the member variables of struct elementz through elements[81];. Probably by running a loop from 0 to 80. As an example -
#import <Foundation/NSObject.h>
#interface Fraction: NSObject {
struct myStructure {
int numerator, denominatior;
}objects[10];
}
-(void) print;
-(void) initialize;
#end
#implementation Fraction
-(void) initialize
{
for( int i=0; i<10; ++i )
{
objects[i].numerator = (i+1);
objects[i].denominatior = (i+2);
}
}
-(void) print
{
for( int i=0; i<10; ++i )
{
printf("%d\t%d\n", objects[i].numerator, objects[i].denominatior);
}
}
#end
int main(int argc, char *argv[])
{
Fraction *obj = [[Fraction alloc] init];
[ obj initialize ];
[ obj print ];
[ obj release ];
return 0;
}
Output:
[Switching to process 949]
Running…
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
Debugger stopped.
Program exited with status value:0.
Hope it helps !

typedef struct element{
NSString *name;
float molarmass;
}elementZ;
elementZ[81] array;

Add a init method within the implementation block of your Elements class:
- (id)init {
if (self = [super init]) {
for (int i=0; i<81; i++) {
elements[i].name = "foo";
}
}
return self;
}
maybe some reading is required to get familar to Objective-C: Introduction to The Objective-C Programming Language
Object creation in Objective-C requires two steps:
Allocation
Initialization
E.g.:
Elements *e = [[Elements alloc] init];

Related

accessing inherited array in Objective C

I'm currently working on a project that's split in two classes, the class 'Array' and the class 'PPCalcVals'. Because other classes, that will be added, will also have to have access the array, I thought it would be the best to write the array class, containing an NSMutableArray and Subclass all the others (beginning with the PPCalcVals class.
So the 'PPCalcVals' class needs to access the elements of the array in the superclass 'Array'.
(Please correct me if this is the wrong approach).
As mentioned the whole program is written and well working in C but to create a GUI and eventually an OSX or IOS application I started to learn OOProgramming with Objecitve C.
Anyways, when I reference the objects in the array of the superclass the only value that gets printed is "null" which is not really what I want.
Here is the code:
main routine:
#import <Foundation/Foundation.h>
#import "Array.h"
#import "PPCalcVals.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
[prices addValue:#12];
[prices addValue:#13];
[prices addValue:#14];
[prices addValue:#15];
[prices addValue:#15];
[prices print];
[myVals print];
}
return 0;
}
array.h file:
#import <Foundation/Foundation.h>
#interface Array : NSObject
{
NSMutableArray *prices;
}
-(id) initWithName: (NSNumber *) values;
-(void) addValue: (NSNumber *) value;
-(void) print;
-(NSMutableArray *) prices;
#end
array.m
#import "Array.h"
#implementation Array
-(id) initWithName:(NSNumber *)values
{
self = [super init];
if(self)
{
prices = [NSMutableArray array];
}
return self;
}
-(void) addValue: (NSNumber *) value
{
[prices addObject:value];
}
-(void) print
{
NSLog(#"%#",prices);
}
-(NSMutableArray *)prices
{
return prices;
}
#end
PPCalcVals.h:
#import "Array.h"
#interface PPCalcVals : Array
#property id high,low,open,close;
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l; //set high and low
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c; //set open and close
-(void) sort; //sort array
-(void) print; //debugging tool
#end
PPCalcVals.m:
#import "PPCalcVals.h"
#implementation PPCalcVals
#synthesize high,low,open,close;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c
{
o = prices[0];
c = prices[2];
open = o;
close = c;
}
-(void) sort;
{
[prices sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
}
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)
{
h = prices[0];
l = prices[2];
high = h;
low = l;
}
-(void) print
{
NSLog(#"open: %#",open);
NSLog(#"close: %#",close);
NSLog(#"high: %#",high);
NSLog(#"low: %#",low);
}
#end
The running program outputs only:
2013-08-05 10:21:08.546 prog1[1314:303] (
12,
13,
14,
15,
15
)
open: (null)
close: (null)
high: (null)
low: (null)
I realize that this is probably a really basic question but I would appreciate your help a lot and I already thank you if you read until this point ;)
You have created two distinct, completely unrelated objects prices and myVals:
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
What you probably meant is to create a PPCalcVals object (which inherits
all methods from the superclass Array):
PPCalcVals *prices = [[PPCalcVals alloc]init];
[prices addValue:#12]; // invokes `addValue` method from superclass "Array"
// ...
[prices print]; // invokes `print` method from "PPCalcVals"
You also have to implement init in the PPCalcVals class in such a way
that it calls the "designated initializer" initWithName in the superclass.
I have one question. Where did you make calls for the functions
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c;
Because all I can see is that these functions are not called. So the properties high, low, open & close are not yet assigned and thus they return Null.
Also may I know the reason why are you overriding the parameters inside above mentioned functions?
o = prices[0];
c = prices[2];
and
h = prices[0];
l = prices[2];

how to create and allocate a C buffer as part of an objective C class

best to explain with an example:
in my AudioItem.h
#define ITEM_CAPACITY 100
typedef struct DataStruct {
void * content;
UInt32 size;
} DataStruct;
typedef DataStruct *DataStructRef;
#interface AudioItem : NSObject
{
DataStructRef data;
}
#property (assign, readwrite) DataStructRef data;
in AudioItem.m
#synthesize data;
-(id)initWithID:(NSString *)itemID
{
self = [super init];
data->content = malloc(ITEM_CAPACITY);
return self;
}
The above code looks a lot like this one, but I get a BAD_EXEC_ERROR.. how come? The reason why I would like to use a C buffer rather than some NSMutableData or whatever is b/c I've tried using NSMutableData and I feel like it's slowing down my real time application
it fails because data is a null pointer when you set its content.
the easy way to do this is:
enum { ITEM_CAPACITY = 100 };
typedef struct DataStruct {
char content[ITEM_CAPACITY];
UInt32 size;
} DataStruct;
#interface AudioItem : NSObject
{
#private
DataStruct data;
}
#implementation AudioItem
- (id)initWithID:(NSString *)itemID
{
self = [super init];
if (0 == self) return;
data.size = ITEM_CAPACITY;
return self;
}

passing the static variable as an argument->Objective C

c++ code
--------
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
public:
static int a;
void set(int s)
{
a=s;
cout<<a<<endl;
}
void setData(int f)
{
cout<<"I am "<<f<<" years old!!!"<<endl;
}
};
int A::a=0;
int main()
{
A* ab=new A();
ab->set(10);
ab->setData(ab->a);
return 0;
}
I am trying to get the same output for
this equivalent Objective C code.
main.m
---------
#import <Foundation/Foundation.h>
#import "A.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
A* ab = [[A alloc]init];
[ab set:10];
[ab setData:ab.a]; //getting error when passed ab->a or ab.a as an argument
[pool drain];
return 0;
}
A.h
---
#import <Foundation/Foundation.h>
#interface A : NSObject {
}
-(void)set:(int)s;
-(void)setData:(int)f;
#end
A.m
----
#import "A.h"
#implementation A
static int a;
-(void)set:(int)s
{
a=s;
NSLog(#"%d\n",a);
}
-(void)setData:(int)f
{
NSLog(#"%d",f);
}
#end
Error:Request for member 'a' in something not a structure or union.
There are no static instance variables or methods in Objective C. What you want can be done with class methods and static file scope variables. Class methods are those methods sent to class objects rather than instances.
#interface AClass
{
}
+(int) a;
+(void) setA: (int) newValue;
#end
// A.m
static int aStorage = 0;
#implementation AClass
+(int) a
{
return aStorage;
}
+(void) setA: (int) newValue
{
aStorage = newValue;
}
#end
// To use:
int something = [AClass a];
[AClass setA: something * 2];
// Or dot syntax if you prefer
AClass.a = AClass.a * 2;
First, declaring a static int in your implementation file doesn't magically make it a member of class A; your ObjC class A has no member variables.
Second, ab->a isn't how you would access the member of a class in ObjC. Once you have a member, write a getter for a, and use a method call to access it. (Or if you really want it to be static, don't add a member, and just add a getter that returns the static variable.)

static behaviour->objective C

I have this static declaration of m_pData=1099656 in a class.
In main NSLog(#"Testing:%d",m_pData);
Its printing me 0.
How to get the same value of m_pData in the class in the main function too.
I cant use obj.m_pData or obj->m_pData to acces the variable.
EDITED:
test2.m
----------
#import <Foundation/Foundation.h>
#import "data_derived.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
data* dat = [data alloc];
requestSession* session = [requestSession alloc];
[session init];
[dat TxCreateImage:RM_REQUEST_SESSION];
NSLog(#"Testing:%d",m_pData); //the static variable is not printing the value its holding.Its printing Zero.If printed the same variable inside the class it gives some numbers.
[dat dataBuffer:&m_pData withLen:&m_uDataSize]; //here the actual values of static values are not passed.when printed both of them contains zero values.
[pool drain];
return 0;
}
data.h
--------
#import <Foundation/Foundation.h>
#import "remote.h"
static int m_nMessageId; //Message ID
static int m_uSessionId; //Session ID
static int m_chSequenceChar; //Sequence ID
static int* m_pData; //Integer buffer to carry data
static int m_uDataSize; //Datasize
#interface data : NSObject {
#public
}
- (id)initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize;
+ (void)initialize;
- (void)dealloc;
- (id) dataBuffer:(int**)m_Data withLen:(int**)uLen;
- (BOOL) TxCreateImage:(int)messageId;
#end
data.m
---------
#import "data.h"
#define ENCODED_MSG_DATA_OFFSET 8
#implementation data
+ (void)initialize
{
m_uSessionId = 0;
m_chSequenceChar= 0;
// Initialize values from derived class
m_nMessageId = 0;
m_pData = 0;
m_uDataSize = 0;
}
- (id) initWithID:(int) uMessageId withData:(id)pData withSize:(size_t) uDataSize
{
if(self=[super init])
{
// Initialize the member variables
m_uSessionId = 0xFF;
m_chSequenceChar= 10;
// Initialize values from derived class
m_nMessageId = uMessageId;
m_pData = (int*)pData;
m_uDataSize = (int)uDataSize;
}
NSLog(#"Data size:%d",uDataSize);
NSLog(#"m_pData:%d",m_pData);
NSLog(#"pData:%d",pData);
return self;
}
- (id) dataBuffer:(int**)m_Data withLen:(int**)uLen
{
if ( m_uDataSize <= RMH_MAX_ENCODED_LENGTH )
{
int abBigEndian[RMH_MESSAGE_MAX_SIZE];
memcpy(abBigEndian,m_Data,m_uDataSize);
NSLog(#"m_Data:%d",*m_Data);
NSLog(#"abBigEndian:%d",abBigEndian);
uLen += ENCODED_CRC_BYTE_LEN + 1;
NSLog(#"%d",*uLen);
}
NSLog(#"END!");
return self;
}
- (BOOL) TxCreateImage:(int)messageId
{
char pData[4096];
sprintf(pData,"%x %d %d %d %x",ASCII_STX,m_uSessionId,m_chSequenceChar,m_nMessageId,ASCII_ETX); //uLen = ENCODED_MSG_DATA_OFFSET;
NSLog(#"%s",pData);
return YES;
}
- (void)dealloc
{
[super dealloc];
}
#end
data_derived.h
---------------------
#import <Foundation/Foundation.h>
#import "data.h"
#define DECLARE_RS232_NEWMSG(ClassID)\
enum \
{ \
ID = ClassID \
}; \
#interface requestSession : data {
#public
DECLARE_RS232_NEWMSG(RM_REQUEST_SESSION);
struct RMH_REQUEST_SESSION_MSG st;
}
-(id)init;
-(void)dealloc;
#end
data_derived.m
---------------------
#import "data_derived.h"
#implementation requestSession
- (id)init
{
size_t asize = sizeof(st);
st.uDeviceID = RS232_PROTOCOL_DEVICE_ID;
st.uProtocolVersion = RS232_VERSION;
memset(st.uReserved,0x00,sizeof(st.uReserved));
NSLog(#"Address of the structure:%d",&st);
self=[super initWithID:ID withData:(id)&st withSize:asize];
if (self) {
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
#end
Don't place your static members in .h file. Move them to data.m.
Also about static keyword - in C (and Objective C, which is clear superset to C), when using static with global variables (like you do), it only indicates that this variables will be local to the file you declared these variable in. So global variables anyway have only one instance, with static modifier or without. If you don't use static, then you can access these variables from other files with external declaration, like:
// file1.m
int variable = 4;
// file2.m
external int variable; // variable == 4
That's why your code is printing you 0. m_pData in test2.m is not the same m_pData you have in data.m. Without static modifier you would get a linker error.
And you might want to write getters/setters for static members. Like:
+ (int *)pData {
return m_pData; // or smth like memcpy
}

Obj-c method override/polymorphism problem

Ok, so I'm using Objective-C. Now, say I have:
TopClass : NSObject
- (int) getVal {return 1;}
MidClass : TopClass
- (int) getVal {return 2;}
BotClass : MidClass
- (int) getVal {return 3;}
I then put objects of each type into an NSMutableArray and take one out. What I want to do is run the getVal func on the appropriate object type, but when I put
id a = [allObjects objectAtIndex:0];
if ([a isKindOfClass:[TopClass class]])
{
int i;
i = [a getVal];
}
I get firstly a warning about multiple methods called getVal (presumably because the compiler can't determine the actual object type until runtime). But more seriously I also get an error "void value not ignored as it should be" and it won't compile.
If I don't try and use the return from [a getVal] then it compiles fine e.g.
[a getval]; //obviously no good if I want to use the return value
It will also work if I use isMemberOfClass statements to cast the object to a class before running the function e.g.
if ([a isMemberOfClass:[BotClass]) i = [(BotClass*) a getVal];
But surely I shouldn't have to do this to get the functionality I require? Otherwise I'll have to put in a statement for every single subclass, and worse have to add a new line if I add a new sub class, which rather defeats the point of method overriding doesn't it?
Surely there is a better way?
Since a BotClass is a MidClass and a MidClass is a TopClass, you could just set the type of a to TopClass*.
TopClass* a = [allObjects objectAtIndex:0];
if ([a isKindOfClass:[TopClass class]]) {
int i;
i = [a getVal];
}
The better way is to add -getVal to the #interface and #import it. Then the compiler will know such this method is likely to return an int and won't complain even if a is an id. Make sure the method name won't coincide with others, though.
(BTW, in ObjC, getters won't be named as -getFoo. The convention is just call it -foo.)
Your code compiles without any warning:
#import <Foundation/Foundation.h>
#interface TopClass : NSObject
{
}
- (int) getVal;
#end
#interface MidClass : TopClass
{
}
- (int) getVal;
#end
#interface BotClass : MidClass
{
}
- (int) getVal;
#end
#implementation TopClass
- (int) getVal {
return 1;
}
#end
#implementation MidClass
- (int) getVal
{
return 2;
}
#end
#implementation BotClass
- (int) getVal
{
return 3;
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *array = [NSMutableArray array];
[array addObject:[[[TopClass alloc]init]autorelease]];
[array addObject:[[[MidClass alloc]init]autorelease]];
[array addObject:[[[BotClass alloc]init]autorelease]];
for (int objectNumber = 0; objectNumber < [array count]; objectNumber++) {
id a = [array objectAtIndex:objectNumber];
if ([a isKindOfClass:[TopClass class]])
{
int i = [a getVal];
NSLog(#"%d",i);
}
}
[pool drain];
return 0;
}
The test "isKindOfClass" is always true in this case, as MidClass and BotClass inherit from TopClass.
Are you sure the compiler knows about the method signatures that you call?