Passing NSMutableArray into a function - iphone

I have this problem with Cocoa, I am calling a function and passing an Array to it:
Some where I call the function:
[self processLabels:labels];
And the function is as follow:
- (void)processLabels:(NSMutableArray*)labs{
labs = [[NSMutableArray alloc] init];
[labs addObject:#"Random"];
....
}
When debugging, I notice that no new object are being added to labels when they are added to labs. Is it because I am re-initializing labs? how could I re-initialize labels inside the function then?
I tried using byref by didn't succeed,
any help is appreciated..
thanks

'labs' should be initialized before you pass it to processLabels, and then it shouldn't be re-initialized.
If you can't initialize the array beforehand for whatever reason and you want processLabels to create it, you need to pass a pointer to a pointer:
[self processLabels:&labels];
and the method would change to:
- (void)processLabels:(NSMutableArray**)labs{
*labs = [[NSMutableArray alloc] init];
[*labs addObject:#"Random"];
....
}

generally spoken, it is preferrable to not pass mutable collections, but to provide methods which perform work on them...
in fact, in response to your code I wonder even what the purpose is of passing the 'labs' array into the function when in fact you are just overwriting it (and creating a memory leak in the process). why do that?

The statement labs = [[NSMutableArray alloc] init]; makes labs to point to the new array in the scope of the method. It does not make the caller's pointer point to the new array.
If you want to change the caller's pointer, do something like this:
// The caller
NSMutableArray *labels; // Don't initialize *labels.
[self processLabels:&labels];
...
- (void)processLabels:(NSMutableArray**)labs{
*labs = [[NSMutableArray alloc] init];
[*labs addObject:#"Random"];
...
}
That's probably a bad idea because processLabels: allocates the array but the caller is responsible for freeing it.
If you want the caller to own the array, you could write processLabels: like this:
- (void)processLabels:(NSMutableArray*)labs{
[labs removeAllObjects];
[labs addObject:#"Random"];
...
}
Or, if processLabels: is just returning a collection of labels:
- (NSMutableArray*)processLabels {
NSMutableArray* labs = [[[NSMutableArray alloc] init] autorelease];
[labs addObject:#"Random"];
...
return labs;
}
If you want the caller to be responsible for freeing the array, remove the autorelease. In that case, convention dictates that the method name should start with alloc or new, or contain the word copy.

You need to pass in a mutable array to be able to change it (that's the definition of Mutable) - to turn an NSArray into a mutable array, use:
NSMutableArray *writableArray = [NSMutableArray arrayWithArray:oldArray];
or if you just want to make an empty mutable array:
NSMutableArray *writableArray = [NSMutableArray array];
Then pass that in.

Will is correct, both about correcting the existing method, and about it being a bad idea. Storing back to a by-reference parameter is certainly valid, and it's used frequently in plain C programs, but in this case it adds needless complexity. In Objective-C, the preferred idiom is to return objects using the return value first, and only store back to a pointer if the return value is already being used to return something else. Not only will this make calls to a method easier to read and write, but it conforms to standard idioms that are commonly used in other languages (such as Java and C#). It becomes quite obvious if you overwrite an array pointer by assigning to it, a potential bug that is more likely to be picked up by tools like the Clang Static Analyzer.
On a related note, you should probably also consider better method and parameter naming. (I realize this is likely a somewhat contrived example.) If you're processing "labels", and they come from some source other than the mutable array you're creating, I wouldn't name the local variable "labs" or "labels" — use a more descriptive name. Method names that are less vague about what they do can vastly improve code readability. In Objective-C, long descriptive method names are preferred. Since Xcode does code completion and the method names are less ambiguous, the end result is usually less typing.

Related

How does calling retain in different ways on the same object work?

I want to know difference between following two:
NSMutableArray *myArray = [[someObject returnMutableArray] retain];
and
NSMutableArray *myArray = [someObject returnMutableArray];
[myArray retain];
I have some complex data flow project in which I have to return different NSMutableArrays.
I also want to know what is the best way to return NSMutableArrays.
There is no difference apart from how you want your code formatted.
The reason this works is in the documentation for NSObject
As a convenience, retain returns self because it may be used in nested expressions.
Therefore retain returns the object that is was called upon (a mutable array in your case) which means you can nest methods or simply use the return value in the assignment as you have in your example.
For returning values from methods you should make sure it is autorelease'd
So using your snippet
- (NSMutableArray *)myMethod;
{
NSMutableArray *myArray = [someObject returnMutableArray];
// ... do some work
return myArray;
}
Because the method returnMutableArray does not contain the keyword's alloc, new or copy it should be made to return an autorelease'd object. Now as we are returning the object at the end of the method we don't need to take any further retains as it will be ready for returning.
If you are unsure on memory management you should read the Advanced Memory Management Guide or (preferably) start using ARC
There is no difference between 1 and 2.
The best practice on iOS is to return autoreleased objects from methods, and there should be no need to retain them.
If you are confused about how retain and release work, you should probably just enable ARC in your project, which manages retain and release for you automatically.

NSMutableArray initWithCapacity method description and memory management

It's about the instance method of NSMutableArray "initWithCapacity".
From documentation, the Return Value is described as:
Return Value
An array initialized with enough memory to hold numItems objects.
The returned object might be different than the original receiver.
There seems to be a typo at "different than", my guess is it should be "different from". And also if the returned object is indeed different from the original, do we have to worry about releasing the memory associated with the original object ?
Hope that somebody knowledgable on this can help ...
http://developer.apple.com/library/mac/#documentation/cocoa/reference/foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/cl/NSMutableArray
You have created an object with alloc, and you are responsible for the memory of that object. The fact that initWithCapacity: may return a different chunk of memory than what originally came from the call to alloc does not change that.
Initializer methods in Cocoa are allowed to deallocate the instance they are passed and create a new one to be returned. In this case, it's necessary for initWithCapacity: to do so, since you're actually asking it to reserve more memory that alloc didn't know about and couldn't have allocated.
This is the reason that alloc and init... should always be paired: [[NSMutableArray alloc] initWithCapacity:10]
Regarding initWithCapacity: specifically, bbum (who knows of what he speaks -- Apple engineer) says that it's usually unecessary. It does not preclude you from expanding the array past the specified size. All it does is potentially allow the array to do some initial optimization*; unless you've measured and it makes a significant difference, it's probably not necessary.
*See Objective-c NSArray init versus initWithCapacity:0
Any time you use a method that contains the word alloc then you are responsible for releasing the memory. For example if you did the following
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
//Store data into the array here
//Once done you need to release the array
[myArray release];
--Editied post because I meant to type alloc and used init instead.

Syntax for accessing instance variables? (Objective-C)

What is the proper syntax for accessing an instance variable in Objective-C?
Assume we have this variable:
#interface thisInterface : UIViewController {
NSMutableString *aString;
}
#property (nonatomic, retain) NSMutableString *aString;
and that it is synthesized.
When we want to access it, we first would want to allocate and initialize it. Having programmed in Objective-C for about a month now, I've seen two different forms of syntax. I've seen people do simply aString = [[NSMutableString alloc] initWithString:#"hi"], where they allocate the string like that; I've also seen people start it off with self.aString and then they proceed to initialize their ivar. I guess I'm just trying to figure out what is the most proper way of initializing an instance variable, because with the former example, I have received EXC_BAD_ACCESS errors from it. After prepending the self. though, it didn't appear.
Forgive me if this is a duplicate question, but after reading some posts on SO, it's made me curious. I'm trying to learn the proper syntax with Objective-C because I prefer being proper rather than sloppy.
If you have declared a property and #synthesize it in the .m file, you simply set it like this:
self.aString = #"hi"; // or [[NSMutableString alloc] initWithString:#"hi"];
Using self.varName takes advantage of what your property declaration actually does- it handles retention of the new value (since your property has the retain attribute), releasing the old value, etc for you.
If you just do:
aString = someValue;
... you may be leaking the original value that was in aString, since without using self.aString you are accessing the variable directly vs through the property.
Note the difference between self->varName and self.varName
The first is pointer access. The second is property access.
Why is that important? Pointer access is direct. Property access, on the other hand makes use of getters and setters (be they #synthesized or not). Moreover, as a convenience, the #synthesized accessors take care of the memory mangement for you (i.e. when using self.varName = ...;), whereas varName = ...; does only what it says, i.e. the assignment -> (there lies the explanation for EXC_BAD_ACCESS errors you might be getting).
Syntactically, both forms are correct. If you want to better communicate intent, use self->varName when you want to work directly with the pointer and use self.varName when you want to take advantage of the #property convenience.
Here are all the possible combinations (I think)
OKs and BADs are only correct when aString property has retain attribute:
#property (nonatomic, retain) NSMutableString *aString;
So:
1
aString = [[NSMutableString alloc] init]; //OK:
This is OK but only in the case aString is not pointing to an invalid object or you will loose a reference to that object and it will leak because you won't be able to reach it to release it.
2
aString = [NSMutableString string]; //BAD
Bad because you are suppose to retain aString (as you declared it that way), you are not retaining it and you will get surely get EXC_BAD_ACCESS in the future
3
aString = [[NSMutableString string] retain]; //OK
Same as the first approach, only good if aString is not pointing to a valid object. However I will use the first though.
4
aString = [[[NSMutableString alloc] init] autorelease];//BAD
Same as the second approach.
5
self.aString = [[NSMutableString alloc] init]; //BAD!!
Bad because you are retaining it twice, hence it will lead to memory leaks
6
self.aString = [[NSMutableString string]; //******GOOD!******
This is probably the safest. It will be retained by the property setter and since you are using the setter any other object that could have been pointed by aString will be released appropriately
7
self.aString = [[NSMutableString string] retain]; //BAD
This is retained twice.
8
self.aString = [[[NSMutableString alloc] init] autorelease];//Ok
This is also OK, but I would use the convenience method instead of this long approach :)
Be wary that the #1 and #3 options are perfectly good if you know what you are doing. In fact I use them much more frequently than #6
I personally prefer to use the self. syntax. It just makes it easier to determine that its an instance variable, and not just some other variable in the current scope that will be lost when its NSAutoreleasePool is drained. However, it is correct to use them both ways, and if you are receiving EXC_BAD_ACCESS errors, it is not because you accessed it without using self.. You are correct in saying that you must alloc it, and whichever way you choose to access your variables, keep it consistent or you will receive errors.
I hope this helps.
Always use accessors except in init, dealloc and in accessors themselves. Doing this will save you a lot of headaches like the one you're describing. Also, name your ivars something different than your property (_foo, foo_, mFoo, but not foo).
self.foo is precisely the same as [self foo]. I calls the method foo. self.foo = x is precisely the same a [self setFoo:x]. It calls the method setFoo:. If you synthesized the property foo as a retain variable, then this looks something like:
#synthesize foo = foo_;
- (void)setFoo:(id)value {
[value retain];
[foo_ release];
foo_ = value;
}
This correctly releases the old value of foo_, assigns a new one and retains it.
foo = x (assuming foo is an ivar) does not call any method. None. It just assigns the value of the pointer in x to the pointer in foo. If foo pointed to something that was retained, it's leaked. If the new value you're assigning isn't retained, you'll crash later.
The solution to this is to always use accessors when you can.
Either.
Using the dot syntax is cleaner (to some) and it compiles to the equivalent. i.e self.iVar is the same as [self iVar] and self.iVar = aValue is the same as [self setIVar:aValue];
self.aString is a syntactic sugar to [self aString]. Synthesize a property just create the -aString and -setAString: method (depending on the property you have chosen it while not be the trivial affectation).
Now the question is whether to use the . notation. I suggest you not to use it.
Why? First know that Objective-C aim to be just an addition to C. This mean that every valid C code is also a valid Objective-C code.
Now look at what they have done with the dot notation. The last statement does not hold anymore. You wont distinguish between an access to a field of a C structure and sending objective-c method.
So please don't use the dot notation. Prefer using the [self ..].

Assigning, mutable to immutable array?

Would someone be so kind as to confirm that I am understanding this correctly. My initial response to this was that the mutableArray when assigned to an immutableArray would become an immutableArray, however this is not the case.
Is this because the initial array is allocated as a mutableArray and the immutableArray is just assigned to point to the same object. The compiler gives a warning, but the the code executes just fine at runtime.
NSMutableArray *mArray = [NSMutableArray arrayWithObjects:#"Teddy", #"Dog", nil];
NSArray *iArray = mArray;
[iArray addObject:#"Snoss"]; // Normally this would crash NSArray
much appreciated
gary.
Don't confuse the physical object that you just created, with how you are effectivley casting it in your code.
In this case, you did physically create a NSMutableArray.
Then you effectivley cast it to an NSArray - which is totally valid - for example, there are many cases where a function might want an NSArray, and you can pass it an NSArray, or anything derived from it (like an NSMutableArray).
The problem is that you get a compiler warning because you are trying to call addObject on an object which the compiler thinks is just an NSArray because that's what it's physical type is.
This will actually work, because it actually is an NSMutableArray, and in runtime would respond to that selector.
It's bad coding practice to do it this way, because NSArray doesn't actualy respond to the addObject selector. For example, I could create a function, like:
-(void) addIt:(NSArray)myThing {
[myThing addObject:#"New String"];
}
The compiler would give you a warning saying the "NSArray" doesn't respond to the "addObject" selector. If you cast an NSMutableArray, and passed it to this function, it myThing, it would actually work.
It's bad practice though, because if you actually passed an NSArray it would crash.
Summary: Don't confuse what the object really is vs. what you are making the compiler interpret it as.
Yes, you are right. You should do
NSArray *array = [NSArray arrayWithArray:mutableArray];
to ensure that nobody can change the array
Your iArray is actually referencing to NSMutableArray instance, that's why it is a NSMutableArray.
Obj-c doesn't have strict check on class types, all objects are of type 'id'.
You could write
NSNumber *iArray = mArray
Compiler will show a warning of wrong cast (not error). But it will work.
Don't mess with pointers, there is no object type transformations as you can expect in C++. (there are overloadable operators for casting object to another class).
Obj-c works with objects much like script/interpreted languages. Dynamic typing (objects only), reflection, dynamic change of methods of instance of classes etc - full flexibility. A perfect mix of speed of low-level C/C++ and flexibility of dynamism.
AFAIK, you are correct. NSMutableArray is a subclass of NSArray, so you can assign mArray to iArray here without a problem.
However, it isn't clean code and you should avoid it.

There's got to be an easier way of dealing with arrays!

To optimize a bottleneck, I converted the creation of a large NSArray to a c-style array. (The resulting creation was 1/8 the time of the original NSArray version. Yeah!) But once it's created, speed is no longer an issue, so I'd rather benefit from it being an NSArray again.
However, it seems ridiculously involved to convert a c-style array to an NSArray (unless I'm missing some magic initWithArrayWrapElementsInObjects method.)
As I understand the process now, I first have to create an NSMutableArray, iterate through the c-style array converting each element (floats in my case) to objects, adding each object to the NSMutableArray, then creating the NSArray with the NSMutableArray.
Is that right? There's got to be a better way.
And help would be appreciated.
Thanks!
There's no direct way to take a blob of memory that you own and "convert" it cheaply into an NSArray-- after all, the framework would need to then own that memory, and it doesn't know where you got it from (malloc, stack, etc). If there were a convenience method for initWithArrayWrapElementsInObjects, it would itself need to do internally what you surmise: iterate over your provided memory and add items to itself (it's possibly the framework could do this as quickly as a memcpy, but who knows).
One way you could tackle this (and probably a fun learning exercise) is by actually creating your own subclass of NSArray that manages memory exactly as you want (ie, lets you create and init with whatever semantics you want), but that behaves to the outside world as an NSArray would. You can do this by inheriting from NSArray and implementing the methods count: and objectAtIndex: to operate on whatever memory you're holding on to. Obviously, you'd need to implement the management of your own memory in the init/dealloc, etc methods as well. See this page http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
under "Subclassing Notes".
The design discussion here hinges on what your data looks like. NSArray, of course, expects its items to be Obj-C references (of type id), and not just arbitrary chunks of data. If your C-style array is holding structures or some other primitive values that aren't object references, then this technique won't really work for you-- NSArray's interface will never be happy with non-reference items.
One final note: you mention taking an NSMutableArray and "creating" an NSArray with it. You should be aware that an NSMutableArray is already an NSArray, since it's a subclass. You can use an instance of NSMutableArray anywhere you'd want an NSArray, without creating some new copy of it.
UPDATE: Missed the note about your array containing floats. Yeah, you're a little bit screwed here. NSArrays want objects. If the capacity doubling was the expensive part (as another poster notes), then try initWithCapacity:. If it's the boxing/unboxing of the floats into object types, there's nothing you can do.
I have created (but don't have handy) a pair of very simple classes (called like MYArray and MYMutableArray) that are intended to wrap just this kind of data with NSArray-like methods on them. But they're not interchangeable with NSArrays. You must use them intentionally.
UPDATE #2. I know it's been ages since this question was live, but I just revisited it and realized there actually is a sort of clever way around this in this specific case. (You want a non-mutable NSArray from a C-style float array). You can create a custom subclass of NSArray that wraps the float values and only converts them to objects when they're accessed via the primitives. This may have performance pitfalls in some corners (?), but it does neatly meet your requirements:
#interface FloatProxyArray : NSArray
{
float * values;
NSUInteger count;
}
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues;
#end
.
#implementation FloatProxyArray
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues
{
if ((self = [super init])) {
values = (float *)malloc(numberOfValues * sizeof(float));
if (!values) {
[self release]; return nil;
}
memcpy(values, arrayOfFloats, numberOfValues * sizeof(float));
count = numberOfValues;
}
return self;
}
- (void)dealloc
{
free(values);
[super dealloc]
}
- (NSUInteger)count
{
return count;
}
- (id)objectAtIndex:(NSUInteger)index
{
if (index >= count) {
[NSException raise:NSRangeException format:#""];
return nil;
}
float val = values[index];
return [NSNumber numberWithFloat:val];
}
#end
(N.B. Written in the editor without compiling/testing.)
One optimization that you can do with the NSMutableArray is initWithCapacity which will prevent the doubling of your array which is the expensive operation in the addition.
Outside of that, since NSArrays and NSMutableArrays expect objects, so it's difficult to get around this.
What benefits of it being an NSArray are you looking to get?
It seems like you may be better off with a custom wrapper object around the C array that responds to whatever NSArray messages you are looking to call. Otherwise you are right back at the point of array creation... You could try manually creating a call to initWithObjects, but at the very least every float has to be wrapped in an NSNumber which would bring down your speed again.
If you really need an NSArray because something else you want to use takes NSArray objects, then you are probably better off subclassing NSArray (following the guidelines posted by Ben).
The “best” optimisation (for speed) would almost certainly be to avoid using NSArray altogether, if possible.