Create an array that hold custom class object - ios

I have class, that have several properties, it look like this:
#interface PlaceHolder : NSObject
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *description;
#property (strong, nonatomic) NSString *webPage;
#property (strong, nonatomic) NSNumber *latitude;
What i need is, to create an array, that hold objects of that class. Obvious, properties will not be nil and will be different each time. So, that array must have several hundreds of PlaceHolder object, and it should be possible to get information for any of that object and it properties. But, when i try to create that array, in NSLog i see that it contain only (NULL) objects. This is how i try too add object to array:
In header i wrote:
#property (strong, nonatomic) PlaceHolder *place;
Then:
self.place = [[PlaceHolder alloc]init];
self.place.name = nameString;
NSLog(#"%# name???", self.place.name);
[self.placeObjectsArray addObject:self.place];
self.place.name is not nil, and still, array is empty. Well, its not true, it not empty but, it only contains (null) objects. How to fill array with objects of my class?
Any advice would be appreciated, thanks!
UPDATED:
I init array like this -
-(id)initWithDelegate:(id)delegateObj{
...
self.placeObjectsArray = [NSMutableArray array];
...
return self;
}
UPDATED: Now, when i try to init-alloc array in same method (instead of setting #property and strong relation) i can see it in NSLog. I wonder why it won't happen when i use my array, that set as property..

You need to alloc-init your Mutable Array ;
NSMutableArray *myArray = [[NSMutableArray alloc]initWithObjects:self.place,nil];
or simply
NSMutableArray *myArray = [[NSMutableArray alloc]init];
Then you could add objects with a for loop or whatever you need, using the following :
for ( YOURINSTRUCTION )
{
[myArray addObject:YOUROBJECT]
}

I recommend to lazy instantiate the array, that way it will only get instantiated when really needed. Since you are setting the array as a property, you can override the getter method for it like this:
- (NSMutableArray *)placeObjectsArray
{
if (!_placeObjectsArray) _placeObjectsArray = [[NSMutableArray alloc] init];
return _placeObjectsArray;
}
With this, you can call [self.placeObjectsArray addObject:self.place] anywhere in your code and the array will always be initialized when needed.

Related

modifying copy of array object affect object stored in the array

I have object copying issue.
#property (nonatomic,strong)ITEM *editingItem;
self.editingItem= nil;
self.editingItem = [[self.ItemsArray objectAtIndex:indexPath.row-1] copy];
self.editingrowIndex = indexPath.row;
When I assign some object to editingItem in didselect table row and start editing it in textfield delegates when i change the object property values then it is changning in the object stored in an array.but i want only editingItem object should have new values.But without updating array new values are getting stored from editingItem to object in the array.
The implementation provided by the OP, in the other answer is incorrect, as it does not copy the instance variables; rather it creates another reference to them. This would explain the issues the OP is seeing in his question (where that code should have been presented, and not in a separate answer).
Here is a better implementation:
- (id)copyWithZone:(NSZone *)zone
{
Item *copy = [[Item allocWithZone:zone] init];
copy->_nombre: [_nombre copy];
copy->_linea = [_linea] copy];
copy->_tags = [_tags copy];
copy->_htmlSource = [_htmlSource copy];
return copy;
}
Note that the instance variable copy statements provided in the other implementation is correct (aside from the missing copy call), but it won't work for private instance variables (a common occurrence), so I always stick to the form copy->_instanceVariable = [_instanceVariable copy];.
Also note that if the object derives from something other than NSObject then first statement should be:
Item *copy = [super copyWithZone:zone];
instead of:
Item *copy = [[Item allocWithZone:zone] init];
Further notes:
I find it highly suspect that you are keeping NSMutableString objects as instance variables. That is fairly unusual in my experience, having only used them as temporary objects for building immutable strings. I suspect you are not using the correct data type to hold this data.
#import <Foundation/Foundation.h>
#interface Item : NSObject <NSCopying>
#property (strong, nonatomic) NSString *nombre;//nombre del medicamento
#property (strong, nonatomic) NSString *linea;//linea a la que pertenece
#property (strong, nonatomic) NSMutableString *tags;//palabras por las que se puede encontrar en el buscador
#property (strong, nonatomic) NSString *htmlSource;//código html para mostrar su contenido
#property (strong, nonatomic) NSMutableString *obj;
-(id) copyWithZone: (NSZone *) zone;
#end
#implementation TempObject
-(id) copyWithZone: (NSZone *) zone
{
Item *copy = [[Item allocWithZone: zone] init];
[copy setNombre: self.nombre];
[copy setLinea: self.linea];
[copy setTags: self.tags];
[copy setHtmlSource: self.htmlSource];
return copy;
}
Override CopywithZone method in your item class and set each and every property inside that method.It is the solution for copying object.When you do allocwithzone and init,the new object is created with new address and old values which you have to set manually in copywithzone: method.So duplicate instance with old values.It is perfect solution working for me.

Why do objects not get added to my array?

I have two custom classes: FSGame and FSEvent. FSGame has an ivar that should be an NSMutableArray of FSEvent objects.
Here's FSGame.h:
#interface FSGame : NSObject
#property (strong, nonatomic) NSMutableArray *players;
#property (strong, nonatomic) NSString *startTime;
#property (strong, nonatomic) NSString *endTime;
#property (strong, nonatomic) NSMutableArray *gameEvents;
#end
And here's my FSEvent.h:
#interface FSEvent : NSObject
#property NSInteger ID;
#property NSInteger pointTo;
#end
I use
#property (strong, nonatomic) FSGame *game;
to keep an instance of FSGame in my AppDelegate. Then, in my application:didFinishLaunchingWithOptions: I create an instance of FSGame so it can be filled throughout the "game".
_game = [[FSGame alloc] init];
Then, in one of my view controllers, I alloc and init an instance of FSEvent and then attempt to add it to the .gameEvents array:
[appDelegate.game.gameEvents addObject: event];
But something seems to go wrong here because if, from another view controller, I try to get access to that object, it will be nil:
FSEvent *previousEvent = [appDelegate.game.gameEvents lastObject];
if (previousEvent == nil) {
NSLog(#"previousEvent is NIL!");
}
What am I missing here?
It's hard to say with the code that's been shown, but it's possible that you never create the mutable array gameEvents and it's nil when you try to access it or add events to it. Make sure you're creating it somewhere, probably in FSGame's -init:
_gameEvents = [NSMutableArray array];
You need to instantiate the arrays, this does NOT happen when you use
_game = [[FSGame alloc] init];
Try using a lazy instantiation in your FSGame class, add this code
-(NSMutableArray *)gameEvents{
if(!_gameEvents){
_gameEvents = [NSMutableArray array];
}
return _gameEvents;
}
And that should be enough, also make sure of accesing by self.gameEvents and not by _gameEvents!
_game.gameEvents is a pointer to a mutable array. It is not initialized, so its value is nil. There are no any mutable array to add objects to.
You can create it when needed writing this method in FSGame.m:
-(NSMutableArray*) gameEvents {
if ( ! _gameEvents ) {
_gameEvents = [NSMutableArray array];
}
return _gameEvents ;
}

Add UIImageView objects to an array (Objective C)

I've read the other threads about arrays of UIImageView-objects, but I can't get it to work. Note that I'm completely new to Objective-c.
I have some UIImageView objects declared in the .h - file like this:
#property (weak, nonatomic) IBOutlet UIImageView *obj1;
I also have an array declared at the same place:
#property (weak, nonatomic) IBOutlet NSArray *arr;
In the viewDidLoad-method I want to add obj1 to arr. How can I do that?
I've tested to initialize arr and add objects to it, but it doesn't work.
_arr = [[NSMutableArray alloc] init];
[_arr addObjects: obj1];
Hank
make sure in debugger that _arr is not nil. You need to declare it as
#property (strong, nonatomic) NSMutableArray *arr;
since arr is not a ui control on view controller, you do not need to add IBOutlet.
Also, your view controller posses it, so it should be strong rather than weak.
You also should use NSMutableArray instead of NSArray, since only the first one can be used for adding objects, and this is how you say to the compiler of the type of this object
Change
#property (weak, nonatomic) IBOutlet NSArray *arr;
to
#property (strong, nonatomic) NSMutableArray *arr;
If you want to add UIImageView Object in your Array you can do that.But the thing is if your want to add object in NSArrar after its initialization than you have to declare NSMutableArray as you can add and remove object in that than the addObject method would work.
Also their is no need to declare NSArray of NSMutableArray as IBOutlet.

Deep copy of an NSMutableArray of custom objects with NSMutableArray members

I'm trying to make a deep copy of an NSMutableArray whose objects are instances of a custom class similar to this:
#interface CustomParent : NSObject
#property NSInteger Id;
#property (strong, nonatomic) NSString *IdStr;
#property (weak, nonatomic) NSDate *Date;
#property (strong, nonatomic) NSMutableArray *CustomChildren;
#property (strong, nonatomic) CustomType *Type;
#property float Value;
#end
I know there are lots of posts dealing with copying objects, but I don´t find examples for getting a complete copy of objects with collection members or properties. NSMutableArray *dstArray = [[NSMutableArray alloc] initWithArray:srcArray copyItems:YES]; raises an exception involving the copyWithZone method.
How can I do this? Thanks!
In order to deep copy the content of the array
[[NSMutableArray alloc] initWithArray:srcArray copyItems:YES];
will send copyWithZone: to every object inside the collection. If they don't respond to this selector, you'll get a crash.
Have your CustomParent class to conform to the NSCopying protocol and you're done.
Here's some extra info on how do achieve it: Implementing NSCopying

Missing property after copy (iOS)

My project is ARC-enabled, I have two models something like:
Category:
#interface Parent : NSObject
#property (assign, nonatomic) Category *parent;
#property (strong, nonatomic) NSArray *children;
#property (strong, nonatomic) NSArray *subCategories;
#end
Product:
#interface Child : NSObject
#property (strong, nonatomic) NSString *name;
#property (assign, nonatomic) Category *category;
#end
To avoid reference loop, and to deploy on iOS 4.x, I set the parent property of Child as assign but not weak.
From JSON data, I can get a tree containing my categories and products. When I use the tree to enumerate, all the things went perfect. And I have a recursion method to search products with name matching a keyword. The method is something as followed:
- (NSArray *)productsWithKeyword:(NSString *)keyword
{
NSMutableArray *filteredProducts = [NSMutableArray array];
for (Category *cat in self.children) {
NSArray *subResult = [cat productsWithKeyword:keyword];
[filteredProducts addObjectsFromArray:subResult];
}
return [filteredProducts copy];
}
The problem is when I'm using the returned array, I can get the right category property. But from the second time and on, the category property becomes 0 (caught from debugger).
So, what's the problem? And what's the fix to the problem?
To avoid a reference loop you want to make one object have a weak reference to the other not have both with weak references to each other. I think what's happening in this case is that the product doesn't own the category and the category doesn't own the product, so ARC releases both of the objects assuming no one claims them.
FIX: make one of these objects the "parent" of the other.

Resources