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.
Related
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.
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
I have an application that uses GC for memory management and a framework that does automatic reference counting. When I try to build that, I get this error:
Linked dylibs built for retain/release but object files built for GC-only for architecture x86_64
Is there a correct way to use the ARC framework in this GC application without changing it? I remember to read that ARC code seemslessly works with non-ARC code, but I only find the per-file compiler switch (-fobjc-arc).
No. ARC code works with manual retain-release code, but not with GC code. A framework built for garbage collection only will not work with either manual retain-release code or ARC; a framework built in GC-optional mode will work the same with both.
I have a Mac OS X App that I need to store objective-c objects in stl containers (as pointers). Everything works fine until I compile the program with garbage collection "supported" due to a custom framework that I need to use.
Problem is all the objects that get stored in the stl containers get released. Is there a way to tell the compiler to not collect those away and I'll release them when I'm done with them?
Is this possible? Is there a way to have a framework that uses garbage collection and the main program doesn't? That would also solve my problem. I can recompile the framework, but it heavily relies on GC.
You can disable garbage collection for individual objects using NSGarbageCollector's disableCollectorForPointer: method. It will then hang around until you call -enableCollectorForPointer: on it.
I believe (but I'm not totally sure) you can also use CFRetain/CFRelease on NSObject subclasses for more or less the same effect.
I've long considered myself a garbage collection snob – despite a secret love for C++, I find myself sneering at developers who actively choose to use languages without (read: missing) garbage collection when they're given the option.
And then I met Objective-C. Wow! Its system of reference counting seems brilliantly simple – I'd even go so far as to say elegant. When developing for OSX, developers are given the option to use a snazzy GC; when developing for iOS, developers are stuck with reference counting.
My question is:
If I am developing an OSX application that could potentially be ported to iOS, is Objective-C's reference counting system time-consuming enough (development-wise and bug-fixing-wise) to warrant ignoring it for the application's first version?
What problems am I likely to run into if I rely on reference counting*, assuming I'm not clever enough to construct any diabolically complex cyclical data structures? With features like autorelease, it all seems so easy, but I know that Apple wouldn't have invested the effort into creating a garbage collector if this were really the case. What should I be on the lookout for?
* I am aware that I can use the garbage collector even if I am throwing around retains and releases (they'll be ignored). However, considering non-GC applications often use RAII, I don't understand how that would work if a generational GC were to "replace" calls to retain and release. Wouldn't resources potentially be released late?
My experience with developing code to port to iOS is that taking GC only code and back porting it to reference counting is a bit tedious and time consuming and potentially error prone. Having said that, as long as you use properties (make them retain even though it makes no difference in GC) as much as possible and you enable the static analyser build phase, it's not too bad. The static analyser will catch most failures to observe the memory management rules. It won't notice if you fail to release an ivar in dealloc, but you can go through and systematically add all the dealloc methods.
Bear in mind that you can't directly port a Mac application to the iPhone, the VC part of MVC has to be completely rewritten, so you could take the approach of writing the Mac UI solely for garbage collection and only make the model classes compatible with both GC and reference counting.