iOS 笔记一: 对象创建、动态绑定、内审

来源:互联网 发布:淘宝上买证书 编辑:程序博客网 时间:2024/06/06 01:20
一. 创建对象
1. 大部分时候,我们使用alloc 和 init 来创建对象,如:
NSMutableArray *cards = [[NSMutableArray alloc] init];
CardMatchingGame *game = [[CardMatchingGame alloc] initWithCardCount:12 usingDeck:d];

2. 或者也可以使用类方法:
NSString’s + (id)stringWithFormat:(NSString *)format, ...
NSString *moltuae = [NSString stringWithFormat:@“%d”, 42];
UIButton’s + (id)buttonWithType:(UIButtonType)buttonType;
NSMutableArray’s + (id)arrayWithCapacity:(int)count;
NSArray’s + (id)arrayWithObject:(id)anObject;

3. 有时候类方法和init方法都有:
[NSString stringWithFormat:...]和 [[NSString alloc] initWithFormat:...]一样
不要被他们困扰, 这2种方式都很好。

4. 你也可以让其它对象给你创建一个新的对象:
NSString’s - (NSString *)stringByAppendingString:(NSString *)otherString;
NSArray’s - (NSString *)componentsJoinedByString:(NSString *)separator;
NSString’s & NSArray’s - (id)mutableCopy;

但是不是所有返回的对象都是新建的, 如:
NSArray’s - (id)lastObject;
NSArray’s - (id)objectAtIndex:(int)index;

除非方法中有“copy”字眼,如果所需要的对象已经存在,你将得到一个指向它的指针,
如果所需要的对象不存在,那么将创建出新的对象。


二. nil
1. 向nil发送消息是可以的,但是什么代码都不会执行,如果该消息有返回值,
那么将返回0.
int i = [obj methodWhichReturnsAnInt]; // i will be zero if obj is nil
你可以使用这个特性来编写代码, 但是请注意:
如果消息返回的是一个C 结构体, 那么返回值是未定义的。
CGPoint p = [obj getLocation]; // p will have an undefined value if obj is nil


三. 动态绑定:
1. Objective-C 有一个特别重要的类型: id,
它表示 ”一个指向未知类型对象的指针“
id myObject;
事实上,在运行时,所有对象指针(如:NSSTring *) 都被当作 id 来处理。
但是在编译期间,如果你用NSString *代替id,编译器能帮你做类型检查。
它能帮你找到bug和建议你什么方法可以发给这个对象,等等。
如果你指定一个对象的类型为id,编译器将无法帮你做这些检查。
在运行时发送一个消息给一个对象,找出该消息对应的执行代码叫做”动态绑定“。

2. 动态绑定是否安全?
在运行时把所有的对象都当作”指向未知类型的指针“看起来好危险,有没有?
没有人能阻止你向一个对象发送它不能理解的消息,并且如果你这么做的话,
你的程序将崩溃。那么是不是Objective-C程序经常崩溃呢?
不是的。
因为我们大部分时候使用了静态类型检查(e.g. NSString *),并且编译器很聪明。

3. 静态类型检查
NSString *s = @“x”; // “statically” typed (compiler will warn if s is sent non-NSString messges).
id obj = s; // not statically typed, but perfectly legal; compiler can’t catch [obj rank]
NSArray *a = obj; // also legal, but obviously could lead to some big trouble!
Compiler will not complain about assignments between an id and a statically typed variable.
编译器不会抱怨在id和静态类型变量之间的赋值,对于编译器来说,这是合法的。
千万不要用”id *“这样的方式来使用id,这个表示一个指向指针的指针。

4.内省
所有继承至NSObject的类都有以下方法:
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)来作为参数,你可以通过类方法"class"来得到一个Class,
而不是实例方法class,如:
if ([obj isKindOfClass:[NSString class]]) {
NSString *s = [(NSString *)obj stringByAppendingString:@”xyzzy”];
}

方法测试使用一个selector(SEL)作为参数:
使用@selector()直接将方法名转换成一个selector:
if ([obj respondsToSelector:@selector(shoot)]) {
[obj shoot];
} else if ([obj respondsToSelector:@selector(shootAt:)]) {
[obj shootAt:target];
}
SEL 是Objective-C的selector类型:
SEL shootSelector = @selector(shoot);
SEL shootAtSelector = @selector(shootAt:);
SEL moveToSelector = @selector(moveTo:withPenColor:);

如果你有一个SEL,你可以试着让一个对象来执行它。
对NSObject使用performSelector: 或者 performSelector:withObject:
[obj performSelector:shootSelector];
[obj performSelector:shootAtSelector withObject:coordinate];

对NSArray使用makeObjectsPerformSelector:
[array makeObjectsPerformSelector:shootSelector]; // cool, huh?
[array makeObjectsPerformSelector:shootAtSelector withObject:target]; // target is an id

在UIButton中, - (void)addTarget:(id)anObject action:(SEL)action ...;
[button addTarget:self action:@selector(digitPressed:) ...];


四. Foundation Framework
1. NSObject: 在ios SDK中几乎是所有类的基类,实现了前面提到的内省方法。
- (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].

2. NSDictionary: 不可变集合,使用key来查找(简单哈希表),所以的key和value
都用强指针保留。
可以使用以下语法创建:@{ key1 : value1, key2 : value2, key3 : value3 }
NSDictionary *colors =     @{ @“green” : [UIColor greenColor],
                                                @“blue” : [UIColor blueColor],
                                                @“red” : [UIColor redColor] };
可以使用数组的方式引用:
NSString *colorString = ...;
UIColor *colorObject = colors[colorString]; // works the same as objectForKey: below

- (id)objectForKey:(id)key; // key must be copyable and implement isEqual: properly
NSStrings make good keys because of this.
See NSCopying protocol for more about what it takes to be a key.

NSMutableDictionary: NSDictionary的可变版本。
使用alloc/init 或者+(id)dictionary...类方法来创建。

遍历字典的键或值:
NSDictionary *myDictionary = ...;
for (id key in myDictionary) {
// do something with key here
id value = [myDictionary objectForKey:key];
// do something with value here
}
0 0