How can I get the Address of an object stored in a NSMutableArray?
I have something like this:
class member variable in .h:
MyClass *__strong*_selectedobject;
in a function in .m:
MyClass *objReference = [_messageBoards objectAtIndex:idxInCaseOfContract];
_selectedobject = &objReference;
the problem is, that _selectedobjectis nil as soon as the function finishes.
_selectedobject is an instance variable within a singleton class. It works with other objects which are not within an array. Also, the object within the array is not suddenly nil, it is just the reference.
You can not get pointer to a position inside an array in Objective-C.
If you need to retain position in an array, so that if another object is written there you'll have it instead of the old one, then save index of that position (and retain the array too if needed). Mind that modifications to the array may render the index invalid.
If you need to retain only the object which was read from array at that moment, simply retain that object. Object address is the object pointer itself, there are no extra indirections.
UPDATE
I'm just posting here how you can store reference to address in object(as question was originally about that), however I strongly advice anyone to think again if this is actually needed:
#interface MyClass : NSObject
{
NSMutableArray* test;
__strong id* foo;
}
*foo = [test objectAtIndex:2];
ORIGINAL ANSWER
As #Vijay-Apple-Dev.blogspot pointed out you are missing something very important about memory - you are making _selectedobject to point to address of temporary variable(objReference) instead of object in memory([_messageBoards objectAtIndex:idxInCaseOfContract]). All method variables becomes nil after their method goes out of scope, and thats why your reference becomes nil(although array is still alive and object is there). Simply do not use local variable and everything should be fine.
Side note - what's the purpose of using address reference instead of object pointer? If you think you're gone save memory you are wrong, as ARC(and MRC also) are working differently ;)
MyClass *objReference is local variable to the method. So once it method finishes, everything will be gone from memory. If you want to keep them, then you have retain them in header file(.h) as instance variable.
#property(nonatomic,retain) MyClass *objReference;
then
self.objReference = [_messageBoards objectAtIndex:idxInCaseOfContract];
NOTE: You must use the self dot syntax when u retain the object. otherwise wont work.
Related
When you write code like below in ARC
__weak NSMutableArray* array = [[NSMutableArray alloc] init];
The compiler will show you a warning or error and say "Assigning retained object to weak variable. object will be released after assignment".
But if you write like this:
__weak NSMutableArray* array = [NSMutableArray array];
There is no error.
I'm wondering if the second usage is reasonable in some situations? What's the difference between these two codes from memory management perspective? How does it work?
There can be very subtle differences that the compiler cannot know.
Let's take an immutable version: [NSArray array] could return the very same static object every time. So your weak variable will point to a valid object, that has a strong reference somewhere else. Or think of the singleton pattern. On the other hand, when calling alloc/init, convention dictates that you're the only owner of that object, and that will typically leave you with nothing.
Also, the factory method certainly looks more like a (functional) method. In any case, it doesn't communicate ownership of what it returns very well. For an autoreleased object, it's not clear whether you're the the only owner or a shared owner.
They are the same because you lose the object instantly. Compiler cannot know probably, except alloc init, that the object will be lost.
In the first form, the method returns a retained object. ARC ensures, that the object is released when there is no strong reference on the call-site. This is immediately true, with the weak reference - thus, the compiler emits a warning or error.
In the second form, the method returns an unretained object. In this case, the compiler must ensure that the object is still valid across the return boundary. When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. That is, there is a strong reference created by the compiler. This strong reference will be automatically released by the compiler generated code.
Thus, in this case there's no error or warning.
In the worst case, holding that object may require to use an autorelease pool. However the compiler can apply certain optimisations which avoids this. Thus we should not assume that the returned object lives in an auto release pool.
See specification: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14
See also this question on SO: Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]
EDIT: This is for a static NSMutableDictionary, not a class member. I see a lot of answers thinking it's a class member, sorry about that. Thanks for the quick responses.
I had a working piece of code, but it was used 2x, so I wrote a convenience function:
- (void) initializeDictionary:(NSMutableDictionary*)mutableDict fromPathName:(NSString*)path
{
mutableDict = // get from file, init if not there.
}
Then I noticed nothing was saving. Stepping through the code, the function creates a dictionary, but the "passed in" value is still nil upon returning. This completely blows away my understanding of pointers (don't take this the wrong way, I'm very comfortable). But their purpose, I thought, was to let you "pass the address" so I could hydrate the thing it points to.
since mutableDict is the "value copy", ARC appears to be wiping it out. I'm asking here because
the other questions have the opposite question "Why is this being retained?" and
It doesn't seem right. Your very first tutorial in any pointer language is "so you can mess with the original value". Does Arc really do this? Is there a concept I'm not getting?
And of course, I may be overlooking something simple.
I seem to have solved it by doing the writeback trick I found elsewhere:
- (void) initializeDictionary:(NSMutableDictionary* __strong *)mutableDictionary fromPath:(NSString*)path;
and using the & to call and * deref to change the value. It just seems far less than elegant.
You pass a pointer of NSDictionary. If you change the pointer value of mutableDict (by allocation or assignment) this will NOT be reflected on the variable passed as this function's argument and since mutableDict is locally defined in the function it will be released by ARC automatically. (Do not forget that even for pointers the address is copied when passed to a function).
The reason that your second solution works is because you pass a pointer to a pointer (not sure if strong is needed there). The value of *mutableDict will be reflected outside since you update a value in the address pointed to by mutableDict. This value is the address of your allocated dictionary and since you change it via a pointer it will be reflected outside the function.
To do what you want you use multiple indirection
- (void) initializeDictionary:(NSMutableDictionary**)mutableDict fromPathName:(NSString*)path
{
mutableDict = // get from file, init if not there.
}
Notice the parameter is (NSMutableDictionary **), a pointer to a pointer to an NSMutableDictionary.
To call the method you need to create a pointer and pass it in like this:
NSMutableDictionary *mutableDictionary;
[self initializeDictionary: &mutableDictionary fromPathName:...];
And on return, the mutableDictionary variable will have been initialised by the method.
However, It's probably easier to just return the dictionary from the method rather than doing it this way.
In Objective-C if you define a variable in a method, the variable is visible only in that method.
If you need to save the variable to use it outside, you need to "return" it from your function. What you did wasn't a trick, is another way of returning a variable.
Try with:
- (void)initializeDictionaryFromPath:(NSString*)path {
NSMutableDictionary *mutableDict = // your initialization
return mutableDict;
}
Then you can define your dictionary with this code:
NSMutableDictionary *mutableDict = [self initializeDictionaryFromPath:path];
I'm new to Objective-C and ARC, and have been searching and reading for hours without finding an answer. The code does what I want it to do, but I want to know that it doesn't rely on favorable conditions. Here's a simplified version of my code:
+(void)foo {
Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * someValue);
// Perform work without complicated memory management
free(classes);
}
I can't do much about the structure I'm allocating. It's filled by objc_getClassList. Unfortunately, Apple doesn't seem to have updated their documentation to explain how to do this under ARC. The typecast above is partly conceived by looking at examples, but it still makes me nervous.
One of my concerns is that if I would have allocated space for a "regular" object, then dealloc would have been called when the variable goes out of scope, which would have happened after free is called. But I don't think that's exactly what's going on here.
Does Class behave differently from other kinds of Objective-C data types? Should I expect something else from it?
What kind of pointer is classes? I guess it references an array of unknown size (a non-object pointer), but ARC still cares about it since the code won't compile without that cast. It looks like a strong pointer, but I don't know what it would be a strong pointer to.
Are there strong pointers to the objects in the array at all, or are the objects themselves strong pointers? If not, does ARC still work, or should I revert to some MRC conventions?
Will there be an automated call to dealloc? When, and how can the compiler ensure that that happens?
Is it better practice to set classes to NULL, and only then do the call to free? Or should I iterate over the array and do something about every object, such as setting them to nil?
you are allocating an array of struct pointers (Class == pointer to a struct), which will be filled with pointers to the Classes registered to the runtime. This pointers will not be released/dealloced etc. as long as your application runs.
You are not allocating any-classes, you are allocating space to hold pointers to this classes. Your code is totaly fine, and __unsafe_unretained is exactly what you want. It tells ARC you are holding a pointer to an Object you are not owning, and so prevent it from trying to release it at the end of the scope of your variable.
Does Class behave differently from other kinds of Objective-C data
types? Should I expect something else from it?
Class is a type that can hold a pointer to any class object, just like how id is a type that can hold a pointer to any object, and how NSString * is a type that can hold a pointer to any object that is an instance of NSString (or subtype thereof). Class objects are (one kind of) objects, and work in basically the same ways that other objects do. The type Class can be used just like other object-pointer types.
What kind of pointer is classes? I guess it references an array of
unknown size (a non-object pointer), but ARC still cares about it
since the code won't compile without that cast. It looks like a strong
pointer, but I don't know what it would be a strong pointer to.
classes is a pointer to Class, i.e. a pointer to a pointer to a class object. You are using it here to point to the first member of an array of Class, which is correct. classes is not an object pointer, but it is a pointer to an object pointer; that's why ARC cares. It's just like if you cast the result of malloc to id * or NSString **. When you don't specify a qualifier on Class, it is implicitly __unsafe_unretained. So classes is already a pointer to an unretained object pointer.
Are there strong pointers to the objects in the array at all, or are
the objects themselves strong pointers? If not, does ARC still work,
or should I revert to some MRC conventions?
Will there be an automated call to dealloc? When, and how can the
compiler ensure that that happens?
Class holds pointers to class objects. Class objects are basically singletons; they are not reference-counted. They generally live for the duration of the program, except perhaps if the class is unloaded. It's not necessary to maintain an explicit strong reference to the class object; the class will stay around.
Is it better practice to set classes to NULL, and only then do the
call to free? Or should I iterate over the array and do something
about every object, such as setting them to nil?
You obviously shouldn't set classes to NULL before calling free(); that way, calling free(classes); won't do anything. Since the elements of this array are __unsafe_unretained, there is no point to setting them to anything before freeing the memory; it will not make a difference.
When it comes to accessing objects from different methods in the same class, from what I understand, these are two ways to do it. Given that I DO want to hold a property pointer to this object, which is the better way to go about this? I've been thinking about this for a while, and wondered if there is a preference consensus.
#1:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomethingToMyArray];
This method takes no parameter and accesses the array via its own property via self
- (void)doSomethingToMyArray
{
// Do stuff with/to the array via self.myArray
[self.myArray ...];
}
Vs #2:
NSArray *array = ... // Get array from somewhere
self.myArray = array;
[self doSomething:array];
This method takes an array and accesses the array via its own method parameter
- (void)doSomething:(NSArray *)array
{
// Do stuff with/to the array via method parameter "array"
[array ...];
}
I think it's primarily going to depend on what doSomethingToMyArray does and who calls it.
Fairly obvious comments:
if you want to do that to more than one array, you need to take an argument;
if what you're doing is actually logically more to do with the array than with your class (e.g. you've implemented randomisation of the order of the array) then it'd be better as a category on NSArray rather than being anywhere in that class at all;
if there's any possibility of subclasses wanting to redefine the manner in which the array is obtained then you'll want to invoke the getter somewhere;
similar concerns apply if a subclass or an external actor should be able to intercede anywhere else in the process.
Beyond those concerns there are a bunch of us that just prefer this stuff to be functional anyway — noting that you're doing something to the array, not with the array, in which case you'd tend more towards self.myArray = [self processedFormOf:array] (or self.myArray = [array arrayByDoingSomething]; if the category tip makes sense).
So, ummm, I don't think there's a clear-cut answer.
That depends on what you want to do, just by reading it:
doSomething:array
I would assume the above method takes ANY array and performs an action, whereas:
doSomethingToMyArray
with this method you are describing the intention of doing something to your instance's array. Inside this method (given that you followed Apple good coding practices and you synthesized your property to _myArray) , you could either go with:
[self.myArray message]
or preferably
[_myArray message]
Your second option is sort of silly. If you're storing a pointer in an instance, then it's so that you can use it later (within that instance) without needing to pass it around whenever you call a method.
This is also dependent on whether you're using ARC or not (use ARC if this is a new project). In a non-ARC project, self.myArray = foo; will do a very different thing than myArray = foo; (the self. syntax calls a property, which in many cases will correctly retain the thing you've assigned). In an ARC project, they'll generally have the same behavior, and there's less room for error.
Personally, in my ARC projects, I do not use the self. syntax from within a class, since it's just extra typing for the same effect. This ties in nicely with the new usage of #property, where you're no longer required to write a #synthesize block, and Objective-C will automatically generate an ivar for you, with the name of your property prefixed by an underscore, i.e. _myPropertyName. That makes it very clear visually when you're accessing code from outside the class (crossing the encapsulation boundary), where things will look like foo.bar = baz; versus inside the class, where it's just _bar = baz;.
IMHO, clearly, a function call would incur an extra overhead.
you would have to allocate an object pointer (though minimal) over the stack (extra memory)
Have to pass it (extra processing)
Property is actually a small function call unless you have made customizations to the getter. I also assume that compiler may have its own optimizations put in place for such accessors so that you can access them with minimal overhead, though I do not have any source to cite this.
When I'm setting a property with an object that is currently in a retained NSArray, will it only store the pointer (light-weight), or will it copy the contents to the property?
From what I know, it seems like it would only assign the pointer, but I'm not sure.
Also, under what circumstances would using *pointer = *otherPointer or the set methods (setDelegate, for instance) copy the value, instead of just passing the pointer, if any.
Shouldn't it always just pass the pointer address?
It always passes the pointer, as you said. Unless you are specifically adding a de-referencing sign, this will always be the case.
However, when you add a property to a class, and set the setter to copy:
#property (nonatomic, copy) id obj;
When using the dot syntax or the setter, This will be translated to:
_obj = [otherObj copy];
Here, it will depend whether the object in question supports copying itself, or will it fall back to it's super class NSObject or another intermediate class's copy.
Moreover, Collection classes NSDictionary and NSArray do a shallow copy, as in they copy the references to their objects only, so you have two collections pointing to the same set of objects.