Grab Object Propertys from NSMutableArray Objective - C VS C++ - objective-c

Hey there I'm new to objective c is there any way to grab and objects properties once it's in an NSMutable array.
like this:
so in c++ it would look like this
for (int i = 0; i < length; i++)
{
someArray[i].someClass.somePropertyInTheClass;
}
is there any possible way to do that with an NSMutableArray in OBJECTIVE -C
Thanks in advance all you pro objective c-ers!

There are two main ways to loop through an array in Objective-C. First, using an index:
NSInteger count = [array count];
for (int i; i < count; i++)
{
id object = [array objectAtIndex:i];
NSLog(#"%#", [object somePropertyInTheClass]);
}
Note that the the count is stored in a variable rather than in the for loop. This avoids having to recalculate the count each time through the loop.
A more concise method is with fast enumeration:
for (id object in array)
{
NSLog(#"%#", [object somePropertyInTheClass]);
}
Both versions are semantically equivalient, they both log each object's somePropertyInTheClass property in the array (assuming each object has a somePropertyInTheClass property). In both versions, id can, and should, be replaced with a specific class, eg NSDictionary * based on what you store in the array.
While fast enumeration is more concise, the approach with the counter is useful if you need to use the index for something other than accessing one array. Also, fast enumeration does not allow you to modify the array, even in another method, while looping. In most cases though, when iterating through an array, fast enumeration can be used.

Hey there I'm new to objective c is there any way to grab and objects
properties once it's in an NSMutable array.
The mere fact of being included in an array or other container doesn't prevent you from accessing the properties of an object. If the object you want is at index i, you can get the object simply:
Person *person = [arrayOfPeople objectAtIndex:i];
or even simpler:
Person *person = arrayOfPeople[i];
You can then of course get the property like this:
NSString *name = [person valueForKey:#"name"];
or just:
NSString *name = person.name;
However, your example shows a loop, suggesting that you might want to get the same property of all the objects in an array. Objective-C containers have the very nice property that they respond to -valueForKey: by getting the value for the given key from each contained object and returning a container with just those values. So, you can say:
NSArray *names = [arrayOfPeople valueForKey:#"name"];
and you get an array of names in names, with one name for each object in the array arrayOfPeople.
You can, of course, also iterate over the array:
for (Person *person in arrayOfPeople) {
NSString *name = person.name;
NSLog(#"The name is %#", name);
}
Finally, you should know that mutable arrays work just the same way as non-mutable arrays when it comes to accessing objects. The only difference between a mutable array and a non-mutable array is that you can add or remove objects from a mutable array after you create it. The mutability of the objects contained in the array isn't affected by the array's own mutability. That is, if you have an array arrayOfPeople, and if the Person objects stored in it can be modified, then you're free to change the name, age, etc. of any object stored in the array regardless of whether arrayOfPeople is mutable or non-mutable.

Related

NSMutableArray Implementation

How is NSMutableArray implemented?
If there are a number of NSMutableArray references to a mutable array e.g. Source Array and each of these pointing arrays sort the objects differently, are the objects copied over into each array or are the object pointers just internally rearranged?
If the source array is updated with new objects, will the NSMutableArray pointers automatically add an the entry to their internal reference.
It just stores pointers.This means that if the NSMutableArray stores immutable objects, then you are sure that they'll not change their state, but if it has a mutable object the state of any referenced object may change at any time.
Exactly I don't know how it's implemented, but I would say a pointer to id.It allocates memory and then update the id at the index that needs:
id* pointers;
< Allocation>
pointers[i]= newObjectPointer;
It's a little hard to parse exactly the scenario you're asking about, but NS(Mutable)Array holds a list of object references. It does not copy the objects you add to it, just keeps a pointer. If those objects can change, and you change them from outside the array, that will be reflected in the things you read back from the array.
NSMutableArray * arr = [NSMutableArray array];
NSMutableArray * child = [NSMutableArray array];
[child addObject:#5];
[arr addObject:child];
[child addObject:#6];
NSLog(#"%#", arr[0]);
> [5, 6]

How to store an array of nil pointers in objC?

I would like to use an array of pointers to instances of objects, but only want to create instances of those objects when required (i.e. lazily). The array corresponds to a table in the UI, so each array index corresponds to a table row.
I would like to use an NSMutableArray to hold pointers to the object instances as they are created (which occurs when the user selects the corresponding row in the UI).
If a row in the table is selected, the corresponding array entry is checked. If the pointer value is nil, the instance hasn't yet been created, and so it is created at that point, and the object pointer is stored in the corresponding indexed array entry.
Obviously, this requires that I initially start with an array of nil pointers, but objC won't let me put a nil pointer in an NSArray.
I can't just add objects to the array as they are created, as the array index would not correspond to the table row.
What's the best objC solution here?
The idiomatic solution in Objective C is to use NSNull:
The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
Create your NSMutableArray, and fill it up with [NSNull null] objects:
NSMutableArray *array = [NSMutableArray arrayWithCapacity:N];
for (int i = 0 ; i != 10 ; [a addObject:[NSNull null]], i++);
When you check for the presence or absence of an object in your NSMutableArray, compare the object at index to [NSNull null]: if they are the same, replace with a real object; otherwise, the real object is already there.
if ([array objectAtIndex:index] == [NSNull null]) {
MyRealObject realObject = [[MyRealObject alloc] init];
[array replaceObjectAtIndex:index withObject:realObject];
}
** edit summary ** edited to initialize the array using a loop (thanks bbum).
NSMutableArray doesn't support sparse arrays. Thus, you could pre-seed the array with NSNull instances (or some other "no object" marker). Something like:
a = [NSMutableArray array];
for(int i = 0; i<numberNeeded; i++) [a addObject:[NSNull null]];
Or, if your array is going to be truly sparse, consider the use of some kind of map instead. NSMutableDictionary will work, but requires objects for keys and all that boxing/un-boxing is painful in some cases. Alternatively, a CFDictionary can easily be configured to use integer keys with object values.
While a dictionary is obviously slower for lookup-by-index, that performance difference is unlikely to cause a problem in most cases (but not all).
What about [NSMutableArray arrayWithCapacity:numberOfRows] ?
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

Is there any way to specify the class of objects of a NSMutableArray?

Im having the following problem:
I've made a NSMutableArray "array" that is going to contain objects of a class named "Class". At the start that array should be empty and it must be filled during the program's execution.
As I never actually told the compiler that my NSMutableArray will be holding elements of the class Class, when I try to write the appropriate methods the compiler wont let me do it.
This is my first experience on Objective-C and iPhone development. I used to code in C/C++ where I declared my arrays in the following way:
Class array[NUMBEROFELEMENTS];
Is there any way to do this in Objective-C?
Thanks!
The truth is that is doesn't matter to the NSMutableArray what type of object it is. NSMutableArray simply stores pointers to all the objects they contain, or reference.
The trick is when you pull the object back out of the array you need to create a new pointer based on the appropriate type:
MyObject *myObject = [myArray objectAtIndex:0];
Then you can use the object however you like:
[myObject doThatThingWithThisValue:10];
Or whatever you need.
Arrays in Objective-C Cocoa are objects (as well as other collections, sets, dictionaries). Arrays can contain references to objects of any type, so the type for the array is simply NSArray, NSMutableArray, etc...
Since they are objects, you can send them messages to manipulate their content.
I suggest you take a look at Apple's excellent Collections Programming Topics, which explain the rudiments of collections.
Here is a quick example :
// two objects of different types
NSNumber *n = [NSNumber numberWithInteger:10];
NSString *s = #"foo";
// alloc/init a new mutable array
NSMutableArray *a = [NSMutableArray arrayWithCapacity:10];
// add an object
[a addObject:n];
[a addObject:s];
// array a now contains a NSNumber and a NSString
Well, you can still have C-style arrays in Objective-C.
However, the characteristics of Objective-C (some people will call it strength, other will call it weakness) is that it has dynamic typing of objects and dynamic dispatch.
It has NSArray and NSMutableArray which are not specialized for the certain class. It can store objects of non-compatible classes.
You can use the following idiom: [obj isMemberOfClass: [Class type]] to make sure an array element is of the desired type and then cast to Class*.
You can also use for-each loop (aka Fast Enumeration):
NSMutableArray* array = //... initialize your array
for (Class* elm in array) {
elm.your_property = 10;
}

NSMutableArray add object with order

I have a NSMUtableArray which has elements, for example:
a,b,c,e
And I want to add an object d to behind c and before e.
In other words, I'd like to insert an object to a sorted array.(The object can be a custom object, too)
I'd like to know : besides using for to find the position, is there any other method to implement it? It is better to use the iOS api.
Thanks.
You can use -[NSArray indexOfObject:inSortedRange:options:usingComparator:] to ask an NSArray for the index where an object should be inserted given an array range that’s currently sorted.
For example, assuming the entire array is sorted::
NSMutableArray *array = …;
id newObject = …;
NSComparator comparator = …;
NSUInteger newIndex = [array indexOfObject:newObject
inSortedRange:(NSRange){0, [array count]}
options:NSBinarySearchingInsertionIndex
usingComparator:comparator];
[array insertObject:newObject atIndex:newIndex];
Since this method uses binary search, it is more efficient than iterating over all elements in the array.
The comparator is a block object that receives two objects of type id and returns an NSComparisonResult value.
To inject element to known index (position) use
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
And to find position of object previously placed into NSMutableArray use
- (int)indexOfObject:(id)anObject
NSMutableArray - Get Arrays Index Integer By Searching With A String
Section Finding Objects in an Array
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
I'd just add the new object at either end and sort the array again. If the array you're adding to is already sorted, the re-sort that moves one object is going to be about as quick as anything you'd implement yourself.
NSMutableArray *things; // populated
id newObject;
...
[things addObject:newObject atIndex:0];
[things sortUsingSelector:#selector(compare:)];

Change the values within NSArray by dereferencing?

I've come across a problem related to pointers within arrays in objective-c.
What I'm trying to do is take the pointers within an NSArray, pass them to a method, and then assign the returned value back to the original pointer(the pointer which belongs to the array).
Based on what I know from C and C++, by dereferencing the pointers within the array, I should be able to change the values they point to... Here is the code I'm using, but it is not working (the value phone points to never changes based on the NSLog output).
NSArray *phoneNumbers = [phoneEmailDict objectForKey:#"phone"];
for (NSString* phone in phoneNumbers) {
(*phone) = (*[self removeNonNumbers:phone]);
NSLog(#"phone:%#", phone);
}
And here is the method signature I am passing the NSString* to:
- (NSString*) removeNonNumbers: (NSString*) string;
As you can see, I am iterating through each NSString* within phoneNumbers with the variable phone. I pass the phone to removeNonNumbers:, which returns the modified NSString*. I Then dereference the pointer returned from removeNonNumber and assign the value to phone.
As you can tell, I probably do not understand Objective-C objects that well. I'm pretty sure this would work in C++ or C, but I can't see why it doesn't work here! Thanks in advance for your help!
Yeah, that's not going to work. You'll need an NSMutableArray:
NSMutableArray * phoneNumbers = [[phoneEmailDict objectForKey:#"phone"] mutableCopy];
for (NSUInteger i = 0; i < [phoneNumber count]; ++i) {
NSString * phone = [phoneNumbers objectAtIndex:i];
phone = [self removeNonNumbers:phone];
[phoneNumbers replaceObjectAtIndex:i withObject:phone];
}
[phoneEmailDict setObject:phoneNumbers forKey:#"phone"];
[phoneNumbers release];
You can't dereference Objective-C object variables. They are always pointers, but you should treat them as though they're atomic values. You need to mutate the array itself to contain the new objects you're generating.
NSArray is not a C/C++ style array. It's an Objective-C object. You need to use the instance methods of the NSArray class to perform operations on it.
In Objective-C you never "dereference" an object pointer to set its value.
Also, you're using what is called Fast Enumeration, which does not allow mutation.
You can also use enumerateObjectsUsingBlock:.
NSArray *array = [NSArray array];
__block NSMutableArray *mutableCopyArray = [array mutableCopy];
[mutableCopyArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
[mutableCopyArray replaceObjectAtIndex:idx withObject:[object modifiedObject]];
}];
Checkout How do I iterate over an NSArray?
While this may work to some degree, I haven't tested it, I'd file this under 'bad idea' and not touch. NSArray, and many other cocoa objects, a fairly complex and can have a variety of implementations under the hood as part of the class cluster design pattern.
So when it comes down to it you really won't know what you're dealing internally. NSArray is actually designed to be immutable so in place editing is even doubly a bad idea.
Objects that are designed to let you mess around with the internals expose those through api methods like NSMutableData's mutableBytes.
You're better off constructing a new NS(Mutable)Array with the processed values.