Updating CoreFoundation PriorityQueue implementation to take advantage of ARC for iOS - objective-c

I found an implementation of a priority queue that primarily uses CFBinaryHeap to work.
I'm currently using the -fno-objc-arc compiler flag to skip the usage of ARC while compiling these files. I attempted to update this code to take advantage of ARC, though I've run into a few snags of understanding.
Is there anyone here who has updated code similar to this for use with ARC?
How do you handle things like free(), and CFRelease()? Can we just get rid of them?
What do you do with the retain and release methods you create for CFBinaryHeapCallBacks?
Do you use __bride or __bridge_transfer to reference the const void * into Objective-C objects? Likewise should you use (__bridge_retained void *) or obj_unretainedPointer() to do the reverse?

ARC basically is a compiler technology that automatically inserts calls to -retain, -release, and -autorelease as needed. It does not remove the need for retains and releases, it just makes them automatic (in the process, optimizing out many that are not required, and playing other tricks to make various common patterns much more efficient than if you did it by hand).
ARC knows nothing about Core Foundation, nor about void* objects, malloc, free, or anything other than ObjC memory management.
This means that as long as you use Core Foundation objects, you should continue to use CFRelease. And if you malloc memory, you should continue to free it.
But.... what if you want to take memory that was created by Core Foundation and transfer it to Cocoa via a toll-free bridge? That's where __bridge* comes in. One of the best sources of information is the clang docs themselves. A great blog article is Everything you need to know about ARC. It includes many useful links to the definitive information.
But here's the short answer (from Transitioning to ARC)
NSString *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
CFStringRef d = (__bridge_retained CFStringRef)my_id; // returned CFRef is +1
Using __bridge_transfer logically moves a CF object into Cocoa. Using __bridge_retained logically moves a Cocoa object into CF. You use these when you are really transferring ownership of the object. In the above example, you generally shouldn't continue using the my_ variables in my opinion. These are particularly useful in cases where you are returning the result out of the function. These should be used for their logical ownership functionality only. Don't use them as a way to "fake" a manual call to retain or release.
If you just want to have a temporary "bridged" pointer to the object so you can use it in CF or Cocoa without transferring it, then use __bridge. That's a no-op that says "don't do any memory management, just let me pretend for the moment that it's the other kind of object." If you do a lot of toll-free bridging, you'll wind up using __bridge quite a lot (making it seem like a small toll.... :D)

Here is a pure objective-c implementation of PriorityQueue, that supports ARC:
https://github.com/jessedc/JCPriorityQueue/tree/experimental/heap-queue

Is simple to implement non ARC lib into XCode project. Just open "Build Phases"(menu when click on your project target) -> "Compile Sources" and to files, which are not using ARC add by double click flag "-fno-objc-arc" and your're done. So simple :)

Related

How to watch memory allocation/deallocation while program written in objective-c is working on OS X?

I'm studying Objective-C. I've found out about the ARC. I made a simple program with one class and one instance variable NSUInteger.
For educational purposes I'd like to examine the memory allocation/deallocation while the program is running.
Are there any console tools to see a program's memory? Or may be it is possible to do it in the Xcode itself? In other words I'd like to see the memory snapshot in different points in times when an object was allocated and then an object was deallocated.
Thank you.
First, NSUInteger variables are no objects in the meaning of Objective-C. They are handled with the C memory management. (Typically they are local vars on the stack, freed, when the local scope is left.)
So let's go to real instance objects of classes like NSNumber or NSString or – more important – MyCustomClass. You can see the whole processing of memory management, when you write a class and compile that with manual memory management. (This is possible via the compiler options. Select the project, go to build phases/compile sources and you will find an extra column compiler flags.)) Since ARC and MRC work together, ARC code will execute the MRC memory handling methods. Simply overwrite them in the MRC class and do some logging, set some breakpoints and so on.
But, this is very important, as long as you only deal with ARC code, you simply do not have to care about memory management. Maybe it is a good idea to learn that, but it is not something you have to do necessarily.

Objc Cocoa MRC - Released and autoreleased objectsI have to write him up to see application

I'm writing a C++ application using Metal API (objective C) and MRC (Manual Reference Counting). I have a very limited experience with ObjC. Most of the Metal API objects are defined as protocols and created as an object returned from C-function or other object's method (ex. MTLDevice newBufferWithLength). To know how to release objects created this way I need to know if they have been set autoreleased or not (I can't call release an autoreleased object with retain count 1 for instance). The problem is I can't find any description in Metal API documentation which would answer this question. I've only read in user guide that all so called lightweight objects are created autoreleased. There are three examples of autoreleased objects but not sure if I can just assume that rest of the objects are not autoreleased. In cocoa many objects also may be created without alloc+init, being returned from a static method (ex NSString string) so the problem seems not to be only Metal related.
Thank you for your help.
The usual Objective-C rule is that creating scope is also responsible to release object. So, in virtually all cases, except well-documented exceptions, returned object is autoreleased (both returned through return value or out-arguments). More correct way to see it is that object is always returned with +0 scope-local retain count, so you are expected to retain it if needed. Reading the manual it seems that Metal API is one of Apple's frameworks, so it should follow this rule unless warned with bold statements. C functions in Objective-C are also expected to behave that way. (There is no difference between a method and a function in terms of resource management.)
For that "alloc-init vs. [NSString string]" part: MRC code either returns [NSString string], which is already +0, or [[[NSString alloc] init] autorelease]. Otherwise it breaks the convention. Exceptions are -[init] and +[new...] methods itself that return +1. Under ARC there is no difference between alloc-init/string, because ARC knows the convention and does the right thing, optimizing excessive retains/releases where possible.
Also note that -[retainCount] is meaningless and "considered harmful", because you never know how many retain-autorelease calls were performed and what objc-runtime accounting is in effect even with your own objects.
ARC is really a great option unless you're writing some sort of Objective-C -to- Whatever bridge, where retain counts and/or cycles must be managed explicitly due to lack of context. It doesn't take anything from you, giving in most cases a big advantage of not managing resources at all.

Memory Leaks when Working with Address Book Contacts in iOS6

I'm using ARC, and my application compiles and works without crashing. However, when I run an Analyze build, I am seeing these warnings. I come from PHP and JavaScript so naturally I have no idea what to do to fix this stuff. Can anyone help me out?
ARC needs some help when dealing with Core Foundation. Try this:
NSArray *linkedPeople = (__bridge_transfer NSArray *)ABPersonCopyArrayOfAllLinkedPeople(person);
and
NSDictionary *personDictionary = (__bridge_transfer NSDictionary *)(ABMultiValueCopyValueAtIndex(addressFromPerson, 0));
__bridge_transfer tells ARC that a non-Objective-C (i.e., Core Foundation) pointer is being moved to an Objective-C pointer, and it allows ARC to take ownership of the object for memory management purposes. CF functions with the word "copy" in them produce an object reference with a +1 reference count. If you don't explicitly call CFRelease() on the object later, then it will leak. Using __bridge_transfer, however, lets ARC do this for you.
(Note: I didn't test this, but I believe those are the issues that the static analyzer is complaining about.)
Yes, you can use:
NSArray *linkedPeople = (__bridge_transfer NSArray *)ABPersonCopyArrayOfAllLinkedPeople(person);
But Apple now recommends using:
NSArray *linkedPeople = CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
It does the same thing, but Apple recommends you use the latter.
See WWDC 2012 session 405, 37:33 into the presentation.
So! Even though you're using Automatic Reference Counting (ARC), it's still a good idea to read up on Objective-C Memory Management:
http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/
But, for your specific problem:
Generally, when you see a C method in the Apple frameworks that has the word Copy in it, you're taking ownership of that Core Foundation type and you need to release it. When you want to release that type, just use:
CFRelease(addressFromPerson)
That's the first issue. Your screenshot cuts off the second error so I'm only speculating, but I think you also need to release your NSDictionary *personDictionary. Similarly:
CFRelease(personDictionary)
Note that you also need to manage the memory for linkedPeople
Normally ARC will take care of memory management for you, but when working with Core Foundation types, you still need to clean up after yourself.
I would strongly recommend you check out these great resources on memory management with ARC, particularly when dealing with CF types and toll-free bridging:
http://www.joergjacobsen.com/blog/2011/10/05/managing-toll-free-bridging-in-an-arced-environment/
http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

Using a custom allocator in an iOS library

I'm creating a library that will be used by multiple types of iOS apps. Part of my API allows a user to specify routines that will be used for the library's allocations. My library is implemented mostly in C++, so this has been straightforward so far.
However, I've recently been adding some user interface functionality to the library: displaying a UIWebView using a custom view controller. I'm not sure how to ensure that my allocators are used for these objects.
How can I ensure that all of the Cocoa UI objects created by my library are allocated with my own functions?
I've tried a few things including overriding -initWithZone and calling CFAllocatorSetDefault before my -init. None of them have worked yet; and honestly I'm still a beginner with Objective C and Cocoa, so I'd like to know what the "correct" way to do this is.
I'm unable to find evidence of it now, but it certainly was the case that CFAllocator, malloc_zone_t and NSZone were all toll-free bridged. So you could just cast your allocator to an NSZone and pass it along.
I think the problem you're going to face is that NSZone was added at NextStep so as to allow a program to maintain multiple heaps, with the feeling being that it would allow programmers to keep related objects close to one another in memory — which is good for caching — and in some cases to throw away entire object graphs without walking the graph, which is obviously fast. However the former was of little benefit in practice and the latter is more likely to create problems than to be of actual benefit. So Apple has back-peddled from NSZones, gradually turning the related runtime calls into no-ops and removing detailed documentation. Apple's feeling is that, at the Objective-C level, you should not only maintain only a single heap (which is a side issue from your point of view) but that they'll always know best how to maintain it.
EDIT: an alternative idea is to replace NSObject's alloc, that being the thing that creates memory. The Objective-C runtime is well-defined enough that we know exactly what behaviour alloc exhibits, so that a vanilla version might be:
+ (id)alloc
{
Class *newInstance;
// we'll use calloc to ensure we get correct initial behaviour of
// everything equal to 0, and use the runtime's class_getInstanceSize
// so that we're allocating the correct amount of memory irrespective
// of whether this call has fallen through from a subclass
newInstance = (Class *)calloc(1, class_getInstanceSize(self));
// the thing that defines a class is that the first thing stored in
// it is the isa pointer, which points to the metaclass. So we'll
// set the isa pointer appropriately
*newInstance = self;
return (id)newInstance;
}
To replace NSObject's normal init, you'd probably want to define your alternative as a category method on NSObject named, say, customInit, then use class_getClassMethod, class_getMethodImplementation and method_setImplementation directly on [NSObject class] to switch it into place. See the Object-C Runtime Reference for documentation on those.

Under automatic reference counting, why are retain, release, and dealloc not allowed?

When trying to use -retain, -release, and -dealloc while building my application using automatic reference counting in Xcode 4.2, I get an error like the following:
Automatic Reference Counting forbids
explicit message send of 'dealloc'
Why am I seeing this error? Are -retain, -release, and -dealloc no longer allowed under automatic reference counting?
Basically:
When using ARC, it's all or nothing. Either the compiler is managing all of the retains/releases/deallocs for you, or it is doing nothing. You cannot intersperse your own calls to them, because the compiler wants to do it all itself. It can make absurd optimizations by doing this (for example, a method that returned an autoreleased object under Manual Memory Management may now produce an object that never ends up in an autorelease pool). If you were to start sprinkling in your own calls to retain and release, then the compiler would have to work with these and wouldn't be able to perform a lot of the optimizations that it wants (and that you should want).
And as an added bonus, invoking -retainCount is now a compiler error! OH HAPPY DAY!
in response to AliSoftware: we CNA mix ARTC and not-ARC frameworks, and also arc and not-ARC source.
(I did it..)
The basic ideas are:
1) compiler will insert/remove calls as a very-very-good cocoa programmer can do
2) cocoa is ANYWAY C code, so we have separate compilations, so the linker CAN link binaries produced by multiple sources. Think it as we can mix asm and cocoa, or C and pascal...
in main opinion the Appleadvantege over c# / java is here: we are alway allows to mix, and, using a COMPILER technique 8non a runtime..) we can rush performance beyond.
Under automatic reference counting, retain, release, and dealloc are not allowed.
If you have an existing code, you can keep using it as is with the -fno-objc-arc you can selectively disable ARC on any file.
If you want to disable ARC on MULTIPLE files:
Select desired files at Target/Build Phases/Compile Sources in Xcode
PRESS ENTER. (double click selects only one file)
Type -fno-objc-arc
Press Enter or Done
As I have pointed out in my answer on Xcode ARC, you can compile specific source files as non-ARC. Dave DeLong's answer is a bit off. It doesn't include the fact that you can instruct the compiler to compile source as non-ARC in an ARC-enabled project (as explained here).