How to programmatically detect automatic reference counting? - objective-c

This might be a silly question, but I just wanted to know. I want my code to detect if ARC is enabled, programmatically. How do I do that? Is there is any flag that I could check? Actually the problem is that, I have written an open-source library. I have used release and retain in it. if some one else uses my library files using ARC enabled, I dont want them to get any errors. how do I achieve this? or is there any possible ways I can provide any tools to compile my library before using it?

#if !__has_feature(objc_arc)
//Do manual memory management...
#else
//Usually do nothing...
#endif
This is of course a compile-time check, you cannot check for ARC at runtime.
An alternative would be to set the -fno-objc-arc compiler flag for your files that use manual memory management in a project that otherwise uses ARC.
Whether you want to bother with this at all or just use ARC everywhere depends on how backward-compatible you want/need to be. Code that supports both ARC and MRC can get quite hard to read and maintain.

You don't detect it programmatically, it operates based on translations. That is, it is not like Garbage Collection -- which is process-wide, required all linked libraries to support (and implement it correctly in that mode). You can have some files compiled with ARC, and some without.
However, you can detect it at compilation.
As far as the distribution of your library: I would not bother with a translation based system, where ref count ops are conditionally enabled. I would (personally) just support one model (MRC in your case, until you choose to migrate it to ARC), then expect people to link to the library, or if they compile it in a target they configure, to disable ARC. Conditionally enabling/disabling code based on the presence of a feature is asking for tough bugs, particularly when it's likely to affect 9% of your library's lines of code.

NO, you can't, Xcode would not compile in ARC projects if your source uses retain-release

Related

Using autorelease requires disable ARC

Hello I am completely new to Apple development
I used this code in my project
https://github.com/vladinecko/accordion-uitableview/tree/master/AccordionTableView
, project releases the memory itself using autorelease
What made ​​me disable the ARC
Because ARC does not allow the use of autorelease
My question is whether to delete the autorelease from the code
And use ARC or i can not do it and I need to have to release the memory for myself
You could leave the code as-is—you can compile some files using ARC and others not, but that’s going to be messy and hard to maintain.
What I’d recommend doing is running Xcode’s ARC-ifying on the code, to get rid of retain and release and autorelease.
In Xcode 5, look under the “Edit” menu for “Refactor”, and select “Convert to ObjC ARC”.
Apparently AccordionTableView does not use ARC, whereas in your project you are using it.
So you have three options
Switch off ARC only for the separate compilation units, which are from AccordionTableView
Adapt the code snippet from AccordionTableView project with ARC guidelines
Switch your own project to not use ARC
First, being new to Objective-C development you need to learn how memory management works. Google for "Apple memory management" and you should find relevant documents.
Before ARC, people did memory management by hand. With ARC, ARC does it for you. The exact same memory management operations should happen, except that with ARC you have less programmer work, and chances to get it right are better.
You have two choices: Either turn ARC off for individual files. This is done in Xcode / target settings / Build phases / Compile sources by adding -fno-objc-arc to the build settings for individual files where you don't want to use ARC. If you use the same files in different projects, you have to do this in every target.
The other choice is to convert the files to ARC. Let the compiler run, remove offending memory management code, which is mostly retain / release / autorelease. If the code uses CoreFoundation functions, then you really need to understand memory management, just hope it doesn't. Use "Analyze" to let the compiler check very carefully that everything is fine.

What is the correct way to fail at compile-time if ARC is off?

I'm working on some Objective-C code I expect to spin off into a library or at least share with some other people. It requires ARC to use, and if ARC is not enabled, it will leak memory.
What is the correct way to make the code fail to compile if ARC is turned off?
You can check for ARC at compile time with
#if __has_feature(objc_arc)
I think a cleaner approach would be to compile the library as a static library. As ARC will incorporate the release calls according to the rules into the compiled library, it doesnt matter from that point on, if the project it is added to is ARC or MRC — so no hassle for the library user.

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).

Mixing garbage collected framework with normal code

I know my way around Objective-C and I have experience with garbage collection from .NET, although I never used it in objective-c. I write my code without using it.
Now I'm thinkig about using one of the frameworks (Blocks) which is available as GC-only. My question is - can I still use the framework without any changes to my current non-GC code and without using GC myself?
A process is either GC or non-GC. That is, all Objective-C will either always be GC'd or will never be GC'd. There is no mixing of the two memory models in a single process. You cannot mix a GC only framework with a non-GC only framework.
When building a framework, you can set GC to "supported" at which point in time the framework could be used in either a GC'd or a non-GC'd process. However, you will have to maintain correctness for both running environments separately.
What is this "Blocks" framework to which you refer? If you are talking about Blocks, the language feature shipped in Snow Leopard's Objective-C, then it works just fine under both GC and non-GC.
As stated in the garbage collection programming guide, "Code compiled as GC Required is presumed to not use traditional Cocoa retain/release methods and may not be loaded into an application that is not running with garbage collection enabled."
So no, unfortunately. But how much work it would be to adopt garbage collection depends on your app. You might try testing to see if it looks like a big project. (It often is, but sometimes it's not so bad.)
In project settings, you can compile with GC supported (NOT required) and they should mix just fine. Compiling with GC supported but not required should allow retain/release to work alongside GC
If you can't compile the project with GC supported, then you'll be in trouble.
EDIT: To clarify: If you compile your project with GC required (-fobjc-gc-only) your retain/release code will be ignored. If you compile without any regard for GC, you can't use the GC framework. However, if you compile with GC supported (-fobjc-gc), your retain/release code will function as needed, and the GC framework will also work.
EDIT: To further clarify (I'm really tired today): If you include a GC-only framework, you have to compile with -fobjc-gc or -fobjc-gc-only and run with garbage collection, in which case your retain/release statements will indeed be no-ops. However, if you compile with -fobjc-gc-only and try to include a framework that is not build with any GC support, you'll have issues. Whereas my understanding is if you compile with -fobjc-gc, you can include a GC-only framework as well as a non-GC framework. From the docs I linked above:
Code compiled as GC Supported is
presumed to also contain traditional
retain/release method logic and can be
loaded into any application.
So if you wanted your Framework to play nice with anything, you'd be better served to compile with -fobjc-gc instead of -fobjc-gc-only.
Apparently I was having a hard time getting my thoughts to the keyboard yesterday. According to the docs:
-fobjc-gc-only This means that only GC logic is present. Code compiled as GC
Required is presumed to not use
traditional Cocoa retain/release
methods and may not be loaded into an
application that is not running with
garbage collection enabled.
So if you build your framework with GC Required, you can't load it into a non-GC-enabled application.
Also according to the docs:
-fobjc-gc This means that both GC and retain/release logic is present. Code
compiled as GC Supported is presumed
to also contain traditional
retain/release method logic and can be
loaded into any application.
So while the burden is on the developer to include retain/release logic in a project that is compiled GC Supported, this allows a framework to be loaded in any application.
I apologize for my unclear rambling yesterday. I was running on 3 hours sleep and trying to do several things at once. Never a good idea.

Avoiding, finding and removing memory leaks in Cocoa

Memory (and resource) leaks happen. How do you make sure they don't?
What tips & techniques would you suggest to help avoid creating memory leaks in first place?
Once you have an application that is leaking how do you track down the source of leaks?
(Oh and please avoid the "just use GC" answer. Until the iPhone supports GC this isn't a valid answer, and even then - it is possible to leak resources and memory on GC)
In XCode 4.5, use the built in Static Analyzer.
In versions of XCode prior to 3.3, you might have to download the static analyzer. These links show you how:
Use the LLVM/Clang Static Analyzer
To avoid creating memory leaks in the first place, use the Clang Static Analyzer to -- unsurprisingly -- analyse your C and Objective-C code (no C++ yet) on Mac OS X 10.5. It's trivial to install and use:
Download the latest version from this page.
From the command-line, cd to your project directory.
Execute scan-build -k -V xcodebuild.
(There are some additional constraints etc., in particular you should analyze a project in its "Debug" configuration -- see http://clang.llvm.org/StaticAnalysisUsage.html for details -- the but that's more-or-less what it boils down to.)
The analyser then produces a set of web pages for you that shows likely memory management and other basic problems that the compiler is unable to detect.
If your project does not target Mac OS X desktop, there are a couple of other details:
Set the Base SDK for All Configurations to an SDK that uses the Mac OS X desktop frameworks...
Set the Command Line Build to use the Debug configuration.
(This is largely the same answer as to this question.)
Don't overthink memory management
For some reason, many developers (especially early on) make memory management more difficult for themselves than it ever need be, frequently by overthinking the problem or imagining it to be more complicated than it is.
The fundamental rules are very simple. You should concentrate just on following those. Don't worry about what other objects might do, or what the retain count is of your object. Trust that everyone else is abiding by the same contract and it will all Just Work.
In particular, I'll reiterate the point about not worrying about the retain count of your objects. The retain count itself may be misleading for various reasons. If you find yourself logging the retain count of an object, you're almost certainly heading down the wrong path. Step back and ask yourself, are you following the fundamental rules?
Always use accessor methods; declare accessors using properties
You make life much simpler for yourself if you always use accessor methods to assign values to instance variables (except in init* and dealloc methods). Apart from ensuring that any side-effects (such as KVO change notifications) are properly triggered, it makes it much less likely that you'll suffer a copy-and-paste or some other logic error than if you sprinkle your code with retains and releases.
When declaring accessors, you should always use the Objective-C 2 properties feature. The property declarations make the memory management semantics of the accessors explicit. They also provide an easy way for you to cross-check with your dealloc method to make sure that you have released all the properties you declared as retain or copy.
The Instruments Leaks tool is pretty good at finding a certain class of memory leak. Just use "Start with Performance Tool" / "Leaks" menu item to automatically run your application through this tool. Works for Mac OS X and iPhone (simulator or device).
The Leaks tool helps you find sources of leaks, but doesn't help so much tracking down the where the leaked memory is being retained.
Follow the rules for retaining and releasing (or use Garbage Collection). They're summarized here.
Use Instruments to track down leaks. You can run an application under Instruments by using Build > Start With Performance Tool in Xcode.
I remember using a tool by Omni a while back when I was trying to track down some memory leaks that would show all retain/release/autorelease calls on an object. I think it showed stack traces for the allocation as well as all retains and releases on the object.
http://www.omnigroup.com/developer/omniobjectmeter/
First of all, it's vitally important that your use of [ ] and { } brackets and braces match the universal standard. OK, just kiddin'.
When looking at leaks, you can assume that the leak is due to a problem in your code but that's not 100% of the fault. In some cases, there may be something happening in Apple's (gasp!) code that is at fault. And it may be something that's hard to find, because it doesn't show up as cocoa objects being allocated. I've reported leak bugs to Apple in the past.
Leaks are sometimes hard to find because the clues you find (e.g. hundreds of strings leaked) may happen not because those objects directly responsible for the strings are leaking, but because something is leaking that object. Often you have to dig through the leaves and branches of a leaking 'tree' in order to find the 'root' of the problem.
Prevention: One of my main rules is to really, really, really avoid ever allocating an object without just autoreleasing it right there on the spot. Anywhere that you alloc/init an object and then release it later on down in the block of code is an opportunity for you to make a mistake. Either you forget to release it, or you throw an exception so that the release never gets called, or you put a 'return' statement for early exit somewhere in the method (something I try to avoid also).
You can build the beta port of Valgrind from here: http://www.sealiesoftware.com/valgrind/
It's far more useful than any static analysis, but doesn't have any special Cocoa support yet that I know of.
Obviously you need to understand the basic memory management concepts to begin with. But in terms of chasing down leaks, I highly recommend reading this tutorial on using the Leaks mode in Instruments.