|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
NSStringNSArrayNSDictionary等这些工具在所有的框架里都会出现iOS大部分类都是继承自NSObject(我还没见过不是继承自NSObject的..)Ruby和Objective-C这两种言语看上往仿佛不着边际:一种是静态言语,另外一种则是静态言语;一种是注释型言语,另外一种是编译型言语;一种有简便的语法,另外一种则是有点冗杂的语法。从文雅的角度来看,Ruby仿佛更能给我们一种自在的编程体验,以是良多人都保持了Objective-C。
但这是一个不幸的笑话。Objective-C实在其实不像他人以为的那样是件紧身衣,它和Ruby一样都受Smalltalk影响,它具有良多Ruby开辟者都喜好的言语功效–静态办法查找、鸭子范例、开放的类和一般情形下高度可变的runtime等这些功效在Objective-C中一样存在,即便那些不着名的手艺也是一样。Objective-C的这些功效都要回功于它的IDE和编译器,但也是由于它们才使你不克不及自在地编写代码
可是等一下,怎样能说Objective-C是静态言语呢?岂非它不是创建在C言语的基本上?
你能够在Objective-C代码中包括任何C或C++的代码,但这不料味着Objective-C仅限于C或C++代码。Objective-C中一切成心思的类操纵和对象内省都是来自于一个叫Objective-CRuntime的工具。这个Objective-CRuntime能够和Ruby注释器相媲美。它包括了壮大的元编程里所必要的一切主要特征。
实在C言语和Ruby一样是撑持这些特征的,用property_getAttributes或method_getImplementation办法就可以将selector对应到详细完成(一个selector处置一个办法),并判别这个对象可否对这个selector做出反响,再遍历子类树。在Objective-C的浩瀚办法中,最主要的就是objc_msgSend办法,是它推进了使用中的每次动静发送。
动静的传送
Smalltalk才是实至名回的第一种面向对象言语,它用“从一个对象发送信息给另外一个对象”的新观点代替了“挪用函数”的旧观点,对前面的言语开展发生了深远的影响。
你能够在Ruby中经由过程如许写来完成动静的发送:
1
receiver.the_messageargument
Objective-C的完成体例和Ruby的差未几:
1
[receivertheMessage:argument];
这些动静完成了鸭子范例的体例,也就是说存眷的不是这个对象的范例或类自己,而是这个对象可否对一个动静做出反响。
发送动静真的长短常棒的事,可是只要当动静在传送数据时,它的代价才会被发扬地更年夜:
1
receiver.send(:the_message,argument)
和
1
2
[receiverperformSelector:@selector(theMessage:)
withObject:argument];
正如Ruby中办法必要symbol撑持一样,Objective-C中selector也必要string来撑持。(在Objective-C中没有symbol。)如许就能够让你经由过程静态的体例利用一个办法。你乃至能够经由过程NSSelectorFromString办法来利用string创立一个selector,并在一个对象里实行它。一样的,我们能够在Ruby中也能够创立一个string或symbol,并把传给Object#send办法。
固然,不管是哪一种言语,一旦你将一个动静发送给不克不及处置该动静的对象,那末默许情形下就会抛出一个非常,还会招致使用的溃散。
当你想在挪用一个办法前判别一下这个对象是不是可以实行这个办法,你能够用Ruby中的respond_to?办法来反省:
1
2
3
ifreceiver.respond_to?:the_message
receiver.the_messageargument
end
Objective-C中也有差未几的办法:
1
2
3
if([receiverrespondsToSelector:@selector(theMessage:)]){
[receivertheMessage:someThing];
}
变得愈来愈静态
假如你想在一个不克不及修正的类(像体系类)中增加你想要的办法,那末Objective-C里的category必定不会让你扫兴—很像Ruby中的“开放类”。
举个例子,假如你想将Rails中的to_sentence办法增加到NSArray类中,我们只必要对NSArray这个类举行扩大就行了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@interfaceNSArray(ToSentence)
-(NSString*)toSentence;
@end
@implementationNSArray(ToSentence)
-(NSString*)toSentence{
if(self.count==0)return@"";
if(self.count==1)return[selflastObject];
NSArray*allButLastObject=[selfsubarrayWithRange:NSMakeRange(0,self.count-1)];
NSString*result=[allButLastObjectcomponentsJoinedByString:@","];
BOOLshowComma=self.count>2;
result=[resultstringByAppendingFormat:@"%@and",showComma?@",":@""];
result=[resultstringByAppendingString:[selflastObject]];
returnresult;
}
@end
Category是在编译的时分将办法增加到程序中—让我们在runtime中静态捕获它们怎样?
有些动静能够嵌套数据,就像Rails的dynamicfinders。Ruby经由过程对method_missing和respond_to这两个办法的重写,先婚配形式,再将新办法的界说增加到这个对象中。
Objective-C中的流程是差未几,但我们不是重写doesNotRecognizeSelector:办法(相称于Ruby中的method_missing办法),而是在resolveClassMethod:办法中捕获Category增加的办法。假定我们有一个叫+findWhere:equals:的类办法,它能够失掉property的称号和值,那末经由过程正则表达式就能够很简单完成找到property的名字,并经由过程block来注册这个selector。
<p>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+(BOOL)resolveClassMethod:(SEL)sel{
NSString*selectorName=NSStringFromSelector(sel);
NSRegularExpression*regex=[NSRegularExpressionregularExpressionWithPattern:@"^findWhere(w+)Equals:$"options:0error:nil];
NSTextCheckingResult*result=[regexfirstMatchInString:selectorNameoptions:0range:NSMakeRange(0,selectorName.length)];
if(result){
NSRangepropertyNameRange=[resultrangeAtIndex:1];
NSString*propertyName=[selectorNamesubstringWithRange:propertyNameRange];
IMPimplementation=imp_implementationWithBlock((id)^(idself,idarg1){
return[selffindWhere:propertyNameequals:arg1];
});
ClassmetaClass=object_getClass(self);
<p>class_addMethod(metaClass,sel,implementation, |
|