Am 11.11.2010 um 17:16 schrieb Christiaan Hofman:
On Nov 11, 2010, at 13:04, Peter Lübke wrote:
In my app, I call AXUIElementCopyAttributeNames() and AXUIElementCopyAttributeValue() very frequently, but as far as I can see, the resulting objects are all properly released and ObjectAlloc and MallocDebug show no indication of possible leaks In your code, do you call CFRelease() on the attribute names and the attribute value when you are finished with them? The convention for Core Foundation functions like these is that, if the function contains the word "copy," you are responsible for CFReleasing the object. This applies to the accessibility functions.
To be exact, I do it like this:
// -valueForAttributeCopy: // Returns an object typed id representing the value for a given attribute of the receiver's AXUIElement or nil if the attribute doesn't exist. // The sender is responsible for releasing the object. - (id)valueForAttributeCopy:(CFStringRef)attribute { id value = nil; id axValue = nil; NSArray *attrNames;
if (AXUIElementCopyAttributeNames((CFTypeRef)_element, (CFArrayRef *)&attrNames) == kAXErrorSuccess) { if ( [attrNames indexOfObject:(NSString *)attribute] != NSNotFound && AXUIElementCopyAttributeValue((CFTypeRef)_element, attribute, (CFTypeRef *)&axValue) == kAXErrorSuccess ) value = axValue; } [attrNames release];
return value; } (where _element is an instance variable with an AXUIElementRef, stored in my AXUIElement wrapper class object.)
This may in fact point to the problem, but you don't say anything about it. You are holding on to the _element, which may lead to the corresponding object in the other app being retained. have you tried instead recreating it rather than putting it in an ivar?
Christiaan
I start iterating over the tree of UIElement children beginning with the application element. This I get with AXUIElementCreateApplication(). Once I get the array of children, I release the parent element, iterate over the children array in the same manner and so on. Every parent is released when I'm done with it. When my scanning method finds a matching element, this element, which is an instance of my wrapper class, is the only object to stay, if not, there's no object left. Everything else is released and releases its _element ivar in its -dealloc method. The reason I put the AXUIElementRef in an ivar is that I want to send action messages to it after retrieving it, and then, again, the wrapper object is released. Thus, you could say, this is a way of "recreating" the UIElement...
Anyway, how can a wrapper class work if it doesn't keep a reference to what it is refering to?
BTW, in most cases, scanning the other app is done looking for a given value for kAXTitleAttribute.
In the calling method, I compare the returned object against the value I'm looking for and then release it by calling [value release].
Do you think it is bad practice to cast CFTypeRefs to type id and releasing them this way?
As I mentioned, ObjectAlloc tells me that my app doesn't accumulate memory allocations, while the other app does. Or am I wrong in that my app is not able (and not allowed) to retain objects in another app's memory space?
Peter
|