Objective C 学习笔记 - daaoling/daaoling.github.io GitHub Wiki
Objective-C 学习笔记
##id
##SEL
SEL is the Objective-C “type” for a selector
SEL shootSelector = @selector(shoot);
SEL shootAtSelector = @selector(shootAt:);
SEL moveToSelector = @selector(moveTo:withPenColor:);
If you have a SEL, you can also ask an object to perform it ...
Using the performSelector: or performSelector:withObject: methods in NSObject
[obj performSelector:shootSelector];
[obj performSelector:shootAtSelector withObject:coordinate];
Using makeObjectsPerformSelector: methods in NSArray
[array makeObjectsPerformSelector:shootSelector]; // cool, huh?
[array makeObjectsPerformSelector:shootAtSelector withObject:target]; // target is an id
In UIButton, - (void)addTarget:(id)anObject action:(SEL)action ...;
[button addTarget:self action:@selector(digitPressed:) ...];
notice that all function you have to implement if you want to use it
- (NSString *)description
is a useful method to override (it’s %@ in NSLog()). Example ... NSLog(@“array contents are %@”, myArray); The %@ is replaced with the results of invoking [myArray description].
Copying objects. This is an important concept to understand (why mutable vs. immutable?).
- (id)copy; // not all objects implement mechanism (raises exception if not)
- (id)mutableCopy; // not all objects implement mechanism (raises exception if not)
It’s not uncommon to have an array or dictionary and make a mutableCopy and modify that. Or to have a mutable array or dictionary and copy it to “freeze it” and make it immutable. Making copies of collection classes is very efficient, so don’t sweat doing so.
Ordered collection of objects. Immutable. That’s right, once you create the array, you cannot add or remove objects. All objects in the array are held onto strongly.
Usually created by manipulating other arrays or with @[].
You already know these key methods ...
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index; // crashes if index is out of bounds; returns id!
- (id)lastObject; returns nil (doesn’t crash) if there are no objects in the array
- (id)firstObject; // returns nil (doesn’t crash) if there are no objects in the array
But there are a lot of very interesting methods in this class. Examples ...
- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;
- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)selectorArgument;
- (NSString *)componentsJoinedByString:(NSString *)separator;
Mutable version of NSArray. Create with alloc/init or ...
+ (id)arrayWithCapacity:(NSUInteger)numItems; // numItems is a performance hint only
+ (id)array; // [NSMutableArray array] is just like [[NSMutableArray alloc] init]
NSMutableArray inherits all of NSArray’s methods. Not just count, objectAtIndex:, etc., but also the more interesting ones mentioned last slide. And you know that it implements these key methods as well ...
- (void)addObject:(id)object; // to the end of the array (note id is the type!)
- (void)insertObject:(id)object atIndex:(NSUInteger)index;
- (void)removeObjectAtIndex:(NSUInteger)index;
Loop Operation:
Example1: NSArray of NSString objects
NSArray *myArray = ...;
for (NSString *string in myArray) { // no way for compiler to know what myArray contains
double value = [string doubleValue]; // crash here if string is not an NSString
}
Example2: NSArray of id NSArray *myArray = ...;
for (id obj in myArray) {
// do something with obj, but make sure you don’t send it a message it does not respond to
if ([obj isKindOfClass:[NSString class]]) {
 // send NSString messages to obj with no worries
}
}
Immutable collection of objects looked up by a key (simple hash table). All keys and values are held onto strongly by an NSDictionary.
Can create with this syntax: @{ key1 : value1, key2 : value2, key3 : value3 }
NSDictionary *colors = @{ @“green” : [UIColor greenColor],
@“blue” : [UIColor blueColor],
@“red” : [UIColor redColor] };
Lookup using “array like” notation ...
NSString *colorString = ...;
UIColor *colorObject = colors[colorString]; // works the same as objectForKey: below
- (NSUInteger)count;
- (id)objectForKey:(id)key;
// key must implement hash and isEqual: properly NSStrings make good keys because of this.
See NSCopying protocol for more about what it takes to be a key. 
Mutable version of NSDictionary.
Create using alloc/init or one of the
+ (id)dictionary... class methods.
In addition to all the methods inherited from NSDictionary, here are some important methods ...
- (void)setObject:(id)anObject forKey:(id)key;
- (void)removeObjectForKey:(id)key;
- (void)removeAllObjects;
- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
Loop Operation:
NSDictionary *myDictionary = ...;
for (id key in myDictionary) {
// do something with key here
id value = [myDictionary objectForKey:key];
// do something with value here
}
objecive-c is different when dispatch and call method, it use dynamic bindding (i.e send method to obj runime)
cause all object pointers (e.g. NSString *) are treated like id at runtime. which means in runtime, they will look up the right code (i.e right method) to execute
Is it safe?
Because we mostly use static typing (e.g. NSString *) and the compiler is really smart to check obj will responed to method. so it's ok
So What we could do intentionally use this dangerous thing?
1.Introspection 2.Protocol
isKindOfClass: returns whether an object is that kind of class (inheritance included) isMemberOfClass: returns whether an object is that kind of class (no inheritance) respondsToSelector: returns whether an object responds to a given method
Class testing methods take a Class
if ([obj isKindOfClass:[NSString class]]) {
 NSString *s = [(NSString *)obj stringByAppendingString:@”xyzzy”];
}
Method testing methods take a selector (SEL)
Special @selector() directive turns the name of a method into a selector
if ([obj respondsToSelector:@selector(shoot)]) {
[obj shoot];
} else if ([obj respondsToSelector:@selector(shootAt:)]) {
[obj shootAt:target];
}//notice the method name shootAt:
I only use the next conditional and do not even need a category:
if (!aString.length) { ... } Using Objective-C theory, a message to NIL will return nil or zero, so basically you do not have to test for nil.
But be careful if the method return a c struct, return value is undefined
CGPint p = [obj getLocation]; // p will have an undefined value if obj is nil , you need check obj is not nil