Cocoa is the Mac development framework, principally consisting of Foundation, the Application Kit (a.k.a. AppKit), and Core Data.
Cocoa Touch is the iPhone development framework, principally consisting of Foundation, UIKit, and Core Data. (“iPhone” here means devices running the iPhone OS, including the iPod touch and iPad.)
On Stack Overflow, please don't tag your question cocoa unless it has to do with Cocoa. It's OK to put an iPhone question there as long as it's about something that exists on both platforms. Tagging an iPhone-specific question “cocoa” is inaccurate, and wastes the time of Mac-only programmers like myself.
(You wouldn't want me to tag my Mac-specific questions “cocoa-touch”, would you?)
(These rules don't apply under garbage collection. If you're using or supporting GC, see the Garbage Collection Programming Guide.)
If you don't own an object, but you want to, then you have two choices:
Ignore the retainCount
method and its Core Foundation equivalent. They are practically useless and frequently misleading. Instead, think about ownerships.
Does object A own object B? If so, then it should have either (a) created object B itself, (b) copied object B from some other object, or (c) retained object B upon receiving it from elsewhere.
If object A does not own object B, then in cases (a) and (b), it should have autoreleased object B immediately after creating it, and case (c) usually should not happen at all.
If object A owns object B, but has not done (a), (b), or (c), then object B is under-retained and may die while object A is holding on to it. When object A goes to use it, you will crash. If object A does not own object B, but does (a), (b), or (c), then object B is over-retained, and, assuming that object A does not release it, object B will become a leak.
The definitive word on this subject is in the Memory Management Programming Guide for Cocoa and the Memory Management Programming Guide for Core Foundation.
Read both of those documents from start to finish.
Maintain the MVC separation at all times. Failure to do so will make development harder, because you will be doing more work. The framework can do a lot for you, but only if your app is properly factored into Model, View, and Controller.
Objective-C is a strict superset of C; unlike C++, there are no changes to existing aspects of C.
C is a thorny language. Concepts such as pointers and the preprocessor are alien to most languages, and to you if you've never used a language that has them before. Since these features exist in C, they exist in Objective-C, and you will use or at least encounter them. So, learn C first, so that your first encounters with them will be ones of deliberate usage and not ones of confusion.
It is not SQLite or any other. More on this later.
If you want a relational database, such as SQLite, you can use SQLite. Both Mac OS X and the iPhone include SQLite, so you can just use that directly (or through a thin wrapper such as FMDB). You'll be giving up all of Core Data's niceties, though, such as support for NSPredicates and (on the Mac) Cocoa Bindings.
If you're coming from another platform, you're used to writing your user interface in code. You may even fear graphical GUI-design tools such as Interface Builder.
Don't.
IB is your friend. It will save you hours of tedious work writing UI code. Embrace it.
If you're new to programming, the debugger will mystify you. Take the time to read the documentation about it, and maybe seek out some screencasts about it. The debugger will tell you about why your app crashed—most times, all you need to do is read what it says.
Don't forget to check the Debugger Console. Often, the framework will dump useful information there.
Instruments will tell you, among other things:
Any time the question “why is XYZ slow?” or “will XYZ be slow?” enters your head, or even a guess that XYZ will be slow, implement XYZ (if you haven't already) and then run Instruments.
Objective-C is a programming language. Cocoa and Cocoa Touch are frameworks—collections of Application Programming Interfaces (APIs). You write your code in the Objective-C language, using the Cocoa/Cocoa Touch APIs. All of the NS-prefixed (and, on the iPhone, UI-prefixed) classes, protocols, and categories you'll use are part of the Cocoa and/or Cocoa Touch frameworks, not the Objective-C language.
In Objective-C:
Classes do not have members, static or otherwise. There are no class variables.
The closest thing is what C calls a static variable, in the class's implementation file. This is not the same thing: A static variable at file scope is only visible within that file, and it is visible to everything in that file.
So, if you were to put multiple classes into that file, all of them would have access to the variable. Conversely, if you were to split the one class into multiple files, only the part that was in the same file as the variable declaration would have access to it. If you were to copy the declaration to all of the files, each file would have its own variable with the same name as all of the others—i.e., you would have multiple variables with the same name.
Thus, “static variables” in C (and, hence, Objective-C) are not the same as “static variables” in certain object-oriented languages that aren't Objective-C. However, in practice, the distinction is minor: When you do need a class variable, a static variable in the implementation file (as long as it's just one file) works as a substitute.
Functions and methods are two different things. Instances and classes have methods. Functions, being a C feature, are not related to any class or instance, regardless of where you declare them.
The IDE is spelled Xcode: Lowercase c, no hyphen.
The object modeling and persistence framework is spelled Core Data: Two words, again with no hyphen. (Not “CoreData” or “Core-Data”). On Stack Overflow, use the core-data tag.
Similarly, Core Foundation, Core Graphics, etc. Apple is not always consistent about this (“CoreGraphics” and “CoreImage” are not uncommon), but outside of pathnames, including the space is never wrong.
On Stack Overflow, tags can't have spaces, so use a hyphen in place of the space: core-foundation, core-data, core-graphics, cocoa-touch. “cocoa touch”, with a space, is two tags, “cocoa” and “touch”.
Core Data is:
Core Data is not:
Just a wrapper of SQLite.
One of the storage formats you can choose is based on SQLite, but that is an implementation detail. You have no direct access to the schema or to the database. You cannot issue SQL queries, regardless of which store you're using.
A relational database.
It is an object database. There are no selects, no updates, no order by or limit clauses; there are only inserts and fetches. You don't work with rows in tables, you work with objects, classed by entity.
Drag these into your browser's bookmarks bar for quick (⌘-number) access:
There are many more of these. Go to the Mac Reference Library and select “Reference” from the list on the left.
There are many more of these. Go to the iPhone Reference Library and select “Reference” from the list on the left.
It bears repeating: Make model objects. Bindings will kick your ass if you use property-list objects (e.g., dictionaries) as model objects. It looks like less work at first, but it's really not—in Cocoa, model objects pay off because you're working with the framework, not against it.
The Bindings Inspector in Interface Builder distinguishes the Controller Key from the Model Key Path for a reason. Consider the common example of binding a table column in a table view:
value
binding to a property of a controller (typically arrangedObjects
of an NSArrayController).Thus, the columns are subordinate to the rows: Each row is a whole model object, broken down into columns, each of which shows part of the object.
In the other direction, if the user edits one of the rows, the cell's value will change, and the table column/table view will set the new object as the model object's new value for the Model Key Path.
This means that it is not possible to use cell editing to replace one object with another in the array, because those objects must be model objects, and the cell can only display and change the value of some property of each object.
There are two solutions to that: (a) Make the model object able to update all of its other properties whenever one of its vital properties is changed (which is fragile, because you will fall behind on the set of properties that need to be updated), or (b) Use a data source, not Bindings.
Bindings is great for certain common cases, but not for everything. There is no shame in using a data source for things that are incompatible with the way Bindings work. Just be sure you aren't doing something deeply wrong, such as not implementing a model layer.
Never call an exception an “error”, nor an exception message (printed in the Console) an “error message”. This is wrong. Exceptions and errors are different things for completely opposite purposes.
Errors are things that have gone wrong that the user needs to know about, and possibly to handle.
Exceptions are the opposite: Things that the user should never know happened. Some exceptions (arguably most) should never happen at all, because they indicate that something has gone wrong inside your program. You may use assertions to detect such cases; when an assertion detects such a case (i.e., fails), the assertion failure is an exception.
In Cocoa, the Application Kit provides APIs to let you present errors to the user. It provides no such features for exceptions, because that's not what they're for.
Whenever your app needs to handle a problem, don't reach for exceptions immediately—think about whether the problem is an exception or an error, and use the one that's appropriate.
On the iPhone, your app normally only has one window, due to both screen size limitations and the current UI model. (It's not yet clear whether this restriction will disappear on the iPad.)
On the Mac, your application has multiple windows. Even if you only create and manage one window, it has others, including the About, Font, Color, Find, and Spelling panels. Even an application that provides no way to access the Font, Color, Find, and Spelling panels (such as a game) will still have an About panel.
So, your application does not have “the window” or “its window”. It has multiple windows. Get used to this; it will matter sooner or later in your app's lifetime.
When practicing with Cocoa, you may want to make a document-based application, at least as a toy app, in order to jump with both feet into the multiple-windows world.
What Cocoa calls “the main window” is the active window: the one that has the active appearance. There's also “the key window”, which is the window that receives key events. These are not always the same window:
Thus, “the main window” (the active one) may not be what you consider the Main (primary) Window: The About panel, for example, can be main (active) while your Main Window is not. A document-based app has no Main (primary) Window, but as long as it has at least one window, it has a main (active) window.
A window can be key even if it cannot become main, as demonstrated by the Inspector panel in the above screenshot.
Don't use threads.
Your UI, specifically, should always run on the main thread. Cocoa and Cocoa Touch will not work any other way; you will cause problems if you try to force the event loop to happen on another thread. In general, you should consider AppKit and UIKit classes to be main-thread-only.
You don't need to make a thread for every window in your app. Indeed, most of the time, you don't need to make a thread for anything.
You can probably do your actual work on the main thread, as long as you do it asynchronously. Many APIs let you schedule an operation on a run loop (which includes the main event loop in a Cocoa or Cocoa Touch application); the API will get back to you when something happens that you may be interested in. You don't even have to write the loop yourself; it's already written as part of the frameworks (specifically, NS/CFRunLoop).
Threads are dangerous (in the “handle with care” sense) on any platform. Cocoa and Cocoa Touch come with many ways to avoid threads, and so avoid the dangers that come with them.
For cases when you really, really do need to put work onto another thread, use NSOperationQueue or (on the Mac only) Grand Central Dispatch. These APIs will create and manage threads for you; your code will run on threads without swamping the system (usually). Moreover, these APIs encourage you to lay out your code in a cleaner way than you might tend to when using threads directly.
See the Concurrency Programming Guide for more information and good advice.