- •C and Objective-C
- •How this book works
- •How the life of a programmer works
- •Installing Apple’s developer tools
- •Getting started with Xcode
- •Where do I start writing code?
- •How do I run my program?
- •So what is a program?
- •Don’t stop
- •Types
- •A program with variables
- •Challenge
- •Boolean variables
- •When should I use a function?
- •How do I write and use a function?
- •How functions work together
- •Local variables, frames, and the stack
- •Recursion
- •Looking at the frames in the debugger
- •return
- •Global and static variables
- •Challenge
- •printf()
- •Integer operations
- •Integer division
- •Operator shorthand
- •Floating-point numbers
- •Tokens for displaying floating-point numbers
- •The while loop
- •The for loop
- •break
- •continue
- •The do-while loop
- •Challenge
- •Getting addresses
- •Storing addresses in pointers
- •Getting the data at an address
- •How many bytes?
- •NULL
- •Stylish pointer declarations
- •Challenges
- •Writing pass-by-reference functions
- •Avoid dereferencing NULL
- •Creating and using your first object
- •Message anatomy
- •Objects in memory
- •Challenge
- •Nesting message sends
- •Multiple arguments
- •Sending messages to nil
- •Challenge
- •Challenge
- •NSMutableArray
- •Reference pages
- •Quick Help
- •Other options and resources
- •Accessor methods
- •Dot notation
- •Properties
- •self
- •Multiple files
- •Challenge
- •Overriding methods
- •super
- •Challenge
- •Object ownership and ARC
- •Creating the Asset class
- •Adding a to-many relationship to Employee
- •Challenge
- •Retain cycles
- •Weak references
- •Zeroing of weak references
- •For the More Curious: Manual reference counting and ARC History
- •Retain count rules
- •NSArray/NSMutableArray
- •Immutable objects
- •Sorting
- •Filtering
- •NSSet/NSMutableSet
- •NSDictionary/NSMutableDictionary
- •Preprocessor directives
- •#include and #import
- •#define
- •Global variables
- •enum
- •#define vs global variables
- •Writing an NSString to a file
- •Reading files with NSString
- •Writing an NSData object to a file
- •Reading an NSData from a file
- •Target-action
- •Helper objects
- •Notifications
- •Which to use?
- •Callbacks and object ownership
- •Challenge
- •Getting started with iTahDoodle
- •BNRAppDelegate
- •Adding a C helper function
- •Objects in iTahDoodle
- •Model-View-Controller
- •The application delegate
- •Setting up views
- •Running on the iOS simulator
- •Wiring up the table view
- •Adding new tasks
- •Saving task data
- •For the More Curious: What about main()?
- •Edit BNRDocument.h
- •A look at Interface Builder
- •Edit BNRDocument.xib
- •Making connections
- •Revisiting MVC
- •Edit BNRDocument.m
- •Writing init methods
- •A basic init method
- •Using accessors
- •init methods that take arguments
- •Deadly init methods
- •Property attributes
- •Mutability
- •Lifetime specifiers
- •copy
- •More about copying
- •Advice on atomic vs. nonatomic
- •Key-value coding
- •Non-object types
- •Defining blocks
- •Using blocks
- •Declaring a block variable
- •Assigning a block
- •Passing in a block
- •typedef
- •Return values
- •Memory management
- •The block-based future
- •Challenges
- •Anonymous block
- •NSNotificationCenter
- •Bitwise-OR
- •Bitwise-AND
- •Other bitwise operators
- •Exclusive OR
- •Complement
- •Left-shift
- •Right-shift
- •Using enum to define bit masks
- •More bytes
- •Challenge
- •char
- •char *
- •String literals
- •Converting to and from NSString
- •Next Steps
- •Index
Chapter 30 Properties
There is no property lifetime specifier called mutableCopy. If you wish for your setter to set the property to be a mutable copy of an object, you must implement the setter yourself so that it calls the mutableCopy method on the incoming object. For example, in OwnedAppliance, you might create a setOwnerNames: method:
- (void)setOwnerNames:(NSSet *)newNames
{
ownerNames = [newNames mutableCopy];
}
More about copying
Most Objective-C classes have no copyWithZone: method at all. Objective-C programmers make fewer copies than you might think.
Curiously, the copy and mutableCopy methods are defined in NSObject like this:
-(id)copy
{
return [self copyWithZone:NULL];
}
-(id)mutableCopy
{
return [self mutableCopyWithZone:NULL];
}
Thus, if you have some code like this:
Appliance *b = [[Appliance alloc] init];
Appliance *c = [b copy];
You will get an error like this:
-[Appliance copyWithZone:]: unrecognized selector sent to instance 0x100110130
Advice on atomic vs. nonatomic
This is an introductory book on programming, and the atomic/nonatomic option relates to a relatively advanced topic known as multithreading. Here is what you need to know: the nonatomic option will make your setter method run a tiny bit faster. If you look at the headers for Apple’s UIKit, every property is marked as nonatomic. You should make your properties nonatomic, too.
(I give this advice to everyone. In every group, however, there is someone who knows just enough to be a pain. That person says, “But when I make my app multithreaded, I’ll need the protection that atomic setter methods get me.” And I should say, “I don’t think you will write multithreaded code anytime soon. And when you do, I don’t think atomic setter methods are going to help.” But what I really say is “OK, then you should leave your setters atomic.” Because you can’t tell someone something they aren’t ready to hear.)
In Appliance.h, make your accessors non-atomic:
@property (copy, nonatomic) NSString *productName; @property (nonatomic) int voltage;
Sadly, at this time, the default for properties is atomic, so you do have to make this change.
220