Objective C 学习笔记 - daaoling/daaoling.github.io GitHub Wiki

Objective-C 学习笔记

Data Tpyes

##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:) ...];

Foundation FrameWork

NSObject

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.

NSArray

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;

NSMutableArray

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 
	}
}

NSDictionary

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. 

NSMutableDictionary

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 
}

Dynamic Binding

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

Introspection

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:

nil Mechanism

NSString “nil or empty” check

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

⚠️ **GitHub.com Fallback** ⚠️