I'm writing an app in an ARC environment, and I'm trying to use a 3rd party library that was written before ARC. I'm using the -fno-objc-arc flags on all the relevant files, so it's compiling, but the project uses #ifndef __OBJC_GC_ blocks to release memory, which is causing memory allocation errors. I'm trying to determine the right solution, and so far I have the following:
1.) find a different library or write my own - this is the only free library of it's kind, so this is obviously not ideal, and I'm new enough that I don't feel comfortable tackling that
2.) remove the #ifndef blocks and cross my fingers - not able to work on the project today, but that's my next plan
3.) refactor the code to be ARC compliant and remove the -fno-objc-arc flags
is #2 likely to work? How hard would #3 be, andwould it actually cause the compiler to define __OBJC_GC_? (there's about 4-5 classes that I'm planning on using, but they're pretty sizeable)
You say the allocation blocks are enclosed into #ifndef __OBJC_GC_.
Note it is #ifndef - "if not defined".
So it should work out of the box if the author maintains the non-GC version correctly.
There is no need for you to remove ifdefs or to forge them.
The compiler, even with ARC on, should not define this flag for iOS.
Just make sure the library itself does not set this flag explicitly..
I would suggest considering another option: Turn off ARC for the project.
Related
I am trying to use a framework which does not use ARC and it seems that I have to turn this feature off before I can use it. My question is, what are the potential ramifications of doing so? If I turn this off, what will I have to do to my current code to make sure I don't have any memory leak or any other issues in general?
ARC works fine with static libraries that use manual reference counting. If you're copying a bunch of .m files into your project, though, that's a different story. Fortunately, it's pretty easy to turn off ARC for specific files; you should do that for the files in that framework and leave your own files using ARC.
I have an iPhone application which is currently in the app store. I want to make what is effectively exactly the same application, but which is free of charge and features ads.
My plan was to effectively just copy the project, create a new one and add ads into the code and release as separate app. However, someone mentioned that the best solution would be to add an additional target to the existing application, providing two binaries at run time.
Seems like a good solution to me, however I am a little confused as to how I would go about altering the code to have ads built into the new target, and leaving the original untouched?
I followed this tutorial which, although old, was basically the same for xcode 4. I duplicated the target and p-list, making sure I was able to run it with changes and not affect the full version target.
I then duplicated the .xib files that would be different. If you look under the project settings, somewhere you can find a list which allows you to choose which resources are included. Include the lite version's xibs in the the lite version, and the full version's in the full respectively. Then you will be able to edit each without affecting the other.
The icons and images can be changed in the same way. Simply create a lite version icon set or other set of images and include the lite icons in the lite target's resource settings instead of the full version's images.
Also, you'll want to create some preprocessor macros. In the build tab look for them, and crete a macro called LITE_VERSION (or whatever you want, it doesn't really matter) for every preprocessing option - debug, distribution and release.
That allows you to add differing code in the same .h and .m files. Simply use
#ifdef LITE_VERSION
// Lite version only code here
#endif
to separate the two. You can also use #ifndef LITE_VERSION to add code only to the full version.
That's it! After all of the above steps, you should be able to edit the lite version's .xib files, put code into the lite or full version only, and have separate images and icons for each.
XenElement's answer is correct. But you should see the best practice to do it. You should have an identifier class to check for targets. If you use macros everywhere in the code, it won't seem good for you and other developers as well. In this little blog post you can see how to create that kind of an identifier class and learn some best practices about targets in xcode.
I followed this Just2us: How to create multiple targets for Xcode iPhone Projects tutorial.
I decided change step-3 with Stu's clue, setting FULL_VERSION explicitly in the paid version.
"To address the concern of not having accidentally LITE_VERSION defined as a macro preprocessor (thus releasing a full version accidentally), I put this little snippet of code in a header file (it just needs to be somewhere in the code base , just make sure that is common to all configurations)":
#ifndef LITE_VERSION
#ifndef FULL_VERSION
#error You probably forgot to specify if this is the Lite or Full version of the app
#endif
#endif
PS: I wrote the code above right after the #import in AppDelegate.
When I'm using big frameworks like the Three20 Framework,
I always have the choice whether to #import the whole framework or to #import only the single file of it i'd need.
I guess there's a difference in compilation-overhead since it has to open all files of the framework, but is there also a run-time difference? like bigger memory-usage? Or does the compiler-optimization already remove everything that's not needed?
And if I use the same framework pretty much in every class I use, is it recommended to include the framework in the prefix file instead of every single class?
Greetings
Infinite :)
There will be a compilation difference, yes: including everything will take longer to compile. But there shouldn't be a run-time difference.
Your idea of including the framework in the prefix is a good one for frameworks you're going to be using throughout. However, there is a catch, which is that if you change something in that framework your entire codebase will have to be recompiled.
There is no performance hit in runtime. No matter how many frameworks or files you import, if you don't use whichever classes they won't affect the resultant bytecode when you compile. The compiler doesn't even optimize anything; unused classes just "aren't there" at all.
Include the framework in the precompiled header file if you're sure it's going to be necessary.
You footprint won't be any different unless you actually use the classes however I prefer to be more frugal with my headers, only including the ones I need. If I need a lot from the same library (like Three20) then you can add the whole reference.
Only include headers in the prefix that don't change much, but it will speed up compilation greatly.
TL;DR Version:
This question has arisen due to the fact that I have multiple frameworks (which I have built) and a client project that uses said frameworks. Now, when I open up the client project and try to debug into the framework, it doesn't work.
However, if I have the project associated with the framework open, then debugging appears to work (though there are some weird issues with breakpoints I don't see being triggered).
I have looked at Apple's docs, and perhaps the answer is buried there somewhere, but I couldn't find it on a skim of the Xcode Debugging Guide.
Long Version:
The reason this question is important to me is that a coworker and I had a disagreement about how headers are imported in the frameworks we build.
I have a tendency to use framework headers (with client apps) in the fashion:
#import "FrameworkA/HeaderA.h"
#import "FrameworkB/HeaderB.h"
He, on the other hand, favors importing the framework headers (with client apps) like this:
#import "HeaderA.h"
#import "HeaderB.h"
and specifying the header search paths in the build target of the client application.
Complicating matters further is the fact that some of these frameworks have interdependencies. For example, FrameworkB has headers from FrameworkA referenced in his format:
#import "HeaderA.h"
His argument for doing this is that debugging only works if we import headers this way. It seems dubious to me that there would be a relation between header importing style and debugging, but I am not really certain how XCode chooses the file to link to during debugging, hence the question.
Thanks in advance for any assistance with this query.
you add project references to the target, and make sure Xcode knows where to find the debug symbols.
#import <FrameworkA/HeaderA.h>
that's the way to go (for internal and external declarations). the reason? the other approach is more likely to cause issues as libraries evolve. the additional qualification disambiguates any case (unless of course there are two FrameworkA/s in your search path), it's best to qualify the file explicitly now, rather than when your clients tell you they cannot use your library with other libraries, or that they can only use them in some conditions. then you have to go fix the issues and reship (this stuff has a way of happening at inconvenient times =p). it's one simple measure to ensure you've developed a robust interface.
perhaps the most important part that people overlook is the location of the products: use a customized central build location for your targets -- many people use the default location, which is by the xcodeproject. otherwise, Xcode may not be able to locate debug information.
finally, debugging complex projects in Xcode can be quite... let's call it 'problematic'. So don't expect the debugging experience to be perfect, even if you've configured everything correctly. all the more reason to integrate assertions and unit tests into your development cycle early on with Xcode. truth is, the debugger may be useless no matter how hard you try - this is not a new issue. hopefully LLDB will improve our debugging experiences.
good luck
Within several projects, I am using 3rd party code that produce more than a few compiler warnings. I obviously do not want to go through and modify code of actively updated 3rd party projects.
This leaves me with a lot of unnecessary warnings that drown out warnings in MY code.
I have used some compiler flags to suppress specific warnings on a per file basis, but that is much too tedious for open source code with 10-20 .m files.
Is there a way all warnings by Xcode group or file path? Or does somebody have a better suggestion?
(FYI: I am using the LLVM 1.5 compiler)
In my experience, XCode 3.x seems to only show the warnings for files that have actually been compiled in the most recent build, so if you build the project, modify a single file and then build the project again, you'll only see the warnings for the modified file. I generally find this to do more harm than good (especially since in Objective-C it's only a warning to call a selector that doesn't exist!) — and thankfully it's fixed in XCode 4 — but in your case in might be useful.
However, for various reasons you might want to consider putting the third-party code into a Framework. This wouldn't automatically suppress the warnings (although it might make it easier to suppress them) but it would mean that the third-party code was compiled into a library and therefore wasn't part of your normal compile cycle.
Turning off warnings on a per file basis is super simple. All that is required is a compiler flag. Here’s the step by step process.
Open the Project Navigator in Xcode
Click on the Project icon at the very top of the navigator
In the resulting detail pane select the target that you are working
with
Select “Build Phases”
Expand “Compile Sources”
In the list locate the file that you’re interested in
Double click the column under the “Compiler Flags” column next to
your file
Add a -w to the resulting dialog
Click “Done”
Build your now warnings free project
here is the reference link
http://blog.bluelightninglabs.com/2011/12/suppressing-xcode-warnings-on-a-per-file-basis/
This is certainly not the easier solution, but you could go through these third-party libraries and fix their warning-causing bugs and submit patches. Then, the warnings go away, the bugs are fixed, and everybody gets to enjoy both improvements.
(How many warnings you'll be able to squash this way will depend on what they are: Deprecated-API warnings may be unavoidable if the library needs to support an older version of Mac OS X or iOS where the now-deprecated APIs were the only way.)