Change values of NSArray after init - objective-c

For my homework I have to write the .h and .m to a Command-line application, the main is given by my teacher. It a simple Chutes and Ladders style board print-out of 100 spaces.
The Ladders and Chutes will be indicated by "L10", and "C10" inside of a single dimension array that stores the board's representation. The first part of the given main is the initBoard which I think I will have create an empty string array. The number of Ladders and Chutes are given in the next two lines of the supplied code, and I am suppose to populate the board with them randomly via their methods.
If I use a for loop in a "initBoard"(the first thing the main calls)method to build a NSArray to a size of 100, populating it with empty stings, will I be able to change the empty strings into the "L10" and "C10" strings that I want in my "makeLadders" and "makeChutes" methods, or do I have to use an NSMutableArray for something like this?
I have read that NSArray is immutable, meaning that it cannot be modified after init, so one must use NSMutableArray if one wishes to modify the contents of arrays. My teacher specifically mentions NSArrays as what should hold the board data so I'm confused.

You have two choices here:
A mutable array containing NSString objects;
An immutable array containing NSMutableString objects.
Example with the first choice:
NSMutableArray* array=[[NSMutableArray alloc] initWithCapacity: 100];
for(NSUInteger i=0; i<100; i++)
{
[array addObject: #""];
}
To change the values use:
[array replaceObjectAtIndex: i withObject: #"New String"];

Related

Grab Object Propertys from NSMutableArray Objective - C VS 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.

array of strings in a constant with #define - objective c

I need a array of strings in a constant. is a good idea to use #define?
For example:
#define rows [NSArray arrayWithObjects: #"NameRowA",#"NameRowB",#"NameRowC", nil]
#define KEY_ROWA [columnas objectAtIndex:0]
#define KEY_ROWB [columnas objectAtIndex:1]
#define KEY_ROWC [columnas objectAtIndex:2]
I need to access to the array of strings and the elements of that array.
I have read, (i donĀ“t know if is true) with this way it is created a new NSArray when it is used, I suppose then the array is released, so I think this is good because you only use that part of memory when you need it.
Use a singleton, it's just a couple of lines of code.
All you need is a static singleton, and a static method for retrieving it (and settings it once).
Your .m file should contain this:
#implementation MyClass
static NSArray *mySingletonArray; // this will be your array
+ (NSArray *)mySingletonArray // this is the static method for accessing your array
{
if (nil == mySingletonArray) {
mySingletonArray = [NSArray arrayWithObjects:#"firstString", #"secondString", nil];
}
return mySingletonArray;
}
Acquire what you need from you array using the static access method [MyClass mySingletonArray], e.g.
NSLog("%#", [[MyClass mySingletonArray] objectAtIndex:0]);
I don't think you want to use #define for this.
In your example, there is no constant array of strings made with this code. Every single time rows is used in your code, a new NSArray is going to be allocated. Also, KEY_ROWA refers to columnas, but that isn't in the rows define. I assume you have something like this
NSArray *columnas = rows;
There is really no difference between that and
NSArray *columnas = [NSArray arrayWithObjects: #"NameRowA",#"NameRowB",#"NameRowC", nil];
But the second line is a lot more obvious. The same is true with KEY_ROWA -- the objectAtIndex call would be more obvious and the macro doesn't get you anything.
I'm not sure what you need exactly, but if you need a shared constant array of strings inside of one class, you could declare it as + instead of - at the beginning, and allocate it once (this is a class variable as opposed to an instance variable). More info here:
How do I declare class-level properties in Objective-C?

copy objects from one NSMutableArray to another NSMutableArray

I am trying to understand copying objects from one NSMutableArray to another. Consider the following 2 scenarios:
1 - copying original to clone where changes in the clone will affect the original.
2 - copying original to clone where the changes in the close will NOT affect the original.
First, I am trying to produce scenario #1 first with the following code. From what I understand, when copying array not using 'mutablecopy', the clone array will just hold the pointer to the same string objects in the original. So if I were to change the first element of the clone to a different object, the first element of the original would change too right? ... but that's not the result I am getting. Why?
Matter of fact, when I use mutablecopy
[self.cloneArray addObject:[[self.originalArray objectAtIndex:i] mutableCopy]];
I get the same result. I am confused.
ArrayClass.h
#interface ArrayClass : NSObject {
NSMutableArray *_originalArray;
NSMutableArray *_cloneArray;
}
#property (nonatomic, retain) NSMutableArray *originalArray;
#property (nonatomic, retain) NSMutableArray *cloneArray;
ArrayClass.m
#synthesize originalArray = _originalArray;
#synthesize cloneArray = _cloneArray;
_originalArray = [[NSMutableArray alloc] initWithObjects: #"one", #"two", #"three", #"four", #"five", nil];
_cloneArray = [[NSMutableArray alloc] initWithCapacity:[self.originalArray count]];
for (int i=0; i<5; i++) {
[self.cloneArray addObject:[self.originalArray objectAtIndex:i]];
}
// make change to the first element of the clone array
[self.cloneArray replaceObjectAtIndex:0 withObject:#"blah"];
for (int n=0; n<5; n++) {
NSLog(#"Original:%# --- Clone:%#", [self.originalArray objectAtIndex:n], [self.cloneArray objectAtIndex:n]);
}
...
2011-03-27 03:23:16.637 StringTest[1751:207] Original:one --- Clone:blah
2011-03-27 03:23:16.638 StringTest[1751:207] Original:two --- Clone:two
2011-03-27 03:23:16.639 StringTest[1751:207] Original:three --- Clone:three
2011-03-27 03:23:16.642 StringTest[1751:207] Original:four --- Clone:four
2011-03-27 03:23:16.643 StringTest[1751:207] Original:five --- Clone:five
You are thinking about this way too hard.
In Objective-C, you have references to objects. An NSString *foo; simply defines a variable foo that refers to an NSString. If you say NSString *bar = foo;, then bar will have a reference to whatever object foo was referring to. No more, no less.
An NSArray is just a collection of object references. So, if you say:
NSArray *b = [NSArray arrayWithArray: a];
You are creating an array b that contains all of the same references to the exact same set of objects as a. If you modify an object referred to by a, that'll be the exact same object in b and the modification will be reflected.
When you copy an object, you are creating a new object that has the identical internal state as the original. I.e. when you say NSMutableString *foo = [barString mutableCopy];, then foo is a reference to a new string; a different one than barString.
So... when creating a new array, the question is do you want the array to contain the exact same contents as the original array or do you want it to contain a new set of objects that you can modify?
You have a misunderstanding of what's going on. The replaceObjectAtIndex:withObject: call isn't modifying objects in the array, it's modifying the array itself. After this line:
[self.cloneArray replaceObjectAtIndex:0 withObject:#"blah"];
you've replaced the object in your clone array, but you haven't changed the original array at all. If you actually modified the NSString object you put in the arrays, you might be able to get the behaviour you were expecting. You won't be able to do it with the objects you've put into the original array in your example, though, since they're immutable string objects. If you stuck mutable strings in there, used the same loop to 'clone' your array, and then did something along the lines of:
[[self.cloneArray objectAtIndex:0] appendString:#"some junk to append"];
you would actually modify the string object at index 0. Since both arrays still contain that same object, you'd get the 'modify original array by changing the objects in the clone array' behaviour.

My NSMutableArray doesn't work

sorry for my stupid question (beginner)
I got the demo program Accelerometergraph the apple site and would like to use
NSMutableArray in the values of acceleration x.
but my NSMutableArray contains only one object, there being several passage
NSMutableArray routine and should contain the same number of objects that the counter
show, how code below
if(!isPaused)
{
array = [[NSMutableArray alloc] init];
[filter addAcceleration:acceleration];
[unfiltered addX:acceleration.x y:acceleration.y z:acceleration.z];
NSNumber *number = [[NSNumber alloc] initWithDouble:acceleration.x];
[array addObject:number];
++a;
if (a == 30) // only check the # objs of mutablearray
{
sleep(2);
}
[filtered addX:filter.x y:filter.y z:filter.z];
}
It looks like you're missing a loop of some kind. The code you list above:
Makes sure something isn't paused.
Creates a new (empty) mutable array.
Adds a value to the new array.
And does some other work.
My guess is that this whole if{} block sits inside some kind of loop. You need to alloc and init the mutable array outside of the loop instead.
You create a new array each time the if block is entered, so the addObject: will only add the object to the most recently created array.
Furthermore, you are leaking the array and number objects. Each time you allocate an object, you are responsible for releasing it. Make sure you're familiar with the guidelines set out in the memory management programming guide.

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.