Objective C: array of class object as property - objective-c

Is it possible in an Objective-C class to store an array of instances of another class as a property?
Simple example: I have a class called "Classroom" and a class called "Students".
#interface Student
#property int m_id;
#end
...
#interface Classroom
#property Student *m_students[20]; // this causes a compilation error: property cannot have an array or function type 'Student *[20]'
#end
How can I do the equivalent of this?

Use a NSArray or NSMutableArray instead:
#interface Classroom
#property NSMutableArray *m_students; // this causes a compilation error.
#end
Then in your implementation:
Student *student = [[Student alloc] init];
[self.m_students addObject:student];
NSArray (and it's subclass NSMutableArray) can contain any Objective-C object. And you can even mix them in the same array.

Related

How can I add values to NSArray of different class A from Class B

I have my .m file where I need to update NSArray of class B, where I should be able to the values from that array.
I am trying this in Class A
// TabHeaderViewModel.h
typedef enum {
UsePassHeaderType,
ManageCardType
}TabHeaderType;
NS_ASSUME_NONNULL_BEGIN
#interface TabHeaderViewModel : NSObject
#property (nonatomic) TabHeaderType headerType;
- (instancetype)initWithHeaderType:(TabHeaderType)headerType;
- (NSArray *)dataSourceForHeaderModel;
#end
And now I want to access datatSourceForHeaderModel from class B in its .m file
TabHeaderViewModel *headerVM = [[TabHeaderViewModel alloc]initWithHeaderType:ManageCardType];
headerVM.dataSourceForHeaderModel = self.dataSourceForHeader;
// getting error - No setter method 'setDataSourceForHeaderModel:' for assignment to property
either code in interface
#property (nonatomic) NSArray *dataSourceForHeaderModel;
or
-(void)setDataSourceForHeaderModel:(NSArray*)datasource;
also do your implementation when you define a method if there is processing.
But its easier to go with the property solution.

Class Method Exposure and Property Definition

I have an academic question about Class Method exposure. There is something that I obviously don't understand about this and would like some clarification from those in the know.
Background:
I have a simple example of two classes named ViewController and ClassB. Class B contains an array with a method named returnArray. The ViewController accesses the array's data. I have exposed the returnArray method in the ClassB.h file.
Question:
Why is it that I can access the array's data in ViewController without having to define a property? I thought that the property would create a getter to allow access to the array. My example (only exposing the method) allows me to access the data without the creation of the #property.
Class Method:
ClassB.h
#interface ClassB : UIViewController
+(NSArray *) returnArray;
//#property (nonatomic, strong) NSArray *returnArray;
ClassB.m
#implementation ClassB
+(NSArray *) returnArray
{
NSArray *locationArray = #[#"Place1", #"Place2"];
return locationArray;
}
ViewController.m
- (void)viewDidLoad
{
NSArray *location = [ClassB returnArray];
NSLog (#"The count of the location is %d", [location count]);
NSLog (#"The second item in testArray is %#", location[1]);
}
Instance method: After reviewing answers
ClassB.h
*/
{
#private
NSArray *returnArray;
}
- (void)setReturnArray:(NSArray*)returnArray;
-(NSArray *) returnArray;
*/
#property (nonatomic, strong) NSArray *returnArray;
#end
ClassB.m - no change
ViewController.h - no change
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Create instance of ClassB
ClassB *classB = [ClassB new];
//Access the instance of returnArray
NSArray *location = [classB returnArray];
NSLog (#"The count of the location is %d", [location count]);
NSLog (#"The second item in testArray is %#", location[1]);
}
#property is a shorthand notation for creating an instance variable and associated accessor methods (with defined access / modification criteria).
What you have is a class method, which internally creates an array and returns it.
That's why you call [ClassB returnArray]; instead of [instanceOfB array];.
These are completely different things. If you wanted to use a property then you would need to create an instance of ClassB and then access the property. This would work, assuming that the array was created when the instance of ClassB was created.
Wain's answer addresses the difference between #property and Class methods, so it's worth a read. My answer assumes you know the difference between class and instance methods, and focuses on the difference between creating a #property versus creating an instance variable with an associate setter and getter.
The reason is because returnArray is a public method that returns an NSArray object on your ClassB.
A #property is merely a convenient way of creating three things at the same time: an instance variable, a setter, and a getter. It has the added bonus of allowing dot-syntax.
But at the end of the day, dot-syntax aside, all you're doing by declaring a #property is equivalently equal to this:
#interface ClassB : NSObject {
#private
NSArray *returnArray;
}
- (void)setReturnArray:(NSArray*)returnArray;
- (NSArray*)returnArray;
This is the same as this:
#property NSArray *returnArray;
Except of course, the dot syntax.
When you do:
NSArray *myArray = classB.returnArray;
You're not actually directly accessing the array you created when you declared the #property.
What you're doing is calling the getter method that was automatically generated when you declared the #property.

Messaging between two classes

I have a basic question about fetching values through different classes.
I have a classA which fills an array (If i print it out it is not empty).
LATER in class B i want to load this Array: I call a function from class A which returns the Array of class A. But in class B if i call my new array then is it null.
I am a bit confused, because i think i retain every value of the array, but its still null. I tried also a lot of different possibilities. I think its a basic OOP syntax fault i produce?!
//CLASS_A.h
#interface classA {
NSMutableArray* buoyArray;
}
#property (nonatomic, retain) NSMutableArray * buoyArray;
-(NSMutableArray*)getArray:(NSMutableArray*)_array;
//CLASS_A.m
...
-(NSMutableArray*)getArray:(NSMutableArray*)_array {
_array=buoyArray;
return _array;
}
//CLASS_B.h
#import "CLASS_A.h"
#class classA;
#interface classB ...
classA *mapSource;
NSMutableArray * buoyArray;
}
#property(nonatomic,retain) classA *mapSource;
//CLASS_B.m
buoyArray=[mapSource getArray:buoyArray];
NSLog(#"%#",buoyArray);
Actually you you are making new object of class A by calling alloc so by init it reintialize all properties values for that instance.
What you need,if you are pushing class B over class A then, fetch existing class A object from stack, by using this line.
mapSource = (ClassA *)[self.navigationController.viewControllers objectAtIndex: [self.navigationController.viewControllers count]-2];
then call this
buoyArray=[mapSource getArray:buoyArray];
NSLog(#"%#",buoyArray);

Question about class member declarations

I`m new to the Objective-C world, so I have a couple of questions about class member declarations. Please notice the comments in the code below:
In header file I have code such
#interface MyClass : NSObject {
//what we points here ? Object or something else ?
NSString *myString;
}
// In interface we declare NSTring *myString in #property declaration is (NSString *) myString.
// What is the difference here ? Why we don`t use the same declaration as above ?
#property(nonatomic, retain) (NSString *) myString;
#end
The thing you're missing is that instance variables (defined between curly braces) are not accessed from the outside (i.e. other objects). To do that - you have to define a property for the instance var (by using #property keyword) to know how outside objects can access a value of given instance var. Also in implementation file (.m) you have to #synthesize instance variable accessor methods for it's appropriate property. Please note that #property declaration not only defines what it holds (NSString *myString), but also how it's being accessed and set. You can define property as read only (#property (readonly)...) or accessible from few threads at a time (#property (nonatomic)).
Also - if your instance var is named differently from the property it represents to other objects - you must show that in implementation file (#synthesize propertyName=instanveVariableName)
update
MyClass *myInstance = [[MyClass alloc] init];
[myInstance myString]; // returns myString property
Try running above 2 lines of code without #property and you'll see the difference.
Actually you are defining a Property of yar class.#interface MyClass : NSObject {
//public object
#public
NSString *myString;
//private object
NSString *myString2;
}
class structure for obj-c
.h file
#interface MyClass : NSObject {
//Your member variable;
// you member objects;
}
//property declarations
//function declarations
#end
so it should look like
#interface MyClass : NSObject {
NSString *str;
}
#property(nanatomic,retain) NSString *str;
-(void)method;
#end

#Synthesize array of class objects?

Having some difficulty with what I thought would be straight forward. I am trying to make an array of class objects but running into different problems. The goal was to create one class that held an array of another class of objects.
Any help appreciated:
// Basic class unit
#interface MobRec : NSObject {
NSString *MName;
int Speed;
}
#end
// Master Class holding an array of units
#interface MobDefs : NSObject {
MobRec *MobInfo;
}
#property(retain) MobRec *MobInfo;
#end
#synthesize MobInfo;
1) From reading it seems I should create and NSMutableArray but how do you declare an NSMutableArray of custom class objects? All iterations I try cause errors. Previously I had predefined the size in the class as MobInfo[20]; but that didnt seem to be good for anything.
2) How do you properly #Synthesize an array of class objects?
I think you misunderstand what #synthesize does. It creates accessor methods to get and set the property (i.e., it would create a getter method to return that NSMutableArray and a setter method to allow you to replace it with another NSMutableArray). To create an NSMutableArray, you would just create one like any other object in that class's initializer.
NSMutableArray doesn't have any type checking as you add (or read) from it, so you can add any objects you want to it.
In this case I'd have something like:
// MobRec Class
#interface MobRec : NSObject {
NSString *mName;
int speed;
}
#property(retain)NSString *name;
#property(assign)int speed;
#end
#implementation MobRec
#synthesize mName, speed;
#end
// MobDefs Class
#import "MobRec.h"
#interface MobDefs : NSObject {
NSMutableArray *mobInfo;
}
#property(retain) NSMutableArray *mobInfo;
#end
#implementation MobDefs
#synthesize mobInfo;
- (id)init {
mobInfo = [[NSMutableArray alloc] init];
MobRec *aNewMobRec = [[MobRec alloc] init];
[mobInfo addObject:aNewMobRec];
[aNewMobRec release];
}
I've included the basics for adding to the array as well so you can see how its used. Oh and don't forget you have to release the MobInfo in the dealloc method.
But mostly look at NSMutableArray
Your MobDefs class is not necessary, you can use an NSMutableArray directly. NSArray can hold objects of any type, and is declared in just the same way as any other object (such as your MName property).