It only takes a minute to sign up. See e. I think the limit should be lowered. Some data from the last dump - out of , question titles the counts for certain minimum title lengths are shown maximum length is :. Even those that are error-messages could easily be shortened by stripping out useless parts, the rest are just prose instead of titles. All those question are either.
I didn't really look yet below , but a rough scan leads me to believe that quality drops greatly when question lengths exceed about I'd need to analyze existing question title length to get a sense of what the maximum length should be. Suggestion of "one line". This of course varies per font and characters used, but for this post it is:. The new question title length limit has been reduced from characters to characters. Extremely short titles can be considerably more difficult to flesh out however. And you will end with more "generic" titles.
No need to limit what the community can moderate by itself, in a way. The existing mechanism of allowing long titles but encouraging people to use shorter titles is probably the best solution. A technological solution, in the form of a shorter hard limit, will just produce more stupidity than it prevents.
Sign up to join this community. The best answers are voted up and rise to the top. Home Questions Tags Users Unanswered. Length limit for question titles that have nothing to do with Unicorns we don't really need that many characters just for the title, do we? Isn't that what the question body is for? Some lower length limit would help here. Ask Question. Asked 9 years, 5 months ago. Active 9 years, 4 months ago. Viewed times. This error can be caused by a virtual directory not being configured as an application X ' in attribute 'TargetProperty' to object of type 'System.
Property path is not valid. To run or subscribe to this report, you must provide a parameter value. Common causes for this error are when the response is modified by calls to Response. Write , response filters, HttpModules, or server trace is enabled. I don't want just a generic "execute" function where I pass in strings for the function name and parameters C error1:The name 'DateTimeStyles' does not exist in the current context Failed to grant permission to execute. The fully qualified file name must be less than characters, and the directory name must be less than characters.
All those question are either the aforementioned prose containing unneccessary parts like paths on the users machine just informative notes in error messages. Georg Fritzsche Georg Fritzsche 2, 18 18 silver badges 30 30 bronze badges. You don't see any additional value in long titles, but you haven't made the case that a limit should be applied.
Please explain how SO will be improved significantly by limiting this field. Note that currently the editors do a great job with too-long titles. Also note that they don't seem to hurt anyone or anything. Limiting them won't magically improve the questions. Pollyanna: Ah, i thought it would be obvious.
At least for me it greatly messes up readability in question listings, which for me leads to them always having to be edited to some reasonable length TM. Jeff Atwood Jeff Atwood k gold badges silver badges bronze badges. IMHO if it goes onto more than one line it is too long. The NSApplication object takes events from the event queue and forwards them to the appropriate window. Create a Class In Objective-C, every class is defined by two files: a header file and an implementation file.
The header file, also known as the interface file, declares the instance variables and methods your class will have. The implementation file defines what those methods do. Instance variables that are pointers to other objects are called outlets. Methods that can be triggered by user interface objects are called actions. Edit RandomController.
- American Woodworking Tools.
- Melvil Decimal System: 005.2.
- Encounters with John Bowlby: Tales of Attachment.
RandomController is a subclass of NSObject. RandomController has two methods: seed: and generate: are action methods. By convention, the names of methods and instance variables start with lowercase letters. If the name would be multiple words in English, each new word after the first one is capitalized—for example, favoriteColor. Also by convention, class names start with capital letters—for example, RandomController. Save RandomController. Select MainMenu. Drag an Object onto the Interface Builder dock. Your actions and outlets should appear in the Connections Inspector. If they do not, check RandomController.
Setting the Class Make Connections A lot of object-oriented programming has to do with which objects need to know about which other objects. Now you are going to introduce some objects to each other. The object diagram in Figure 2. Right-click or Control-click if you have a one-button mouse on the icon that represents your instance of RandomController.
The Connection panel will then appear. Drag from the circle beside textField to the text field that says Label Figure 2. Set the textField Outlet This step is all about pointers: You have to just set the pointer textField in your RandomController object to point to the text field.
Control-drag from the button to your instance of RandomController. When the panel appears, select seed: Figure 2. Control-drag from the button to RandomController. Choose generate: in the Received Actions panel Figure 2. The syntax may be different, but the underlying concepts are the same.
For example, a class in Java would be declared like this: import com. Bar; import com. Note that like Java, Objective-C allows only single inheritance; that is, a class has only one superclass. Types and Constants in Objective-C Objective-C programmers use a few types that are not found in the rest of the C world. Ignore it. IBOutlet is a hint to Interface Builder when it reads the declaration of a class from a. It also acts as a hint to Interface Builder. We use nil instead of NULL for pointers to objects. Study it for a moment.
Instance variables are declared inside the braces. However, import ensures that the file is included only Foundation. You are importing Note that the declaration of the class starts with interface. The symbol is not used in the C programming language. Here are a few other Objective-C keywords: end, implementation, class, selector, protocol, property, and synthesize. It contains the implementations of the methods. You can also enable the Assistant Editor in the toolbar, which automatically shows the counterpart for the selected file beside it.
The method increments the count instance variable and then sends the message setIntValue to the textField object with count as an argument. It has no visibility specifiers: All methods are public, and all instance variables are protected. In fact, there are visibility specifiers for instance variables, but they are rarely used. The default is protected, and that works nicely. In Chapter 3, we will explore Objective-C in all its beauty. For now, just copy the following methods.
You can safely remove the init and dealloc methods Xcode has created for you. Neither method returns anything. Because Objective-C is C with a few extensions, you can call functions, such as random and srandom from the standard C and Unix libraries. Build and Run Your application is now finished. Click Run in the toolbar to run your application again. Select the Issue navigator to see a list of build issues.
If you click on an issue, the erroneous line of code will be highlighted in the editor.
- Cocoa Programming for Mac OS X - PDF Free Download.
- Parents Guide to the Internet.
- PDF Cocoa Programming for Mac OS X 2nd Edition EBook!
- Works under MDS 005.26.
- Psychology of Perception?
- The Planes They Flew in World War I.
- R for Mac OS X FAQ;
- Heavens to Louie.
- 1st Edition.
- Frequently Asked Questions on R for Mac OS X.
- Cocoa Programming for Mac OS X的更多书评!
In Figure 2. The compiler is smart about certain types of errors; in this case, a callout is shown with a proposed solution to the problem. Press Return to apply the proposed solution. Compiling Once your application is running, click the buttons and see the generated random numbers. Congratulations—you have a working Cocoa application. Did you see the log statement on the console? When things go badly, the Cocoa classes will log to the console, so you will want to keep an eye on the console while testing your application.
The console is part of the Debug Area. You can control console visibility by using the Debug Area toggle on the toolbar. By default, Xcode is configured to show the console only when log output is generated and to hide it when the program exits. You can configure Xcode to always show the log in the Behaviors tab of the Preferences panel, as shown in Figure 2.
Behaviors in Preferences awakeFromNib Note that your application is flawed: When the application starts, instead of anything interesting, the word Label appears in the text field. You will make the text field display the time and date that the application started. As we discussed earlier, a NIB file is a collection of objects that have been archived. When the program is launched, the objects are brought back to life before the application handles any events from the user. This mechanism is a bit unusual; most GUI builders generate source code that lays out the user interface. Instead, Interface Builder allows the developer to edit the state of the objects in the interface and save that state to a file.
After being brought to life but before any events are handled, all objects are automatically sent the message awakeFromNib. Add the awakeFromNib method to RandomController. For now, just type it in. You will understand it later on. Briefly, you are creating an instance of NSDate that represents the current time. Just make sure that you add them after implementation and before end.
You will never have to call awakeFromNib; it gets called automatically. Simply run your application again. You should now see the date and time when the app runs Figure 2. Some of the confusion that you may experience as you read this book will come from trying to figure out which methods you have to call and which will get called for you automatically. Documentation Before this chapter wraps up, you should know where to find the documentation, as it may prove handy if you get stuck while doing an exercise later in the book.
Documentation and API Reference If you Option-click on a method, class, or function name, Xcode will show a quick-help pop-over from which you can go to the full documentation for that term. Also, the Quick Help Inspector in the utility area displays quick help for the term under the cursor, or the selected object in Interface Builder. What Have You Done? The application object reads the main NIB file and unarchives the objects inside. The objects are all sent the message awakeFromNib. Then the application object checks for events.
The timeline for these events appears in Figure 2. A Timeline When it receives an event from the keyboard mouse, the window server puts the event data into the event queue for the appropriate application, as shown in Figure 2. The application object reads the event data from its queue and forwards it to a user interface object, such as a button, and your code gets triggered.
If your code changes the data in a view, the view is redisplayed. Then the application object checks its event queue for another event. This process of checking for events and reacting to them constitutes the main event loop. This ends the process, and all your objects are destroyed. Move on to the next chapter so we can fill in some blanks. Chapter 3. Objective-C Once upon a time, a man named Brad Cox decided that it was time for the world to move toward a more modular programming style.
C was a popular and powerful language. Smalltalk was an elegant untyped object-oriented language. Starting with C, Brad Cox added Smalltalk-like classes and message-sending mechanisms. He called the result Objective-C. Objective-C is a very simple extension of the C language. In fact, it was originally just a C preprocessor and a library. Objective-C is not a proprietary language. Teaching C and basic object-oriented concepts could consume an entire book.
This chapter assumes that you already know a little C and something about objects and introduces you to the basics of Objective-C. If you fit the profile, you will find learning Objective-C to be easy. Creating and Using Instances Chapter 1 mentioned that classes are used to create objects, that the objects have methods, and that you can send messages to the objects to trigger these methods. In this section, you will learn how to create an object and send messages to it. As an example, we will use the class NSMutableArray.
In this case, it points to an object. Before using the object that foo points to, you would need to make sure that it is fully initialized. You can also send messages to classes, as demonstrated by sending the message alloc to the class NSMutableArray. The method init returns the newly initialized object. We will talk about this in the next chapter. Some methods take arguments. If a method takes an argument, the method name called a selector will end with a colon.
For example, to add objects to the end of the array, you use the addObject: method assume that bar is a pointer to another object : [foo addObject:bar]; If you have multiple arguments, the selector will have multiple parts. For example, to add an object at a particular index, you could use the following: [foo insertObject:bar atIndex:5]; Note that insertObject:atIndex: is one selector, not two.
It will trigger one method with two arguments. This outcome seems strange to most C and Java programmers but should be familiar to Smalltalk programmers. The syntax also makes your code easier to read. Most programmers grow to appreciate the Objective-C messaging syntax. You are now at a point where you can read simple Objective-C code, so it is time to write a program that will create an instance of NSMutableArray and fill it with ten instances of NSNumber. Close any projects that you were working on.
When the panel pops up, choose to create a Command Line Tool Figure 3. Figure 3. Choose Project Type A command-line tool has no graphical user interface and typically runs on the command line or in the background as a daemon. Unlike in an application project, you will always alter the main function of a command-line tool. Name the project lottery Figure 3.
Unlike the names of applications, most tool names are lowercase. Set the Type to Foundation. Name Project When the new project appears, select main. Edit main. The headers are precompiled, so this approach is not as computationally intensive as it sounds. We will discuss the importance of autorelease pools in the next chapter. Note that no array exists yet. You have simply declared a pointer that will refer to the array once it is created. One of the extensions is that strings are instances of the class NSString.
In C, strings are just pointers to a buffer of characters that ends in the null character. Both C strings and instances of NSString can be used in the same file. Wherever a string is needed, the classes in the frameworks expect an NSString. Besides the multibyte problem, you will have to wrestle with the fact that some languages read from right to left.
Whenever possible, you should use NSString instead of C strings. Completed Execution Sending Messages to nil In most object-oriented languages, your program will crash if you send a message to null. In applications written in those languages, you will see many checks for null before sending a message.
In Java, for example, you frequently see the following: if foo! The message is simply discarded, which eliminates the need for these sorts of checks. In the preceding example, what is bar set to? If bar were a pointer, it would be set to nil zero for pointers. For other types, the value is less predictable. All classes that come with Cocoa have names with the NS prefix. Classes that you will create will not start with NS.
These classes are all part of the Foundation framework. Some commonly used methods on NSObject are described next. A good description method will often make debugging easier. The value returned by the description method is put into the log string. In NSObject, this method is defined to return YES if and only if the receiver and anObject are the same object—that is, if both are pointers to the same memory location. For example, NSString overrides the method to compare the characters in the receiver and anObject.
If the two strings have the same characters in the same order, they are considered equal. The second expression compares the characters in the strings. It is indexed by integers. Thus, if there are n objects in the array, the objects are indexed by the integers 0 through n — 1. You cannot put a nil in an NSArray. An NSArray is created with all the objects that will ever be in it. You can neither add nor remove objects from an instance of NSArray.
We say that NSArray is immutable. Its mutable subclass, NSMutableArray, will be discussed next. Immutability is nice in some cases. Because it is immutable, a horde of objects can share one NSArray without worrying that one object in the horde might change it. Instead of changing a string or number, you will simply create another one with the new value. A single array can hold objects of many different classes. Arrays cannot, however, hold C primitive types, such as int or float.
Here are some commonly used methods implemented by NSArray: - unsigned count Returns the number of objects currently in the array. If i is beyond the end of the array, you will get an error at runtime. If the array is empty, nil is returned. Objects are considered equal if isEqual: returns YES. To create a mutable array from an immutable one, use Here are some commonly used methods implemented by NSMutableArray: - void addObject: id anObject Inserts anObject at the end of the receiver.
You are not allowed to add nil to the array. If index is already occupied, the objects at index and beyond are shifted up one slot to make room. You will get an error if anObject is nil or if index is greater than the number of elements in the array. You will get an error if index is beyond the end of the array. As mentioned earlier, you cannot add nil to an array. Sometimes, you will want to put an object into an array to represent nothingness. The NSNull class exists for exactly this purpose. In Cocoa, all manipulations involving character strings are done with NSString.
As a convenience, the Objective-C language also supports the " Works like sprintf. Stylish Objective-C programmers almost never do. The beginner would follow this path. In contrast, the old hand would create a class BankAccount that inherited from NSObject and has an instance variable called transactions that would point to an NSMutableArray. Subclassing involves more code and requires a deeper understanding of the superclass. By using composition instead of inheritance, Cocoa developers can take advantage of very powerful classes without really understanding how they work.
In an untyped language, such as Objective-C, inheritance is just a hack that saves the developer some typing. There are only two inheritance diagrams in this entire book. All the other diagrams are object diagrams that indicate which objects know about which other objects. This is much more important information to a Cocoa programmer. Creating Your Own Classes Where I live, the state government has decided that the uneducated have entirely too much money: You can play the lottery every week.
You will write a program that will make up lottery entries for the next ten weeks. Each LotteryEntry object will have a date and two random integers Figure 3. Besides learning how to create classes, you will build a tool that will certainly make you fabulously wealthy. Select Objective-C class as the type. Drag both files into the lottery group if they are not already there.
It takes no arguments and returns nothing. The method entryDate will return the value stored in the entryDate variable. The method setEntryDate: will allow the value of the entryDate variable to be set. Methods that allow variables to be read and set are called accessor methods. You have not declared accessors for setting these variables; you are going to set them directly in prepareRandomNumbers. Changing main. Many of the lines have stayed the same, but several have changed. Here is the heavily commented code.
This program will create an array of LotteryEntry objects, as shown in Figure 3. Object Diagram Implementing a description Method Build and run your application. You should see something like Figure 3. Completed Execution Hmm. Not quite what we hoped for. You are seeing the default description method as defined in NSObject. Next, you will make the LotteryEntry objects display themselves in a more meaningful manner. Add a description method to LotteryEntry. Now you should see the dates and numbers: Figure 3.
Because NSDate is immutable, many objects often share a single date object. There is seldom any need to create a copy of an NSDate object. This is a class method. A class method is triggered by sending a message to the class instead of an instance. If the receiver is earlier than anotherDate, the return value is negative. NSTimeInterval is the same as double. This is something that should be handled by the initializer, so you are going to override the init method in your LotteryEntry class.
In the LotteryEntry. Now delete the following line in main. Take another look at our init method. The answer is that the initializers of some Cocoa classes will return nil if initialization was impossible. In order to handle these cases gracefully, we must both test the return value of [super init] and return the appropriate value for self from our initiailizer.
This pattern is debated among some Objective-C programmers. We believe it best to be in the habit of assigning to self and testing that value. Initializers with Arguments Look at the same place in main. Next, declare the method in LotteryEntry. It should work correctly. However, your class LotteryEntry has a problem. You are going to e-mail the class to your friend Rex. Rex plans to use the class LotteryEntry in his program but might not realize that you have written initWithEntryDate:.
The problem is that firstNumber and secondNumber will not get initialized properly—both will be zero. Note that initWithEntryDate: still does all the work. Because a class can have multiple initializers, we call the one that does the work the designated initializer. If a class has several initializers, the designated initializer typically takes the most arguments.
You should clearly document which of your initializers is the designated initializer. Note that the designated initializer for NSObject is init. All other initializers call the designated initializer. The day will come when you will create a class that must, must, must have some argument supplied. Apple has made significant improvements to both over the years. This section discusses the processes of setting breakpoints, invoking the debugger, and browsing the values of variables.
While browsing code, you may have noticed a gray margin to the left of your code. If you click in that margin, a breakpoint will be added at the corresponding line. Add a breakpoint in main. Creating a Breakpoint When you run the program, Xcode will start the program in the debugger if you have any breakpoints.
To test this, run it now. The debugger will take a few seconds to get started, and then it will run your program until it hits the breakpoint. When your application is running, the debugger bar will be shown below the editor area. The debugger bar contains a button to toggle visibility of the full debugger area, including the variables view and console, as well as buttons to control the execution of your program and information about the current thread and function.
You should also see the Debug navigator on the left, which shows the threads in our application and frames on the stack for each thread. Because the breakpoint is in main , the stack is not very deep. In the variables view on the left in the debugger area, you can see the variables and their values Figure 3. Stopped at a Breakpoint Note that the variable i is currently 0. Return your attention to the debugger bar. Four of the buttons above the variables view are for pausing or continuing and stepping over, into, and out of functions. Click the Continue button to execute another iteration of the loop.
Click the Step-Over button to walk through the code line by line. The gdb debugger, being a Unix thing, was designed to be run from a terminal. When execution is paused, the gdb terminal will appear in the Console panel. If a variable is a pointer to an object, when you po it, the object is sent the message description, and the result is printed in the console. Try printing the newEntry variable. Using the gdb Console Exceptions are raised when something goes very wrong.
To make the debugger stop whenever an exception is thrown, you will want to add an exception breakpoint. Click the Add button at the bottom of the breakpoint navigator and select Add Exception Breakpoint Set the exception type to Objective-C and click Done Figure 3. Disable the existing breakpoint in main by clicking on the blue breakpoint icon in the breakpoint navigator.
The breakpoint will be dimmed when it is disabled. Adding an Exception Breakpoint You can test this exception breakpoint by asking for an index that is not in an array. It should stop when the exception is raised. One of the challenging things about debugging Cocoa programs is that they will often limp along in a broken state for quite a while.
Using the macro NSAssert , you can get the program to throw an exception as soon as the train leaves the track. For example, in setEntryDate:, you might want an exception thrown if the argument is nil. Your code, being correct, will not throw an exception. Note that a message, including the name of the class and method, is logged and an exception is thrown.
Wise use of NSAssert can help you hunt down bugs much more quickly. You probably do not need your assert calls checked in your completed product. On most projects, there are two build configurations: Debug and Release. In the Debug version, you will want all your asserts checked. In the Release configuration, you will not. You will typically block assertion checking in the Release configuration Figure 3. Disabling Assertion Checking To do this, bring up the build settings by selecting the lottery project in the project navigator topmost item.
Then select the lottery target, change to the Build Settings tab, and find the Preprocessor Macros item. A quick way to find it is to use the search field at the top of the Build Settings panel. The Preprocessor Macros item will have one item beneath it for each build configuration: Debug and Release. Before going on, fix your assertion: It should ensure that dates are not nil. You can change your current build configuration to Release by opening the scheme editor in the Product menu, click Edit Scheme Now when you build and run your application, it will be built using the Release configuration.
Note that the default build configuration for the Archive action is Release. We will discuss build configurations in more detail in Chapter NSAssert works only inside Objective-C methods. For more in-depth information, refer to the documentation from the Free Software Foundation www. You have written a simple program in Objective-C, including a main function that created several objects. Some of these objects were instances of LotteryEntry, a class that you created. The program logged some information to the console. At this point, you have a fairly complete understanding of Objective-C.
Objective-C is not a complex language. The rest of the book is concerned with the frameworks that make up Cocoa. From now on, you will be creating event-driven applications, not command-line tools. Meet the Static Analyzer One of the handiest tools in Xcode is the static analyzer. Traditionally, developers have relied on compiler warnings for hints on potential trouble areas in their code. The static analyzer goes much deeper, looking past syntax and tracing how values are used within your code.
Because of the default compiler settings and our careful typing, you should find, if you run the analyzer now, that our application has no issues as it stands. Then select the lottery target. Change its value to No Figure 3. Disable Automatic Reference Counting Now analyze the lottery application. In the Product menu, click Analyze. The Static Analyzer at Work In this case, the static analyzer has found a number of memory-related problems in our program because we disabled a feature called automatic reference counting, which we will discuss in the next chapter.
This is one of the more useful aspects of the static analyzer: It knows the rules for retaincount memory management in Objective-C, and it can also identify other dangerous patterns in your code. Leave automatic reference counting disabled for now. As mentioned earlier, an object is like a C struct. NSObject declares an instance variable called isa.
Because NSObject is the root of the entire class inheritance tree, every object has an isa pointer to the class structure that created the object Figure 3. The class structure includes the names and types of the instance variables for the class. The class structure has a pointer to the class structure for its superclass. The selector is of type SEL. Each method name is mapped to a unique int.
For example, the method name addObject: might map to the number When you look up methods, you will use the selector, not the string "addObject:". As part of the Objective-C data structures, a table maps the names of methods to their selectors. The Selector Table At compile time, the compiler looks up the selectors wherever it sees a message send. If it does not find the method, it follows the pointer to the superclass. If the superclass does not have a method for 12, it continues searching up the tree. If it reaches the top of the tree without finding a method, the function throws an exception.
R for Mac OS X FAQ
Clearly, this is a very dynamic way of handling messages. These class structures can be changed at runtime. In particular, using the NSBundle class makes it relatively easy to add classes and methods to your program while it is running. This very powerful technique has been used to create applications that can be extended by other developers. Chapter 4. If two people have the same favoriteColor, the objects will have pointers to the same color object.
As the people age, their favorite color might change. Figure 4. The Problem We do not want this orphaned color to be taking up room in the memory of our program. We want the memory deallocated so that we can put new objects in that memory, but we must be sure that the color is not deallocated while any objects are pointing to it. This is a relatively tricky problem. Apple has come up with three solutions: 1. The first is manual reference counting, or retain counts: Every object has a retain count, which should represent the number of other objects that have pointers to it.
If the color is the favorite of two people, the retain count of that color should be 2. When the retain count of an object goes to zero, it is deallocated. Then, in Mac OS The unreachable objects are automatically deallocated. The new solution, introduced in Mac OS ARC relies on the original retain-count mechanism but with a twist: The compiler manages the bookkeeping of retain counts for you. What are the trade-offs? Manual reference counting is, after all, manual and requires some work on your part: You need to explicitly retain objects that you want to keep around and explicity release them when you are no longer interested in them.
If not used carefully, the retain-count mechanism allows for a dastardly problem: Object A retains Object B, B retains A. Together, they are an island of memory that will never go away, because they are retaining each other. This is known as a retain cycle. An Island of Garbage The garbage collector sounds good on the surface but has a performance cost: It requires CPU time to scan through the objects, looking for garbage.
This can sometimes result in poorer or uneven performance. For example, in an application that requires smooth performance, such as an action game, or an application that plays back video being rendered in real time, the garbage collector can cause hiccups in the processing while it is doing a scan.
Additionally, the garbage collector cannot manage memory that you allocate manually, such as with malloc , without special treatment. Garbagecollected code cannot run on versions of Mac OS X prior to ARC provides the best of both worlds: You get the speed and efficiency of manual reference counting, along with the freedom from memory-management concerns that garbage collection allows. If you want to write code for versions of Mac OS X prior to Living with Manual Reference Counting Retain counts are a pretty simple concept. Every object in Objective-C has a retain count.
The retain count is an integer. When an object is created by the method, the retain count is set to 1.
Cocoa(R) Programming for Mac(R) OS X (3rd Edition)
When the retain count becomes zero, the object is deallocated. You increment the retain count by sending the message retain to the object. You decrement the retain count by sending the message release to the object. When the retain count becomes zero, this indicates that no one cares about it any more. It is deallocated so that the memory it was occupying can be reused.
A commonly used analogy is that of the dog and the leash. Each person who wants to ensure that the dog will stay around retains the dog by attaching a leash to its collar. Many people can retain the dog; as long as at least one person is retaining the dog, the dog will not go free. When zero people are retaining the dog, it will be deallocated. Objects Retain Each Other The retain-count system gives the developer a lot of control over how and when objects are deallocated, but it requires that you meticulously retain and release objects.
If you release an object too many times, it will be deallocated prematurely, and your program will crash. If you retain an object too many times, it will never get deallocated, and you will waste memory. Fortunately, some simple rules govern when you should retain and release objects. These rules take the guesswork out of memory management with retain counts. In fact, once you are clear on these rules, it will be very clear in most cases when to retain and when to release.
Note that if you did not disable automatic reference counting at the end of the Chapter 3 be sure to make that build setting change now. Open lottery. Whenever we create a new instance of an object, we are taking responsibility for releasing it.
Open main. What about the LotteryEntry instances we added to the array? Instead, the array stores a pointer to the object and sends it the message retain. When the array is deallocated, the objects in the array are sent the message release. Also, if an object is removed from an array, it is sent release. When the entry object is created, it has a retain count of 1. When the entry object is added to the array, its retain count is incremented to 2.
When the array is deallocated, it releases the entry. This decrements the retain count to 1. So the LotteryEntry object is being leaked it is never deallocated. In this example, the process ends an instant later, and the operating system reclaims all the memory. Thus, the lack of deallocation is not a big deal. However, in a program that ran a long time, such a memory leak would be a bad thing. What guarantee does LotteryEntry have that the NSDate instance will not be deallocated out from under it? Right now, it has no guarantee. This is called a strong reference. In some situations, a weak reference nonretaining is more appropriate; this is generally used to avoid creating a retain cycle.
For example, a parent object generally retains its children perhaps indirectly via an array , but the child will not retain its parent. Open LotteryEntry. The perfect place to relinquish ownership is dealloc. Add a dealloc method to LotteryEntry. Build and run your app. It should work fine, and you should see that the entries are being properly deallocated Figure 4. Running without the Garbage Collector There is, however, still a memory leak.
When the method returns, df and result both have a retain count of 1. The pointer returned by this method would be to the freed object, now an invalid pointer, almost certainly leading to a crash. The problem, then, is that you need to return a string, but you do not want to retain it. This is a common problem throughout the frameworks, which leads us to the final piece of the retain-count puzzle: the autorelease pool. Autorelease pools simplify releasing objects. You can add an object to the current autorelease pool simply by sending it the message autorelease.
Adding an object to an autorelease pool marks it to be sent a release message at some point in the future. The release message is sent once the pool is drained. In a Cocoa application, an autorelease pool is created before every event is handled and is drained after the event has been handled. Thus, unless the objects in the autorelease pool are being retained, they will be destroyed as soon as the event has been handled.
In the case of the lottery project, a command-line tool, there is no event loop, and so the autorelease pool has been created explicitly. This hints at another aspect of autorelease pools: They can be nested to reduce peak memory consumption, for example, in a large loop. The topmost pool is the pool to which autoreleased objects will be sent.
Note that if you autorelease an object n times, it will be sent release n times once the pool is drained. Sometimes, Objective-C programmers autorelease objects out of necessity, such as in this case, when returning an object from a method; other times, it is more a matter of convenience. Because you will frequently need objects that you are not retaining, many classes have class methods that return autoreleased objects.
NSString, for example, has stringWithFormat:. This behavior makes it perfect for providing an intermediate result. One of the resulting strings is returned and may be retained by the object that asked for it. The other 25 strings are deallocated automatically at the end of the event loop. Note that you would probably get better performance in this example by appending the uppercased string to an NSMutableString instead of creating a new string and adding it to the autorelease pool each time through the loop. The Retain-Count Rules Now that you are familiar with retain, release, and autorelease, you are ready for the rules.
Implementation details are in parentheses. That is, assume that the new object has a retain count of 1 and is not in the autorelease pool. You have a responsibility to release the object when you no longer need it. Some of the common methods that convey ownership are alloc which is always followed by an init method , copy, and mutableCopy. That is, assume that it has a retain count of 1 and is already in the autorelease pool and thus doomed unless it is retained before the autorelease pool is drained.
This increments the retain count. The message release decrements the retain count immediately; autorelease causes the message release to get sent when the autorelease pool is drained. When its retain count goes to zero, it is sent the message dealloc. One of the tricks to understanding memory management is to think locally. The LotteryEntry class does not need to know anything about other objects that also care about its entryDate. Programmers new to the language sometimes make the mistake of trying to keep tabs on objects throughout an application.
If you follow these rules and always think local to a class, you never have to worry what the rest of an application is doing with an object.
Accessor Methods An object has instance variables. Other objects cannot access these variables directly. To enable other objects to read and set an instance variable, an object will usually have a pair of accessor methods. For example, if a class Rex has an instance variable named fido, the class will probably have at least two other methods: fido and setFido:. The fido method enables other objects to read the fido variable; the setFido: method enables other objects to set the fido variable. If you have a nonpointer type, the accessor methods are quite simple.
Matters become more complicated if foo is a pointer to an object. If you assume that foo is a pointer to an NSDate, there are three common idioms in setter methods. All three work correctly, and you can probably find some experienced Cocoa programmers who will argue the superiority of any one of them. Each has trade-offs. Suppose that you reverse the order. If x and foo are both pointers to the same object that happens to have a retain count of 1, the release would cause the object to be deallocated before it was retained. Trade-off: If they are the same value, this method performs an unnecessary retain and release.
9: Brew and Analyze
Trade-off: An extra if statement is necessary. Trade-off: An error in retain counts will result in a crash one event loop after the error. This behavior makes the bug harder to track down. In the first two idioms, your crash will happen closer to your error. Also, autorelease carries some performance overhead. You have read the trade-offs and can make your own decision on which to use.
Objective-C programmers call this method foo. In the common idioms of Objective-C, a method prefixed with get takes an address where data can be copied. Change setEntryDate: in LotteryEntry. You have now completed converting the lottery project to a retain-counted application. Living with ARC Although manual reference counting is fairly simple, it can be difficult to execute perfectly.
At best, this leads to minor leaks but more typically results in crashes. At the end of Chapter 3, we saw that the static analyzer was able to find Objective-C memory errors in our code. ARC is a compiler feature, based on the same technology that powers the static analyzer. When you compile your application, your use of Objective-C object pointers references is examined by the compiler, which then applies the same rules we described earlier in this chapter, retaining, releasing, and autoreleasing to ensure that the objects live as long as necessary and are deallocated when they are no longer needed.
Essentially, this means that all the memory-related changes we made to the lottery project were unnecessary under ARC. In fact, when using ARC, it is an error to call retain, release, or autorelease. With ARC, you will think less about retain counts and focus more on object relationships.
Relationships are defined by references, which are simply object pointers. There are two types of references: strong and weak. Strong References By default, references are strong. If you assign an object to a strong reference, ARC assumes that you want that object to stick around and retains it implicitly. If that reference is changed to a new value, the old object is released and the new object retained, just like the setEntryDate: setter we wrote in the previous section. You can still implement dealloc to take care of any other cleanup tasks.
Weak References Weak references are similar to the old manual reference-counted pointers: There is no implicit retain; the pointer value is simply changed in memory. Such references have long been an area ripe for causing crashes, however. If the pointer is not retained, the object can be deallocated, leaving a bad pointer to cause a crash when it is used.
ARC addresses this by automatically setting weak references to nil when the object they point to has been deallocated. Recall the retain-cycle issue we touched on before, where two objects are retaining each other and thus are never deallocated. In ARC, this is referred to as a strong reference cycle. By using weak references strategically, we can avoid these cycles altogether. This causes a strong reference cycle! Person has a strong reference to both parent and children; the children array has strong references to objects it contains.
No strong reference cycle. Note that only classes compiled with ARC can have weak references made to them. The object will not be retained, but this reference will not be set to nil when the object is deallocated. In fact, it is possible to use ARC on a per file basis. It is important, however, that manually reference-counted code adhere to the rules discussed earlier in this chapter.
Additionally, you cannot override retain, release, or autorelease.
Related Cocoa(R) Programming for Mac(R) OS X (3rd Edition)
Copyright 2019 - All Right Reserved