I'm just wondering if #synthesize should still be used even though Xcode does it automatically for properties, simply because it's been done that way for so long? Or does this mean we can all stop using #synthesize (unless you have a reason to give its instance variable a different name)?
I just want to make sure that from a professional standpoint I'm conforming to good coding practice.
I personally no longer use synthesize for new development only unless required (see lnafziger's comment below). The reason is because I currently develop for iOS 6, which requires a new version of Xcode, which has the capabilities of auto-including the #synthesize during compile time. If I were to do this with old code, there may still be someone in my organization that is using an old version of Xcode (i.e version 4.2) where this would cause problems for them.
So depending on if you still need to be compatible with the older versions of Xcode, this answer will vary. But if you only need to work with new versions of Xcode, you should be fine not declaring #synthesize.
To directly answer your question, I think, skipping #synthesize is not unprofessional. Assuming you don't requiring it for some reason (and I'll talk about that), I think it's more professional to write less and cleaner code. #synthesize is just noise.
There's a few cases where you might consider it:
You need compatibility with the old (32 bit OS X) runtime, or an older version of iOS (pre 4.0).
Note: Though you might care about 32 bit OS X, I'm not even sure Apple would even accept an app that targets iOS prior to 4.0 now. Certainly, you're going to be really limit yourself.
Your product is a source library you want other developers to be able to use with older versions of Xcode.
You need to use an older version of Xcode (pre 4.4).
You've hit an edge case in the language where #synthesize is required. (There's at least one case of this, related to categories.) If you hit this, #synthesize that one variable and move on. Don't go back and #synthesize everything.
Note that if you turn on -Weverything you'll get compiler warnings about this. -Weverything includes everything, including some warnings that suggest changes I'd consider ill-advised. This is one of them. Find the appropriate warning switch to turn it back off (it's in the warning message) and do so. :)
See also:
Objective-C Feature Availability Index
If you are ok with your ivar being synthesized with _propertyName you can safely get rid of the synthesize statements. If you want your ivar to be named something else, you need to include it like so
#synthesize propertyName = ________cool_ivar_name
There really is no overall correct answer for this. Other than the specified technical reasons given by the other answers (such as tying an alternate ivar name to a property), I feel it is most important to keep consistent with your code. If you are contributing with older libraries that use #synthesize all over the place, you might want to stick with it in the name of consistency. Otherwise, if you are starting anew and shooting for the less verbose approach, stick with omitting #synthesize as much as possible. I personally like less verbose code, but I value code consistency somewhat more, especially when weeding through thousands of lines of code.
Related
Let me start by saying I am not sure if this belongs here or at Super User. I started here.
Now, I am a very tidy person, and I like collapsing methods so that I can get around very easily. However, one thing that aggravates me is that all my #synthesize commands are always there. I can see no way to collapse them. (I have over 50 properties to synthesize) Is there a way I can hide these commands, while not messing up my build.
Thanks.
Unfortunately, from "available features" perspective, XCode is a very old IDE. Therefore no foldable code regions - see detailed discussion Xcode regions
Also note that with the latest compiler (LLVM 4.0), declaring #synthesize is optional. You can enable/disable it in compiler settings in your project settings.
However, if you are using GCC or an older LLVM version (for whatever reasons), this is not possible.
Edit:
After rereading your question... having 50 properties in one class smells very bad. Consider splitting your class into several smaller classes.
You can also put the #synthesize commands to the end of the #implementation file.
Since Xcode 4.4 you don't need to #synthesize properties if you don't want another name for it — it uses auto synthesise.
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
According to Apple's ARC Documentation, there are a fairly significant number of changes to the way that one develops software when using ARC.
As a complete beginner to Objective-C, would it be better to start off with ARC disabled, with the idea that it would give me a better low-level understanding of what is going on behind the scenes? Or has ARC essentially deprecated the 'old way' of doing things, to the point that it's not really worth spending time learning?
This is basically an opinion question, and is therefore fairly dangerous.
My Opinion is a qualified yes. It is worth learning basic memory management. The qualification being don't get bogged down in it. Learn what ARC is doing for you under the hood with some very simple projects. Once you have a basic understanding of how to handle memory management, i.e. how to avoid retain cycles(as jemmons alluded to they can still be a problem with ARC).
Once you have a basic grasp of memory management. Start using ARC.
Also as Jason Coco pointed out ARC handles memory management for (to put it simply) NSObject subclasses. So all of the CF Objects you will still be handling yourself, if you need to use them.
An excellent explanation about what ARC is doing for you under the hood can be found in the WWDC2011 Session 323 - Introducing Automatic Reference Counting.
But there are some other considerations that might steer your decision.
What devices do you need to target?
If you plan to target iOS 4.3 and up ARC effectively handles memory management for you.(of NSObject subclasses)
If you plan to target iOS 4.2 then you will not be able to use weak references(you will use unsafe_unretained). iPhone 3g? & iPod touch 2nd gen are stuck at this OS level, because there are many of these devices still in service many developers are still targeting them.
If you plan to target iOSs earlier than 4.2(This would be rare) you will definitely need to learn MRC(Manual Reference Counting).
If you plan to build Mac Apps, there is a garbage collector available on that platform. ARC is also an option(full ARC 10.7, no weak support 10.6).
It's worth noting that ARC is checked by default when you start a new project in Xcode. This is as good a sign as any that the old retain/release way of doing things is deprecated and Apple sees ARC as the future. Your first lesson as a new ObjC developer might be that it never pays to swim up-stream against Apple.
Also, while it's fairly easy to convert old retain/release samples to ARC (for the most part, just drop any retains, releases, and autoreleases), the inverse is not true. And I've already seen a lot of sample code cropping up that's written ARC-style. So as someone just starting out, it'd pay more to learn the ARC way.
Note this doesn't mean you don't have to understand reference counting. It's still an important part of an object's life cycle and you still need to be aware of such things (if only to know when to use weak or strong references). But when it comes time to write code, write it with ARC on.
The "old" style is simply just reference counting to manage your object's lifetime. There's not really all that much too it, but it can be error-prone and cause all kinds of grief. If you're just starting, I'd personally suggest you just learn to program using ARC. You'll still get to deal with reference counting when you need to use the C-library objects, like CoreFoundation or CoreGraphics.
Apple itself recommends ARC for new projects.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html#//apple_ref/doc/uid/10000011i
read point 2 in At a Glance
There is sooo much more interesting to learn in Objective C & iOS apart from the memory management.
My advice : Don't bother about MRR
It would be a great idea just to go over it and understand what's going on, but for development it's not essential, and as you can see most if not all developers have moved their deployment targets to iOS 5.0+, so you are likely not to develop under manual reference counting.
However if you plan to use non ROP -retainable object pointers- in your code like CFStringRef, you might want to really look at non ARC so you can understand things like bridge, because you can combine ARC and non ARC code in one project.
I've just started learning Obj-C and i'm a little confused. The videos I've been watching on Lynda.com were created with Xcode 4, but there are so many differences that I find it hard to believe that all of them occurred in 2 point releases. For instance:
In the video you could write:
#property NSString * myString
And it would be fine, but now in 4.2 it throws an error unless you write something like:
#property (nonatomic, retain) NSString * myString
In addition, there are no longer init or dealloc methods in the implementation code by default and NSAutoReleasePool is implemented completely differently. What gives?
While I can't guarantee that this list is exhaustive, the differences you'll find on the net are:
Objective-C 1.0 or 2.0
Old or modern runtime
Manual or automatic reference counting
My personal take on the main differences is:
Objective-C 2.0 brought properties and synthesized accessors among other things
The modern runtime has a different way of organizing instance variables (non-fragile instance variables), but you probably won't notice in day-to-day development work
The modern runtime also allows 64-bit apps if the OS supports it
Automatic reference counting lets you do away with retain/release code at the modest cost of following the coding and naming conventions
There are more differences, but these are the most important ones as I see it - personally I rarely have to use autorelease pools, and if I understand correctly the new syntax does not change the functionality.
If you create a project with "automatic reference counting" option "on" then there wouldn't be any init or dealoc methods.
When creating project
CHECK the Use Automatic Reference Counting.
When creating a project you can check the option "Use Automatic Reference Counting". If you do check this, then there won't be any init or dealloc methods, because Xcode automatically does the reference counting.
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.