I have managed to avoid C and C++ up until now (except for a few HelloWorlds), and have instead worked in higher-level languages. I've worked and lived in VB6, then Java, then C#, then ActionScript, and now Ruby.
I've recently become curious about programming for the IPod Touch/IPhone. Though I've seen some possibilities for avoiding ObjectiveC (like Mono for IPhone), I'm curious about Objective C. Mostly: does it require the developer to handle garbage collection and manage pointers and that sort of thing?
Edit: I am totally open to the possibility that my concept of higher- and lower-level languages is incorrect or misleading.
Garbage collection: yes, but not nearly as bad as C or C++. Once you understand Objective-C garbage collection it's really easy. It doesn't take that long to learn or master either.
As far as pointers go - you'll be using pointers far less frequently than you would in C or C++. Yes, a bit of knowledge about pointers is useful (knowing the difference between declaring NSString * and NSString) but that's also not that complicated.
Personally I would avoid all the "higher-level" languages that are emerging for iPhone development. They really only eliminate the need for you to learn Objective-C but still force you to use the native framework (Cocoa Touch). They add complexity for laziness sake. Objective-C can be learnt in a week, debugging framework nuances takes a lot longer. But then again, it is only my opinion.
edit:
C# memory management can also be a pain if not done correctly. Yes, there's a garbage collector that works in a lot of cases. However, there are also objects that need to be disposed and not disposing them correctly can lead to memory leaks. Creating your own IDisposable objects can also be tricky if you're not 100% sure what the order of the Disposing sequence is. I've seen a lot of projects where developers get this horribly wrong. Basically what I'm saying is that the Objective-C memory management is not more complex or more technically difficult than the Dispose chain in C#/.NET
There is garbage collection for Objective-C but not for the iPhone, i. e. if you write software for the iPhone you have to handle the memory stuff on your own, but this is no general Objective-C problem.
"Mostly: does it require the developer to handle garbage collection and manage pointers and that sort of thing?" - on the iPhone, yes.
It's not as "high-level" as C# and Java, IMO, but it's still considered a high-level language, just like C++ and, yes, C.
Objective C does have garbage collection, but the iPhone Object C does not.
Related
I've been introduced to an Objective-C codebase which has ~50,000 LoC and I'd estimate that 25% or so is duplicate code. Unfortunately, OO principles have been mostly ignored up to this point in the codebase in favor of copy and pasting logic. Yay!
I'm coming from a Java background and a lot of this duplication is fixable with good old-fashioned objective oriented programming. Extracting shared logic into a base class feels like the correct solution in a lot of cases.
However, before I embark on creating a bunch of base classes and sharing common logic between derived classes, I thought I should stop and see if there are any other options available to me. After watching Ken Kocienda's 'Writing Easy-To-Change Code' WWDC session from 2011, he's advising me to keep object hierarchies as shallow as possible. He doesn't offer up any hard statistics as to why he has this opinion, so I'm wondering whether I'm missing out on something.
I'm not an Objective-C expert by any stretch of the imagination, so I'm wondering if there's any best practices when deciding on an object hierarchy. Basically, I'd like to get opinions on when you decide to stop creating base classes and start using composition instead of inheritance as a way of sharing code between classes.
Also, from a runtime performance standpoint, is there anything to sway me away from creating object hierarchies?
I wrote up some thoughts awhile back on coming to iOS from other backgrounds, including Java. Some things have changed due to ARC. In particular, memory management is no longer so front-and-center. That said, all the things you used to do to make memory management easy (use accessors, use accessors, use accessors) is still equally valid in ARC.
#Radu is completely correct that you should often keep your class hierarchies fairly simple and shallow (as you read). Composition is often a much better approach in Cocoa than extensive subclassing (this is likely true in Java, too, but it's common practice in ObjC). ObjC also has no concept of an abstract method or class, which makes certain kinds of subclassing a little awkward. Rather than extracting shared logic into base classes (particularly abstract base classes), it is often better to extract them into a separate strategy object.
Look at UITableView and its use of delegates and datasources. Look at things like NSAttributedString which HAS-A NSString rather than IS-A. That's common and often keeps things cleaner. As with all large object hierarchies, keep LSP in mind at all times. I see a lot of ObjC design go sideways when someone forgets that a square is not a rectangle. Again, this is true of all languages, but it's worth remembering as you design.
Immutable (value) objects are a real win whenever you can use them.
The other piece you will quickly discover is that there are very few "safety decorations" like "final" or "protected" (there is a #protected, but it isn't actually that useful in practice and is seldom used). People from a Java and C++ background tend to fret about compiler enforcement of various access rules. ObjC doesn't have compiler enforcement of most protections (you can always send any message you want to any object at runtime). You just use consistent naming conventions and don't go poking around at private methods. Programmer discipline takes the place of compiler enforcement. In practice, it works just fine that way in the vast majority of cases.
That said, ObjC has a lot of warnings, and you absolutely must eliminate all warnings. Most ObjC warnings are actually errors.
I've strayed a little from the specific question of object hierarchies, but hopefully it's useful.
One major problem with deep hierarchies in Objective-C is that Xcode doesn't help you at all understanding/managing them. Another is simply that just about anything in Objective-C gets about twice as complex than the equivalent in Java, so you need to work harder to keep stuff simple.
But I find composition in Objective-C to be awkward (though I can't say exactly why), so there is no "perfect" answer.
I have observed that small subroutines are much rarer in Objective-C vs Java, and one is much more likely to see code duplicated between mostly-identical view controllers and the like. I think a big part of this is simply the development tools and the relative awkwardness with creating new classes.
PS: I had to rework an app that contained roughly 55K lines, close as we could count. As you found, there was likely about 25% duplication, but there was also another 25% or so of totally dead code. (Thankfully, that app has been pretty much abandoned since.)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I've yet to use ARC, since the majority of the code in the project I'm working on at the moment was written pre-iOS 5.0.
I was just wondering, does the convenience of not retaining/releasing manually (and presumably more reliable code that comes as a result?) outweigh any 'cost' of using ARC?
What are your experiences of ARC, and would you recommend it?
So:
How much benefit can ARC bring to a project?
Does ARC have a cost like garbage collection in Java?
Have you been using ARC and if so, how have you found it so far?
There is no downside. Use it. Do it today. It is faster than your old code. It is safer than your old code. It is easier than your old code. It is not garbage collection. It has no GC runtime overhead. The compiler inserts retains and releases in all the places you should have anyway. But it's smarter than you and can optimize out the ones that aren't actually needed (just like it can unroll loops, eliminate temporary variables, inline functions, etc.)
OK, now I will tell you about the small downsides:
If you're a long-time ObjC developer, you will twitch for about a week when you see ARC code. You will very quickly get over this.
There are some (very) small complications in bridging to Core Foundation code. There are slightly more complications in dealing with anything that treats an id as a void*. Things like C-arrays of id can take a little more thinking about to do correctly. Fancy handling of ObjC va_args can also cause trouble. Most things involving math on an ObjC pointer is trickier. You shouldn't have much of this in any case.
You cannot put an id in a struct. This is fairly rare, but sometimes it's used to pack data.
If you did not follow correct KVC naming, and you intermix ARC and non-ARC code, you will have memory problems. ARC uses KVC naming to make decisions about memory management. If it's all ARC code, then it doesn't matter because it will do it the same "wrong" on both sides. But if it's mixed ARC/non-ARC then there's a mismatch.
ARC will leak memory during ObjC exception throws. An ObjC exception should be very close in time to the termination of your program. If you're catching a significant number of ObjC exceptions, you're using them incorrectly. This is fixable using -fobjc-arc-exceptions, but it incurs the penalties discussed below:
ARC will not leak memory during ObjC or C++ exception throws in ObjC++ code, but this is at the cost of both time and space performance. This is yet another in a long list of reasons to minimize your use of ObjC++.
ARC will not work at all on iPhoneOS 3 or Mac OS X 10.5 or earlier. (This precludes me from using ARC in many projects.)
__weak pointers do not work correctly on iOS 4 or Mac OS X 10.6, which is a shame, but fairly easy to work around. __weak pointers are great, but they're not the #1 selling point of ARC.
For 95%+ of code out there, ARC is brilliant and there is no reason at all to avoid it (provided you can handle the OS version restrictions). For non-ARC code, you can pass -fno-objc-arc on a file-by-file basis. Xcode unfortunately makes this much harder than it should be to do in practice. You should probably move non-ARC code into a separate xcodeproj to simplify this.
In conclusion, switch to ARC as soon as you can and never look back.
EDIT
I've seen a couple of comments along the lines of "using ARC is no substitute for knowing the Cocoa memory management rules." This is mostly true, but it's important to understand why and why not. First, if all of your code uses ARC, and you violate the Three Magic Words all over the place, you'll still have no problems. Shocking to say, but there you go. ARC might retain some things that you didn't mean it to retain, but it'll release them as well, so it'll never matter. If I were teaching a new class in Cocoa today, I'd probably spend no more than five minutes on the actual memory management rules, and I'd probably only mention the memory management naming rules while discussing KVC naming. With ARC, I believe you could actually become a decent beginning programmer without learning the memory management rules at all.
But you couldn't become a decent intermediate programmer. You need to know the rules in order to bridge correctly with Core Foundation, and every intermediate programmer needs to deal with CF at some point. And you need to know the rules for mixed-ARC/MRC code. And you need to know the rules when you start messing around with void* pointers to id (which you continue to need to perform KVO correctly). And blocks... well, block memory management is just weird.
So my point is that the underlying memory management is still important, but where I used to spend significant time stating and restating the rules for new programmers, with ARC it is becoming a more advanced topic. I'd rather get new developers thinking in terms of object graphs rather than fill their heads with the underlying calls to objc_retain().
Better, more technical answers than mine will come, but here goes:
ARC != garbage collection. There is no run time penalty, it is done at compile time.
ARC also != just auto releasing everything, as you suggest in your comment. Read the docs
It's awesome once you realise how much manual reference management you were doing
Use it!
One drawback - maintaining old, non-arc code suddenly becomes very tedious.
How much benefit can ARC bring to a project?
The benefit is a significant degree of protection from common memory management mistakes. Leaks caused by failing to release an object and crashes due to failing to retain or prematurely releasing an object should be significantly decreased. You still need to understand the reference counted memory model so that you can classify your references as strong or weak, avoid retain cycles, and so on.
How much does garbage collection really 'cost'?
There is no garbage collection in iOS. ARC is similar to GC in that you don't have to manually retain or release objects. It's unlike GC in that there's no garbage collector. The retain/release model still applies, it's just that the compiler inserts the appropriate memory management calls into your code for you at compile time.
Have you been using ARC and if so, how have you found it so far?
It's a little disconcerting if you're used to reference counting, but that's just a matter of getting used to it and learning to trust that the compiler really will do the right thing. It feels like a continuation of the change to properties that came with Objective-C 2.0, which was another big step toward simplifying memory management. Without the manual memory management calls, your code becomes a little shorter and easier to read.
The only issue with ARC is that it's not supported in older versions of iOS, so you need to take that into account before you decide to adopt it.
I think ARC is a great idea. Compared to GC, you can have your cake and eat it too. I tend to believe that MRC imposes an invaluable 'discipline' towards memory management that everyone would benefit from having.
But I also agree that the real issue to be aware of is Object Ownership and Object Graphs (as many have pointed out), and not low-level reference counts per se.
To conclude: ARC is NOT a free pass to be mindless about memory; it is a tool to help humans avoid repetitive tasks, that cause stress and are prone to error, therefore better delegated to a machine (the compiler, in this case).
That said, I'm personally kind of a craftsman and haven't made the transition yet. I just started using Git...
UPDATE: So I migrated my whole game, gl library included, and no problems so far (except with the migration assistant in Xcode 4.2). If you are starting a new project, go for it.
I've used it in a couple of (admittedly small) projects, and I have only good experiences, both performance- and reliability wise.
One minor note of caution is that you need to learn the do:s and don't:s of weak references not to cause any reference loops if you're coding your UI by yourself, the designer tends to do a good job of it automatically if you set up your GUI using it.
The only downside I have encountered is if you use a library with a lot of CoreFoundation functions and data. In MRC you didn't need to worry about using a CFStringRef instead of an NSString*. In ARC, you have to specify how the two interact (basic bridge? release the CoreFoundation object and move it to ARC? Make a Cocoa object as a +1 CoreFoundation retained object?) Also, on OS X, it's only available on 64-bit code (Although I do have a header that works around that…).
I have spent a lot of time getting into iOS development. I have spent a lot of time familiarizing myself with objective-c as well as xcode. I have spent a lot of time going through the motions without understanding the fundamentals of what Cocoa is.
I haven't grown up my entire life understanding coding concepts as some people have, and when people tell me that Cocoa is a framework, that doesn't really mean very much to me.
Can somebody undertake to explain IN SIMPLE ENGLISH what Cocoa is? What a framework is? How I as an aspiring developer should use it? What it should mean to me? I have spent so much time trying to understand it from definitions that don't make sense, that I wanted to try this and see if something could just click.
Thanks for your time
Think of a framework like a library. So let's talk in terms of books. A library is full of books! In this case, our books are our classes. Now books have pages that tell the story, and classes do too, they're called methods and properties.
So based on the above, we can tell that libraries contain classes which help us do things. A framework is just a packaged library really.
When you write things like:
NSObject* foo = [[NSObject alloc] init];
and later call:
[foo release];
what you're doing is using parts of Cocoa—specifically, memory management. +alloc is a class method which creates an object, and -init is an instance method (+ refers to class methods, - refers to instance methods—that's how they get defined in Objective-C code). Likewise, -release is used to release your ownership of the object you created previous.
These three methods are part of Cocoa. In the NSObject book.
I hope this is simple enough for you to understand.
In addition to containing library routines, a framework usually forces your application into a certain paradigm, such as requiring your app to be structured in a certain way, and/or requiring a lot of defined subroutines/methods in your app that the framework can call. In fact, a framework such a Cocoa Touch can often call your app far more than your app might call any library code in the framework.
One good way of learning a framework is to read the source code of many example apps, and try to separate out the application logic from the framework glue.
First I went and purchased:
Beginning iPhone Development: Exploring the iPhone SDK
And it said I should know Objective-C
Then I went and purchased Learn Objective–C on the Mac by Mark Dalrymple, Scott Knaster
And it said I should know C
then now I'm at the beginning with Learn C on the Mac by Dave Mark
So this is the long journey I need to take to finally start producing actually GOOD apps for the iPhone
C > OBJECTIVE-C > APPS?
Nah, forget learning C, just go straight to Objective-C. My humble opinion.
If the Learn Objective C book assumes you know C then is it likely to not go into the code in as much detail as you need, making it more difficult for you. However you don't need to learn all of C, or even a lot, so working through a book will take some time.
Better, as silky says, jump straight into Objective-C, and when you struggle just come to SO
If you're a complete beginning to computer programming, I might get some information about programming in general before going to Objective-C; it's an easy language, but it would help to general programming constructs (like if statements, etc) and how they work before you learn how Objective-C does it.
I would think that you WOULD want to learn C first. Most objective-c books are going to presume that you know the difference between pointers and values, that you know basic looping and control statements, and that you understand arrays, structs, and functions.
Contrary to some other advice, unless an objective-c book you buy specifically starts from zero and makes that claim, I WOULDN'T just jump in. People will say that objective-c is easy, but that's not necessarily true, since with compiled languages (unlike interpreted ones where speed doesn't matter so the runtime can hide complexity via abstraction) the devil is in the details.
If you read an objective C book and you don't know what the "*" is for in front of a variable, start with C. My two cents.
I've seen several approaches, and each seem to have significant plusses and minuses. I'm learning iPhone development, I'm building a relatively simple app, which, at it's core, is really not much more than CRUD operations on 3 or four related entities.
I'm used to ActiveRecord-type object persistence. The implementations for Cocoa Touch that I read about online are commonly referred to as extremely slow.
Most of the examples I see online (specifically the Pragmatic Programmers screencasts) have SQL hardcoded into the controller class, which doesn't seem... right to me. Seems very old school (but maybe old school is best in this case).
I know we can't discuss SDK 3.0 here, but it's common knowledge that CoreData is coming for the iPhone, that would of course limit my audience (I'm not sure I really care about that this much. It will be an app for sale, but I'm not planning on it replacing my career)
I have not tried Gus Mueller's FMDB yet, but I have read good things.
What are some of your experiences, what works, and what doesn't. Where would you recommend that a (still pretty novice) iPhone programmer invest their time?
Right now there's a lot of semi-raw SQL encoded in apps because there's no built-in system for higher level work. FMDB is a nice way to do this but it just wraps the SQLite calls into something more Objective-C like. It's great for some situations but obviously not for everything.
If you're familiar with ActiveRecord then SQLite Persistent Objects may be useful to you, because it's intended to be similar to ActiveRecord. I haven't used either so I couldn't tell you how similar it actually is. If that doesn't seem right for some reason, it's probably best at this point to target 3.0 and make use of Core Data.