4 Foundation和带属性的字符串(1)

来源:互联网 发布:一元购源码下载 编辑:程序博客网 时间:2024/05/21 07:12
创建对象
多数时候,我们创建对象以alloc和init...
NSMutableArray *card = [[NSMutableArray alloc] init];CardMatchingGame *game = [[CardMatchingGame alloc] initWithCardCount:12 usingDeck:d];


或者以类方法
NSString:     
+ (instancetype)stringWithFormat:(NSString *)format, ...NSString *moltuae = [NSString stringWithFormat:@"%d", 42];
UIButton:     
+ (id)buttonWithType:(UIButtonType)buttonType;
NSMutableArray:     
+ (instancetype)arrayWithCapacity:(NSUInteger)numItems;
NSArray:
+ (instancetype)arrayWithObject:(id)anObject;


有时类创建方法与init方法共存
[NSString stringWithFormat:...]
等同
[[NSString alloc] initWithFormat:...]
不要被这个干扰。使用任一版本皆可。
iOS似乎倾向分配/初始化版本在新的API,但大多是中性的。


你也可以要求其他对象来为你创建新的对象
NSString:
- (NSString *)stringByAppendingString:(NSString *)aString;
NSArray:
- (NSString *)componentsJoinedByString:(NSString *)separator;
NSString与NSArray:
- (id)mutableCopy;


但是,并非其他对象给出的对象都是新创建的
NSArray:
- (id)lastObject;
NSArray:
- (id)objectAtIndex:(NSUInteger)index;
除在它的方法有“copy”这个单词,如果对象已经存在,你将得到一个指向它的指针
如果对象不是已经存在的,这时创建



nil
给nil发消息(通常)是OK的。没有代码会执行。
如果该方法返回一个值,它会返回零。
int i = [obj methodWhichReturnsAnInt]; // 如果obj是nil,i将会是零
依靠这个并且编写代码使用这个是绝对没问题的

但要小心,如果该方法返回一个C结构。返回值是不确定的。
CGPoint p = [obj getLocation]; // 如果obj是nil,p将有一个不确定的值



动态绑定
Objective-C有个重要的类型叫做id
意思是“指向一个未知/不确定的对象”类型
id myObject;
真正的所有的对象指针(如的NSString*)在运行时将像id一样对待
但是在编译的时候,如果你输入NSString*的东西,而不是id的,编译器可以帮助你
它可以发现bug,并建议用什么方法将是适合发给它的,等
如果你使用的id类型的东西,编译器不会有很大的帮助,因为它知道的并不多
弄清楚当消息在运行时发送,代码的执行被称为“动态绑定”


它安全么?
对待所有对象指针为“指向未知类型的”在运行时看似危险,对不对?
是什么阻止你发送消息到它不明白的一个对象?
什么都没有。并且如果你这样做你的程序会崩溃。天哪,Objective-C程序必须崩溃很多
不尽然
因为我们大多使用静态类型(如NSString*)并且编译器真的是很聪明


静态类型
NSString* s =@“x”;     //“静态”类型(如果s发送非NSString消息,编译器会发出警告)id obj = s;     //不是静态类型,但是完全合法;编译器不能捕获[obj rank]NSArray *a = obj;     //同样合法,但很明显会导致一些大麻烦!
编译器不会抱怨id和静态类型变量之间的分配

有时候,你正在默默地这样做。你已经这样做了!
- (int)match:(NSArray *)otherCards{...PlayingCard *otherCard = [otherCards firstObject];     //firstObject返回id! ...}

切勿使用“id *”的方式(这将意味着“一个指向对象的指针的指针”)


我们什么时候故意地使用这个危险的情况呢!
当我们想把不同类的对象混在同一个集合的时候(例如在一个NSArray)
当我们想在MVC中支持的“盲的,结构化”的通信(即委托)
而且,还有其它通用或盲的通信需求
但是为了让这些更安全,我们将使用两件事:内省和协议


内省
在运行时询问对象是什么类或者可以发送什么消息给它


协议
语法是“介于两者之间”id和静态类型
没有指定对象指向的类,但是指定了什么方法是它实现的
例如...
id <UIScrollViewDelegate> scrollViewDelegate;
我们将在下周讨论如何声明和使用协议



内省
所有继承自NSObject类的对象知道这些方法...
isKindOfClass:     返回BOOL:一个对象是否属于这个类的一种(包括继承)
isMemberOfClass:     返回BOOL:一个对象是否属于这个类的一种(不包括继承)
respondsToSelector:     返回BOOL:一个对象是否响应一个给定的方法
它可以在运行时计算这些问题的答案


给这些方法参数有点麻烦
类的测试方法用class
你通过发送类方法class到一个类来得到一个类
if ([obj isKindOfClass:[NSString class]]) {    NSString *s = [(NSString *)obj stringByAppendingString:@”xyzzy”];}


方法的测试方法用选择器(SEL)
特有的@selector( )指令,把一个方法名转化到一个选择器
if ([obj respondsToSelector:@selector(shoot)]) {    [obj shoot];} else if ([obj respondsToSelector:@selector(shootAt:)]) {    [obj shootAt:target];}


SEL是选择器的Objective-C“类型”
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];     //酷吧?[array makeObjectsPerformSelector:shootAtSelector withObject:target];     //目标是一个id

在UIButton中,- (void)addTarget:(id)anObject action:(SEL)action …; 
[button addTarget:self action:@selector(digitPressed:) ...]; 
0 0
原创粉丝点击