Size of the NSMutable Array in objective C? - objective-c

I want to ask the size of the NSMutable Array can be 2000? If not, is it possible to open an array to store 2000 elements. The elements is the user-defined object. Thank you.

The answer is that an NSMutableArray always starts with a size of zero. If you want it to be so you can do something like this:
NSMutableArray* anArray = [NSMutableArray arrayWithSize: 2000];
[anArray replaceObjectAtIndex: 1999 withObject: foo];
you need to prefill the array with NSNull objects e.g.
#implementation NSArray(MyArrayCategory)
+(NSMutableArray*) arrayWithSize: (NSUInteger) size
{
NSMutableArray* ret = [[NSMutableArray alloc] initWithCapacity: size];
for (size_t i = 0 ; i < size ; i++)
{
[ret addObject: [NSNull null]];
}
return [ret autorelease];
}
#end
Edit: some further clarification:
-initWithCapacity: provides a hint to the run time about how big you think the array might be. The run time is under no obligation to actually allocate that amount of memory straight away.
NSMutableArray* foo = [[NSMutableArray alloc] initWithCapacity: 1000000];
NSLog(#"foo count = %ld", (long) [foo count]);
will log a count of 0.
-initWithCapacity: does not limit the size of an array:
NSMutableArray* foo = [[NSMutableArray alloc] initWithCapacity: 1];
[foo addObject: #"one"];
[foo addObject: #"two"];
doesn't cause an error.

Related

Seg Fault when using addObject to NSMutableArray

I seem to be having a problem with the NSMutableArray.
Here's my code:
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
while(condition) {
NSInteger temp = someNumber;
[returnArray addObject: temp];
}
But as soon as it hits the addObject message, the program seg faults. Any advice?
You can't add primitives like integers to an array, only objects (hence the name addObject:). If you want to add numbers, you have to convert them to an NSNumber, or one of the related classes.
You can only add objects to array and NSInteger is not an array.
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
while(condition) {
[returnArray addObject: [NSNumber numberWithInt: someNumber]];
}
You need to wrap primitives such as NSInteger into an NSNumber class. You can do the following:
while(condition)
{
NSInteger temp = someNumber;
[returnArray addObject:#(temp)];
}
Or if your compiler doesn't support that syntax:
while(condition)
{
NSInteger temp = someNumber;
[returnArray addObject:[NSNumber numberWithInteger:temp]];
}

Method Creates an Array with 11 objects, All Out of Scope, Unrecognized Selector Results

Okay, so, I'm doing a simple lookup. I have an array of NSString objects and a string to search for in the array's elements.
It all seems to work up until I try to add a match to a new mutable array made to hold the search results. The stringHolder variable gets the string, and resultsCollectorArray even get the right number of new elements, but each element is empty and "out of range". Here's the method:
#implementation NSArray (checkForString)
-(NSMutableArray *) checkForString: (NSString *) matchSought
{
long unsigned numberofArrayElements;
long unsigned loop = 0;
NSRange searchResults;
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init];
id stringHolder;
numberofArrayElements = [self count];
while (loop < numberofArrayElements) {
searchResults.length = 0;
searchResults = [[self objectAtIndex: loop] rangeOfString: matchSought options:NSCaseInsensitiveSearch];
if (searchResults.length > 0) {
stringHolder = [self objectAtIndex: loop];
[resultCollectorArray addObject: stringHolder];
}
loop++;
}
return [resultCollectorArray autorelease];
}
Once we get back to the main portion of the program, I get an unrecognized selector sent to the mutable array that was supposed to receive the result of the method. Here's the main section:
#import <Foundation/Foundation.h>
#import "LookupInArray.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *testString = [[NSString alloc] initWithString: #"ab"];
NSMutableString * resultString = [[NSString alloc] init];
NSArray * theArray = [[NSArray alloc] initWithObjects: ..., nil]; // Actual code has the objects
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSUInteger arrayCount = 0;
unsigned long loops = 0;
resultArray = [theArray checkForString: testString];
arrayCount = [resultArray count];
while (loops < arrayCount){
resultString = [resultArray objectAtIndex: loops]; // Here's where we get the unrecognized selector.
NSLog(#"%#", resultString);
loops++;
}
[pool drain]; // Also, I'll release the objects later. I just want to get what's above working first.
return 0;
}
I've searched the other answers (for hours now), but didn't seen anything that solved the issue.
Any and all help would be really appreciated.
And thanks beforehand.
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init]; is so incorrect. You are creating a mutable set and assigning it to a mutable array.
You are getting unrecognized selector because objectAtIndex: is not a valid selector for NSMutableSet. Make that statement,
NSMutableArray * resultCollectorArray = [[NSMutableArray alloc] init];
A Better way
NSArray * filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchString]];
You can directly filter the array using predicates. This way you do this in a single step. :)

How to append values to an array in Objective-C

I'm doing this:
for(int i=0;i>count;i++)
{
NSArray *temp=[[NSArray alloc]initWIthObjects]i,nil];
NSLog(#"%i",temp);
}
It returns to me 0,1,2,3....counting one by one, but I want an array with appending these values {0,1,2,3,4,5...}.
This is not a big deal, but I'm unable to find it. I am new to iPhone.
NSMutableArray *myArray = [NSMutableArray array];
for(int i = 0; i < 10; i++) {
[myArray addObject:#(i)];
}
NSLog(#"myArray:\n%#", myArray);
This code is not doing what you want it to do for several reasons:
NSArray is not a "mutable" class, meaning it's not designed to be modified after it's created. The mutable version is NSMutableArray, which will allow you to append values.
You can't add primitives like int to an NSArray or NSMutableArray class; they only hold objects. The NSNumber class is designed for this situation.
You are leaking memory each time you are allocating an array. Always pair each call to alloc with a matching call to release or autorelease.
The code you want is something like this:
NSMutableArray* array = [[NSMutableArray alloc] init];
for (int i = 0; i < count; i++)
{
NSNumber* number = [NSNumber numberWithInt:i]; // <-- autoreleased, so you don't need to release it yourself
[array addObject:number];
NSLog(#"%i", i);
}
...
[array release]; // Don't forget to release the object after you're done with it
My advice to you is to read the Cocoa Fundamentals Guide to understand some of the basics.
A shorter way you could do is:
NSMutableArray *myArray = [NSMutableArray array];
for(int i = 0; i < 10; i++) {
[myArray addObject:#(i)];
}
NSLog(#"myArray:\n%#", myArray);

Can a function return an object? Objective-C and NSMutableArray

I have an NSMutableArray. It's members eventually become members of an array instance in a class. I want to put the instantiantion of NSMutable into a function and to return an array object. If I can do this, I can make some of my code easier to read. Is this possible?
Here is what I am trying to figure out.
//Definition:
function Objects (float a, float b) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithFloat:a]];
[array addObject:[NSNumber numberWithFloat:b]];
//[release array]; ????????
return array;
}
//Declaration:
Math *operator = [[Math alloc] init];
[operator findSum:Objects(20.0,30.0)];
My code compiles if I instantiate NSMutableArray right before I send the message to the receiver. I know I can have an array argument along with the method. What I have problem seeing is how to use a function and to replace the argument with a function call. Any help is appreciated. I am interested in the concept not in suggestions to replace the findSum method.
Use autorelease to return objects you create in methods/functions.
NSMutableArray* Objects(float a, float b) {
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
// or: [NSMutableArray array];
[array addObject:[NSNumber numberWithFloat:a]];
[array addObject:[NSNumber numberWithFloat:b]];
return array;
}
Or simply:
NSMutableArray* Objects(float a, float b) {
return [NSMutableArray arrayWithObjects:
[NSNumber numberWithFloat:a],
[NSNumber numberWithFloat:b],
nil];
}

Can I assign array size using NSMutableArray?

I used to be a Java Programmer, which the array need to declare the very first time, like this:
int[] anArray; // declares an array of integers
anArray = new int[10]; // allocates memory for 10 integers
I don't know whether the Objective C , NSMutableArray also give me this ability or not. Actually, I want to make a 10*10 array. thz in advance.
I try to do this:
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my incompatible type assignment.
The capacity field is seldom useful. The array will be expanded on demand anyway.
And the capacity field just tells the array how much memory you may use. The array's length is still 0.
But you can grow the array from empty:
for (int i = 0; i < 10; ++ i)
[myArray addObject:…];
To read and write to an element in an NSMutableArray, you need:
id x = [array objectAtIndex:i]; // x = array[i];
[array replaceObjectAtIndex:i withObject:y]; // array[i] = y;
You cannot subscript an NSArray directly.
Your code has memory leak. Unlike Java, ObjC doesn't use a GC unless you explicitly enable it (and ObjC on iPhoneOS doesn't have GC). ObjC manages memory by manual reference counting. Basically you need to ensure the ref count of stuff you don't own doesn't change in the process. See http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html for detail.
In your case, [[NSMutableArray alloc] …]; creates an object of ref count +1, then the assignment will take over the array, that means you don't own it any more, but the ref count is not balanced to 0, so this memory will not be properly deallocated. You need to use convenient methods such as [NSMutableArray array…] to create an object with ref count 0.
NSArray's can only store ObjC objects. int in C (ObjC) is a primitive, and cannot be stored into an NSArray. You have to box it into an NSNumber by [NSNumber numberWithInt:0]. You can get back the integer with -intValue.
To conclude, your code needs to be modified as:
-(NSMutableArray*)get10x10Array {
NSMutableArray* arr = [NSMutableArray array];
for (int i = 0; i < 10; ++ i) {
NSMutableArray* subarr = [NSMutableArray array];
for (int j = 0; j < 10; ++ j)
[subarr addObject:[NSNumber numberWithInt:0]];
[arr addObject:subarr];
}
return arr;
}
But ObjC is a superset of C. You can just use a plain 10x10 C array.
int arr[10][10];
You want a 10x10 array -- of what?
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my
incompatible type assignment.
Because you can't assign to myArray like that. myArray is an object that represents an array data structure. It is not a C array.
If you want a 10x10 array of a primitive data type, you can declare one like you would in C:
int myArray[10][10];
initWithCapacity: is what you want. It may look like
NSMutableArrat *array = [[NSMutableArray alloc] initWithCapacity:10];
You can't access Cocoa array objects with the bracket notation. Your second bit of code should be:
NSMutableArray *myArray = [[NSmutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i++) {
[myArray insertObject:[NSMutableArray arrayWithCapacity:10] atIndex:i]; // Note: not using myArray[i]!
}
There are two ways to do this.
Plain old C
If you want to store objects, you should use the id type instead of int.
int myarray[10][10];
myarray[5][2] = 412;
Objective-C
NSArray's are not meant to have spaces without objects, if you need them you could use [NSNull null], but if that's the case a C array would be better anyway.
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i < 10; i++) {
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int j=0; j < 10; j++) {
[innerArray addObject:[NSNull null]];
}
[myArray addObject:innerArray];
[innerArray release];
}
[[myArray objectAtIndex:5]
replaceObjectAtIndex:2 withObject:[NSNumber numberWithInteger:123]];
NSArray objects have a fixed size that cannot be changed once they have been initialised. NSMutableArray objects can change size. A 10×10 array is sometimes implemented as an NSArray containing 10 individual NSArray objects, each of these containing ten items. This quickly gets cumbersome, sometimes it is easier to resort back to plain C for such a task:
int tenByTen[10][10];
Or, you can use this:
typedef struct
{
int y[10];
} TenInts;
typedef struct
{
TenInts x[10];
} TenByTen;
Then you could do:
- (void) doSomethingWithTenByTen:(const TenByTen) myMatrix
{
NSLog ("%d", myMatrix.x[1].y[5]);
}
And you can also return them from methods:
- (TenByTen) mangleTenByTen:(const TenByTen) input
{
TenByTen result = input;
result.x[1].y[4] = 10000;
return result;
}
You want NSMutableArray +arrayWithCapacity:
Note that setting the initial capacity is merely an optimization - Mutable arrays expand as needed.
EDIT:
To do the 10x10 case,
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
NSMutableArray *subArray = [NSMutableArray arrayWithCapacity:10];
[myArray addObject:subArray];
for (int j = 0; j<10; j++) {
[subArray addObject:[NSNumber numberWithInt:0]];
}
}
Notes:
an array retains the objects added to it, so its not necessary to retain subArray
only objects (not primitive types like "int") can be added to an NSArray, hence the need for NSNumber numberWithInt:
you use methods like objectAtIndex: and replaceObjectAtIndex:withObject: to get/set a value from an NSArray, not array subscript ([]) syntax
See Apple refs for NSArray and NSMutableArray
You can use the following code to resize the NSMutableArray once it was created:
#interface NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize;
#end
#implementation NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize
{
int size = (newSize > [self count]) ? self.count : newSize;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
for (int i = 0; i < size; i++){
[array addObject:[self objectAtIndex:i]];
}
return array;
}
#end