Quick NSMutableArray Question - objective-c

I was wondering, would using a NSMutableArray be the best way for making an array that i will be adding objects to? Or, just a regular NSArray? secondly, I'm trying to make something sort of like an ArrayList in java (so there is no limit to the size), and I would like to know how to do that. What I've thought of is to make a bigger array and copy older array into it. My code:
- (void) addAccount:(BankAccount *)b
{
accountCount = [NSNumber numberWithDouble:[accountCount doubleValue] + 1];
NSMutableArray *oldList = accounts;
accounts = [[NSMutableArray alloc] (some code to make bigger and copy over)];
}
P.S. I taught myself this language yesterday, so I may not understand you response if it's too advanced

NSMutableArrays are what you want. Also, NSMutableArrays are already like ArrayLists or STL vectors, or anything else with "no limit to the size". You can say [myArray addObject:someObject]; until you run out of memory, and it will just keep resizing itself as needed.

The difference between an NSMutableArray and an NSArray lies in the meaning of the word "mutable". i.e.: A mutable array can be modified after it's created whereas a "normal" NSArray is immutable and can't be modified after it's created.
As such, using an NSMutableArray and adding objects to it via the addObject: method would seem an ideal solution.

If you want to be adding objects all at once use NSArray. If you're going to be adding some objects now, then more later, use NSMutableArray.
Your code snippet doesn't make much sense. To make an NSMutableArray, do this:
NSMutableArray *array = [NSMutableArray array];

If you don’t need an order (normally you don’t), use a NSSet/NSMutableSet.

Related

Add Array with Dictionaries to another Array in Objective-C

I want to add an Array which contains a Dictionary to an other Array. So the first Array contains a few items and each item consists of 4 key/value pairs. Now I want to add the first Array to the second on position [i,1] (so the second Array would be a three dimensional array?). How can I achieve this?
here's my code:
NSMutableArray *routenArray = [[NSMutableArray alloc] init];
NSMutableArray *firstArray = [[NSMutableArray alloc] init];
NSDictionary *firstDict = [NSDictionary dictionaryWithObjectsAndKeys:abfahrt,#"Abfahrt", ankunft, #"Ankunft", dauer, #"Dauer", route, #"Route", nil];
[firstArray addObject:firstDict];
for (int i = 0; i < firstArray.count; i++) {
routenArray [i][1] = firstArray [i];
}
You know, you really need to learn the basics of "3D" arrays, and indeed arrays / NSMutableArrays generally.
Fundamentally you use addObject to add an item to an NSMutableArray.
The answer to your question is that you use addObject to add objects to your "outside" array.
The things you add, can themselves me complex data objects like arrays - that's the "3D' part as you're thinking about it.
To access elements of an NSArray (or NSMutableArray), you use firstObject, lastObject, or objectAtIndex.
(You don't use braces[1][17].)
I encourage you to read some basic tutorials on NSArray for Xcode.
Click the "tick" sign to mark my answer as correct, closing this question. Then, forget you ever asked this question :) Read some tutorials, then ask new specific questions about NSArray. Also search here for 1000s of examples and QA.
It's possible you're looking for addObjectsFromArray
Generally to solve problems like this.
Go to the dock for the highest class involved in your problem, in this case NSMutableArray ...
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
no matter how experienced you are, you can always find amazing stuff in there. Just read through each method available to you; often you find just what you want.
In this case addObjectsFromArray is your gift from above. Next, on this site just search on addObjectsFromArray and you'll find lots of great example code and other incidentalia.
Cheers!
There are no "three dimensional arrays". There is NSArray (and NSMutableArray), and they contain objects. Since NSArray and NSDictionary are themselves objects, an NSArray can contain another NSArray which can contain another NSArray. That doesn't make it three-dimensional. And that's where your problem comes from: "routenArray" (wer mixt hier deutsche und englische Namen? ) doesn't contain any objects. routenArray [0] is nil.
What you are writing:
routenArray [i][1] = firstArray [i];
is just a shortcut for
[[routenArray objectAtIndex:i] replaceObjectAtIndex:1 withObject:[firstArray objectAtIndex:i]];
So this is very much not what you think it is.

Incompatible pointer type assigning "NSMutableArray" to "NSArray"?

This is my code
NSMutableArray * reversedNamesArray; //theres about a thousand variable already stored in here, this is just for documentation
reversedNamesArray = [reversedNamesArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
//Incompatible pointer type assigning "NSMutableArray" to "NSArray"
The message above is what i get, i know what it means, but i don't want to take an extra step of copying an NSMutableArray of a thousand variable to a NSArray is there any cast i can use to fix the warning, it doesn't affect my code, but i just want a fix for it. and can you explain why they are not compatible, they NSMutableArray and NSArray should use the same amount of bytes so i don't see why they are incompatible in the first place.
-sortedArrayUsingSelector: is implemented in NSArray and returns an NSArray even when called on an NSMutableArray.
You should use one of the sort methods implemented in NSMutableArray. This would work:
[reversedNamesArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
#GerdK's answer is the right one, but I thought I would explain why you cannot just cast an NSArray into NSMutableArray. If you could, major optimizations would be lost. Consider the following:
NSArray *first = #[...];
NSArray *second = [first copy];
This is extremely cheap. second just adds an extra retain onto first and we're done. On the other hand:
NSMutableArray *first = [NSMutableArray arrayWith…]
NSArray *second = [first copy];
This is more expensive. In order to create second, we actually have to create new array and copy the pointers over and add extra retains.
Now, imagine what you're requesting were legal:
// Not legal, but let's say it were
NSArray *first = #[...];
NSMutableArray *second = (NSMutableArray *)[first copy];
Now [NSArray copy] has to be defensive against this. It has to implement copy as a full (expensive) copy. That's a real performance loss.
You might say "But I'll just use copy when I want to really copy and retain when I want to retain." Sure, but that's not good enough. Say I want to store an immutable copy of something I'm passed:
- (void)setSomething:(NSArray *)array {
_something = [array copy];
}
This is a very efficient and correct setter. If I pass a real NSArray, then it's cheap (and this is probably the normal case). If I pass an NSMutableArray (it's a subclass, so I can do that), then I automatically make a real copy (so the object can't change behind my back). You get this kind of optimization for free by keeping mutable and immutable objects separate. Otherwise, I'd have to interrogate the object and ask if it were mutable and then make decisions based on that.

Appending NSDictionary to other NSDictionary

I have one NSDictionary and it loads up UITableView. If a user scrolls more and more, I call API and pull new data. This data is again in the form of an NSDictionary. Is it possible to add the new NSDictionary to the existing one?
You looking for this guy:
[NSMutableDictionary addEntriesFromDictionary:]
Make sure your UITableView dictionary is an NSMutableDictionary!
Check it here
Use NSMutableDictionary addEntriesFromDictionary to add the two dictionaries to a new mutable dictionary. You can then create an NSDictionary from the mutable one, but it's not usually necessary to have a dictionary non-mutable.
Is your NSDictionary full of other NSDictionaries? It sounds like you would need an NSMutableArray that you could add NSDictionaries to at the end. Assuming you can control the flow of data coming in and wouldn't run the risk of duplicates in your array, you could certainly append the data.
NSMutableArray *array = [[NSMutableArray alloc] init];
arrayCount = [array count]; // check the item count
[array addObject:dictToAppend];
Without seeing how you are implementing it, I can't provide more detailed code examples. Appending items is easy to do, but know it can only be done with mutable versions of Arrays or Dictionaries. Hope this helps a little.

How do you benefit from creating an NSArray in Objective-C?

Well, I've been learning Objective-C for a while now, and I don't get why creating an NSArray would be beneficial for you. It's just a collection of some stuff right? Why can't you just use them without making an NSArray. Or can you use the objects in it in the implementation of every one of your methods (even if it's a local ivar).
So, any help would be appreciated. Thanks guys!
You could make instance variables for every “item” you need:
NSString *str1;
NSString *str2;
NSString *str3;
…but that’s hard to work with, an array is simply more convenient. What would you do if you wanted to print all these strings?
NSLog(#"%#", str1);
NSLog(#"%#", str2);
NSLog(#"%#", str3);
Wouldn’t it be easier to loop over an array?
NSArray *strings = [NSArray arrayWithObjects:#"one", #"two", #"three", nil];
for (NSString *str in strings)
NSLog(#"%#", str);
How about if you have ten, twenty strings? And what if you don’t know how many strings you will need? What if you want to pass all these items to somebody else? Are you going to pass them one by one?
- (void) doSomethingWithString1: (NSString*) str1 andString2: (NSString*) str2…;
Or would you rather pass an array?
- (void) doSomethingWithMyStrings: (NSArray*) strings;
Very often, the NSArray you see is a front for an NSMutableArray working behind the scenes.
Billing it in the interface as an NSArray is just a way to ensure that it cannot be manipulated from without, which could have moderately disastrous consequences. (Thus, when asking for an NSArray from an object, you'll usually get a copy of the NSMutableArray used internally.)
Understanding why creating an NSMutableArray is beneficial is left as an exercise to the reader.
Different contexts.
When you use an NSString it's generally used for a single value. It's quite simple.
NSArray
If you want to loop through many keys/values, use an NSArray. It is not possible to loop through NSStrings because they don't have the order structer that NSArray's do.
Why use NSString
It would be silly to call myArray[0] and foo[0] every time you saved just a value. NSString is simpler than NSArray, since you can easily set a value on a GUI element (without having to call myArray[0])
Why use NSArray
It is more flexible than NSString because NSArray can hold multiple values, which may be needed in certain situations.
Weighing pros and cons
Pros (NSArray):
Can make your code cleaner (call myArray[1] and myArray[0] instead of mystring and foo)
Simplified memory management (easier to release one NSArray than many NSStrings)
Cons (NSArray):
Can make your code very complicated (was that on myArray[0] or 1?)
Might be difficult to know what type of data is in the array (if it's an NSString, it's always going to be a string, an array can hold many different types of data). You wouldn't use 50 tissues to dry yourself off from the shower but use a towel.
So it boils down to one thing. What context are you using?

Creating an NSArray initialized with count N, all of the same object

I want to create an NSArray with objects of the same value (say NSNumber all initialized to 1) but the count is based on another variable. There doesn't seem to be a way to do this with any of the intializers for NSArray except for one that deals with C-style array.
Any idea if there is a short way to do this?
This is what I am looking for:
NSArray *array = [[NSArray alloc] initWithObject:[NSNumber numberWithInt:0]
count:anIntVariable];
NSNumber is just one example here, it could essentially be any NSObject.
The tightest code I've been able to write for this is:
id numbers[n];
for (int x = 0; x < n; ++x)
numbers[x] = [NSNumber numberWithInt:0];
id array = [NSArray arrayWithObjects:numbers count:n];
This works because you can create runtime length determined C-arrays with C99 which Xcode uses by default.
If they are all the same value, you could also use memset (though the cast to int is naughty):
id numbers[n];
memset(numbers, (int)[NSNumber numberWithInt:0], n);
id array = [NSArray arrayWithObjects:numbers count:n];
If you know how many objects you need, then this code should work, though I haven't tested it:
id array = [NSArray arrayWithObjects:(id[5]){[NSNumber numberWithInt:0]} count:5];
I can't see any reason why this structure in a non-mutable format would be useful, but I am certain that you have your reasons.
I don't think that you have any choice but to use a NSMutableArray, build it with a for loop, and if it's really important that the result not be mutable, construct a NSArray and use arrayWithArray:
I agree with #mmc, make sure you have a valid reason to have such a structure (instead of just using the same object N times), but I'll assume you do.
There is another way to construct an immutable array which would be slightly faster, but it requires creating a C array of objects and passing it to NSArray's +arrayWithObject:count: method (which returns an autoreleased array, mind you) as follows:
id anObject = [NSNumber numberWithInt:0];
id* buffer = (id*) malloc(sizeof(id) * anIntVariable);
for (int i = 0; i < anIntVariable; i++)
buffer[i] = anObject;
NSArray* array = [NSArray arrayWithObjects:buffer count:anIntVariable];
free(buffer);
You could accomplish the same thing with even trickier pointer math, but the gains are fairly trivial. Comment if you're interested anyway.
Probably the reason there is no such method on NSArray is that the semantics are not well defined. For your case, with an immutable NSNumber, then all the different semantics are equivalent, but imagine if the object you were adding was a mutable object, like NSMutableString for example.
There are three different semantics:
retain — You'd end up with ten pointers to the same mutable string, and changing any one would change all ten.
copy — You'd end up with ten pointers to the same immutable string, or possibly ten different pointers to immeduable strings with the same value, but either way you'd not be able to change any of them.
mutableCopy — You'd end up with ten different mutable string objects, any of which you could change independently.
So Apple could write three variants of the method, or have some sort of parameter to control the semantics, both of which are ugly, so instead they left it to you to write the code. If you want, you can add it as an NSArray category method, just be sure you understand the semantic options and make it clear.
The method:
-(id)initWithArray:(NSArray *)array copyItems:(BOOL)flag
has this same issue.
Quinn's solution using arrayWithObjects:count: is a reasonably good one, probably about the best you can get for the general case. Put it in an NSArray category and that's about as good as it is going to get.