How to add new array element from another method in Objective-c? - objective-c

I have some array( #private NSArray employees []; ) and method , which take string parameter( name of employees) and put this parameter in array. How I can do this with Objective-c?

You could do the following,
Create a property,
#property (nonatomic) NSMutableArray *array;
Initialise the array in your init method or somewhere else appropriate,
self.array = [[NSMutableArray alloc] init];
Your method could look something like this,
- (void)addEmployeeName:(NSString *)employeeName {
[self.array addObject:employeeName];
}

You can create a class Employee and use a type with your array.
For example:
NSArray<Employee*> * employees = [[NSArray alloc] init];
At this point, your method will be:
-(Employee *)createEmployee:(NSString *)name{
Employee *myEmpl = [[Employee alloc]init];
[myEmpl setName:name];
return myEmpl;
}
and you can add the object (of type Employee) in your array in this way:
[employees addObject:[self createEmployee]];
the same thing is possibile with an object of type NSString instead of Employee.
You can also avoid defining the type in your NSArray because Objective-C use the type inference

Related

Make variable names variables (Objective-c)

I'd like to do something like this:
.h
LocalRoom* zone1;
LocalRoom* zone2;
LocalRoom* zone3;
LocalRoom* zone4;
etc....
.m
NSString *number = 1;
NSString *variable = [NSString stringWithFormat: #"zone%#", number]
[[variable variableValue] broadcastChatMessage:redStringPrefix fromUser:#"server"];
emulating:
[zone1 broadcastChatMessage:redStringPrefix fromUser:#"server"];
How do I do this? Is it possible?
Given names like “zone1”, “zone2”, etc., I would make an array rather than a dictionary. Either way, these should not be separate variables.
#property(strong) NSMutableDictionary *zones;
-(id)init {
....
_zones = [[NSMutableDictionary alloc] init];
....
}
aZone = [_zones objectForKey: [NSString stringWithFormat:#"zone%d", someZoneNumber]];
... etc ...
You can do something similar using Key-Value Coding. You would write
[[self valueForKey:variable] broadcastChatMessage:redStringPrefix fromUser:#"server"];
rather than
[[variable variableValue] broadcastChatMessage:redStringPrefix fromUser:#"server"];
This would of course require that zone1, zone2, etc. are instance variables (or properties) on self.

Array object doesn't retain it's data

I have an object that contains a array. On initialization of this object, the array is allocated and properly filled (as I can see in the debugger). This object is use to manage elements in a single view.
My problem is that when I try to call the object a second time, the array (and all other parameter of this object) are nil yet they have a memory address (again as seen in debugger).
This is the .h of the object in question :
#import <Foundation/Foundation.h>
#import "ObjectDef.h"
#import "AbstractNode.h"
#interface RenderingMachine : NSObject
{
NSMutableArray* _objectID; // pair list
NSMutableArray* _objectList; // node list
ObjectDef* _defs; // definition of pairs
unsigned int _size;
unsigned int _edgeSize;
AbstractNode* _lastNode;
}
-(void) InitializeMachine;
-(bool) AddObjectByIndex:(int)index :(float)x :(float)y :(float)originX :(float)originY;
-(bool) AddObjectByType:(NSString*)type;
-(NSMutableArray*) GetObjectID;
-(NSMutableArray*) GetObjectList;
-(unsigned int) Size;
-(void) DrawAllNode;
-(int) ComputePar;
-(void) ComputeLastEdge:(int)edgeCount;
//+(RenderingMachine*) GetMachine;
#end
My main problem right now is with _defs which is filled in InitDefinitions :
-(void) InitializeMachine
{
_defs = [[ObjectDef alloc] init];
[_defs InitDefinitions];
_objectID = [[NSMutableArray alloc] init];
_objectList = [[NSMutableArray alloc] init];
_objectID = [NSMutableArray arrayWithObject:[_defs GetPair:3]]; // adding the field node ID
AbstractNode* rootNode = [[FieldNode alloc] init];
_objectList = [NSMutableArray arrayWithObject:rootNode]; // adding the field node as root node
_size = 1;
_edgeSize = 0;
}
What I'd like to know is if might be a bad alloc / init call or could it be a problem with the ARC of xcode because this particular file compiles with ARC (the other being ignore with "-fno-objc-arc").
Also, as mentionned the _defs is problematic, but all the property declared under #interface are having the same problem.
First you create a retained object with _objectID = [[NSMutableArray alloc] init];
and then you overwrite it with an autoreleased one _objectID = [NSMutableArray arrayWithObject:[_defs GetPair:3]];
to add the object better use [_objectID addObject:[_defs GetPair:3]];
same thing with the _objectList Object

Add a tag to NSMutableArray

Is it possible to set a tag for an NSMutableArray? I have to somehow determine, in an array of arrays, the single array which needs to be rewritten, and if I could just set the tag to that inner array to 1 (or some other number), this would be extremely easy.
Example:
NSMutableArray* outerArray = [NSMutableArray new];
NSMutableArray* innerArray1 = [NSMutableArray new];
NSMutableArray* innerArray2 = [NSMutableArray new];
NSMutableArray* innerArray3 = [NSMutableArray new];
NSMutableArray* innerArray4 = [NSMutableArray new];
[outerArray addObject:innerArray1];
[outerArray addObject:innerArray2];
[outerArray addObject:innerArray3];
[outerArray addObject:innerArray4];
//now let's say innerArray1 needs to be rewritten
//I would like to be able to do this
[innerArray1 setTag:100];
//then later, when I need to determine which of the arrays inside outerArray
//needs to be rewritten, I can just do this
for(NSMutableArray* temp in outerArray) {
if(temp.tag == 100) {
//do what I need to do
}
}
But you can't use setTag: with NSMutableArrays. What would be a workaround?
Arrays are ordered collections, so why don't you just keep track of which index needs to be rewritten.
When something happens such that the array at index 0 (which, in your example, would be innerArray1) of outer array needs to be written, cache index 0 -- as a property if this routine needs to span across separate methods.
Then, when it comes time to do the rewrite, consult the cached index. Retrieve the array to be rewritten like this: NSArray *arrayToRewrite = [outerArray objectAtIndex:cachedIndexToRewrite]; Or access it directly: [[outerArray objectAtIndex:cachedIndexToRewrite] replaceObjectAtIndex:whatever withObject:whatever];
You could use an NSMutableDictionary instead. The "tag" would just be the key and the array would be the value.
Use associated objects. You can even add a category to NSMutableArray that would add a tag property to them.
#interface NSMutableArray (TagExtension)
#property (nonatomic, assign) NSInteger tag;
#end
#implementation NSMutableArray (TagExtension)
#dynamic tag;
static char TagExtensionKey;
-(NSInteger)tag {
NSNumber *ourTag = (NSNumber *)objc_getAssociatedObject(self, &TagExtensionKey);
if( ourTag ) {
return( [ourTag integerValue] );
}
return(0);
}
-(void)setTag:(NSInteger)newTag {
objc_setAssociatedObject(self, &TagExtensionKey, [NSNumber numberWithInteger:newTag], OBJC_ASSOCIATION_RETAIN);
}
#end
See also: How to add properties to NSMutableArray via category extension?
Not sure why a dictionary is a bad idea here… as alternatives, you can:
remember the index
or if each entry is a unique array, you can simply refer to it by pointer:
NSArray * tagged = theArray;
for (NSMutableArray * at in outerArray) {
if (tagged == at) {
//do what I need to do
}
}
Make your inner arrays class variables. Then you can just access them as:
for(NSMutableArray* temp in outerArray) {
if(temp == self.innerArray1) {
//do what I need to do
}

Removing duplicates from array based on a property in Objective-C

I have an array with custom objects. Each array item has a field named "name". Now I want to remove duplicate entries based on this name value.
How should I go about achieving this?
I do not know of any standard way to to do this provided by the frameworks. So you will have to do it in code. Something like this should be doable:
NSArray* originalArray = ... // However you fetch it
NSMutableSet* existingNames = [NSMutableSet set];
NSMutableArray* filteredArray = [NSMutableArray array];
for (id object in originalArray) {
if (![existingNames containsObject:[object name]]) {
[existingNames addObject:[object name]];
[filteredArray addObject:object];
}
}
You might have to actually write this filtering method yourself:
#interface NSArray (CustomFiltering)
#end
#implementation NSArray (CustomFiltering)
- (NSArray *) filterObjectsByKey:(NSString *) key {
NSMutableSet *tempValues = [[NSMutableSet alloc] init];
NSMutableArray *ret = [NSMutableArray array];
for(id obj in self) {
if(! [tempValues containsObject:[obj valueForKey:key]]) {
[tempValues addObject:[obj valueForKey:key]];
[ret addObject:obj];
}
}
[tempValues release];
return ret;
}
#end
I know this is an old question but here is another possibility, depending on what you need.
Apple does provide a way to do this -- Key-Value Coding Collection Operators.
Object operators let you act on a collection. In this case, you want:
#distinctUnionOfObjects
The #distinctUnionOfObjects operator returns an array containing the distinct objects in the property specified by the key path to the right of the operator.
NSArray *distinctArray = [arrayWithDuplicates valueForKeyPath:#"#distinctUnionOfObjects.name"];
In your case, though, you want the whole object. So what you'd have to do is two-fold:
1) Use #distinctUnionOfArrays instead. E.g. If you had these custom objects coming from other collections, use #distinctUnionOfArray.myCollectionOfObjects
2) Implement isEqual: on those objects to return if their .name's are equal
I'm going to get flak for this...
You can convert your array into a dictionary. Not sure how efficient this is, depends on the implementation and comparison call, but it does use a hash map.
//Get unique entries
NSArray *myArray = #[#"Hello", #"World", #"Hello"];
NSDictionary *uniq = [NSDictionary dictionaryWithObjects:myArray forKeys:myArray];
NSLog(#"%#", uniq.allKeys);
*Note, this may change the order of your array.
If you'd like your custom NSObject subclasses to be considered equal when their names are equal you may implement isEqual: and hash. This will allow you to add of the objects to an NSSet/NSMutableSet (a set of distinct objects).
You may then easily create a sorted NSArray by using NSSet's sortedArrayUsingDescriptors:method.
MikeAsh wrote a pretty solid piece about implementing custom equality: Friday Q&A 2010-06-18: Implementing Equality and Hashing
If you are worried about the order
NSArray * newArray =
[[NSOrderedSet orderedSetWithArray:oldArray] array]; **// iOS 5.0 and later**
It is quite simple in one line
NSArray *duplicateList = ...
If you don't care about elements order then (unordered)
NSArray *withoutDUP1 = [[NSSet setWithArray:duplicateList] allObjects];
Keep the elements in order then (ordered)
NSArray *withoutDUP2 = [[NSOrderedSet orderedSetWithArray:duplicateList] array];
Implement isEqual to make your objects comparable:
#interface SomeObject (Equality)
#end
#implementation SomeObject (Equality)
- (BOOL)isEqual:(SomeObject*)other
{
return self.hash == other.hash;
}
- (NSUInteger)hash
{
return self.name;///your case
}
#end
How to use:
- (NSArray*)distinctObjectsFromArray:(NSArray*)array
{
return [array valueForKeyPath:#"#distinctUnionOfObjects.self"];
}

How to declare class array in objective c

I can declare NSMutableArray or NSArray but I want to declare class array. Let say user is a class so I can declare array as:
user* obj[10];
it is valid in Objective c, but I am not sure how I can set array capacity dynamically. Which we usually do with MutableArray as initWithCapacity:..
This is what I am doing with class:
user* objuser;
CustomOutput* output = [[CustomOutput alloc] init];
[objuser cutomSerialize:output];
NSMutableData* data = output.data;
But If I have array as:
NSMutableArray* aryUserObj;
I can't call cutomSerialize method from arryUserObj.
I want to Serialize all the userObj at ones and get a single NSData object.
The standard approach to serialize an array of objects is for you to define encodeWithCoder: and initWithCoder: in your User object:
#interface User: NSObject {
....
}
-(void)encodeWithCoder:(NSCoder*)coder ;
-(id)initWithCoder:(NSCoder*)coder;
#end
What you currently have in CustomSerialize should be in these methods.
Then, if you want to encode an object, you do
User* user=... ;
NSData* data=[NSKeyedArchiver archivedDataWithRootObject:user];
and decode it:
User* user=[NSKeyedUnarchiver unarchiveObjectWithData:data];
If you have an array of objects,
NSMutableArray* array=... ; // an array of users
NSData* data=[NSKeyedArchiver archivedDataWithRootObject:array];
and
NSArray* array=[NSKeyedUnarchiver unarchiveObjectWithData:data];
Iteration over array is done automatically.
Note also that you don't get the mutable array back, it's an immutable array.
NSMutableArray * users = [NSMutableArray array];
for (int i = 0; i < someNumber; ++i) {
User * aUser = [[User alloc] initWithStuff:someStuff];
[users addObject:aUser];
[aUser release];
}