There are a few trailblazing developers out there who intentionally set their app’s deployment target to iOS 6. When dealing with open source libraries like DTCoreText this might give you a fair share of deprecation warnings. But there is also another problem caused by this that library vendors need to address.
The SDK used should always be the Latest iOS, but the Deployment Target setting tells the compiler and linker at what level of fanciness it can enable the turbo features.
One such special feature that only gets enabled if the deployment target is no less than 10.8 on Mac or 6.0 on iOS is ARC-support for GCD objects. Such objects are for example GCD semaphores and dispatch queues.
This is the kind of warning/error you will see that tells you that some work is necessary:
Those pop up in places where you never thought you would see them. But only if the deployment target allows activation of GCD ARC mode.
This is quite a bit of a problem for people who use many open source libraries, like this gentlemen who raised a CocoaPods issue for it.
How To Fix That 1: Disabling ARC-support for GCD Objects
There are two kinds of approaches that you can take with this: you can force-disable ARC-support in GCD, or you can hide the deprecated code with a preprocessor directive.
You can disable ARC-support by setting a compiler define. In a Podspec you would add this line:
s.compiler_flags = '-DOS_OBJECT_USE_OBJC=0'
In Xcode you can put this define into the Preprocessor Macros.
As component vendor you have to do both because of the nature of CocoaPods which compiles the code into a new static library, independent from your Xcode project settings.
How To Fix That 2: Conditionals
Option 1 is for the lazy ones, the ones that say “our code still targets iOS 5”. Well, DTCoreText targets 4.3, but still I want it to build without warnings if the deployment target is set to 6.0.
You can easily check the above mentioned preprocessor define in code with strategically placed #ifs to disable deprecated code. Here are a couple examples that I fixed today.
Before:
After:
If the “OS OBJECT” is using ARC then the compiler doesn’t even see the dispatch_release.
This is a different scenario. The IVAR selfLock is defined via an assign property. So the compiler is absolutely correct in telling us that the object will be released right after assignment since there is no strong reference.
The fix is just as simple, there might be a more elegant way to just change the keyword, but I couldn’t be bothered.
We only need to get the IVAR created as strong and the warning is gong… uh, gone.
Conclusion
My first approach was to try to combine target conditionals for OS X 10.8 and iOS 6, but Alex Akers came to my rescue and prevented me from forming a knot in my brain.
@cocoanetics You could just do #if OS_OBJECT_USE_OBJC ?
— Alex Akers (@a2) January 18, 2013
Now you know how it’s done. Go and fix your open source code.
Categories: Recipes
What if OS_OBJECT_USE_OBJC is defined, but the developer uses the -fno-objc-arc compiler flag?
@Jeff Kelley: I don’t think it makes sense to write macros to support both ARC and MRR.
The main benefits to ARC is being able to think in terms of an object graph and reducing how much code you write. Supporting MRR in the same compilation unit means more code (more, even, than only supporting MRR) and needing to think in terms of both the object graph and reference counting.
So I would just require ARC with an #if and an #error at the top of the file. The alternative is to support FOUR different combinations of memory management + block memory kinds.
All of that said, I think that OS_OBJECT_USE_OBJC_RETAIN_RELEASE combines OS_OBJECT_USE_OBJC and ARC in a single macro. But I’ve never found documentation on this, so you’d be advised to test this carefully before using it. When confronted with all of this, I just dropped MRR support.
With the wisdom from this post, I was able to update my repo to suport MRC/ARC at the same time. Nevertheless, l’ll perhaps drop MRC support pretty soon.