在我们进一步了解整个运行时之前,需要先了解一些接下来出现的术语。截至目前Mac和iPhone的开发者关心的有两个运行时:Modern Runtime & Legacy Runtime 。前者覆盖所有64位Mac OS X 的app和所有的iOS app,后者覆盖其余的(全部的Mac OS X 32位 App)。关于方法,这里有两种基本类型的方法,一种是实例方法(’-‘开头, 例如-(void)doFoo,作用于对象实例),另一种是类方法(’+‘开头,例如+(id)alloc)。方法就像C语言中的函数类似,一段代码完成一个小的任务,如下:
-(NSString*)movieTitle{return@"Futurama: Into the Wild Green Yonder";}
#import < Foundation/Foundation.h>
@interfaceMyObject : NSObject{NSString*aString;}@property(retain)NSString*aString;@end@implementationMyObject-(id)init{if(self=[superinit]){[selfsetAString:nil];}returnself;}@synthesizeaString;@endintmain(intargc,constchar*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];idobj1=[NSMutableArrayalloc];idobj2=[[NSMutableArrayalloc]init];idobj3=[NSArrayalloc];idobj4=[[NSArrayalloc]initWithObjects:@"Hello",nil];NSLog(@"obj1 class is %@",NSStringFromClass([obj1class]));NSLog(@"obj2 class is %@",NSStringFromClass([obj2class]));NSLog(@"obj3 class is %@",NSStringFromClass([obj3class]));NSLog(@"obj4 class is %@",NSStringFromClass([obj4class]));idobj5=[MyObjectalloc];idobj6=[[MyObjectalloc]init];NSLog(@"obj5 class is %@",NSStringFromClass([obj5class]));NSLog(@"obj6 class is %@",NSStringFromClass([obj6class]));[pooldrain];return0;}
我们通过目标对象的isa指针来查询该类或者其继承体系中的父类是否能够响应 @selector(printMessageWithString:)。假设我们在类的派发表或者它的cache中找到了该selector,然后我们通过该函数指针来执行该方法。因此我们可以了解objc_msgSend()方法永远不会返回,它从执行开始,通过指针查找到你的方法执行,然后是你的方法执行之后返回,因此看起来好像objc_msgSend()方法返回似的。Bill Bumgarner对此过程有更多的细节探索(Part 1, Part 2 & Part 3)。
//declare C function pointer
int(computeNum*)(id,SEL,int);//methodForSelector is COCOA & not ObjC Runtime
//gets the same function pointer objc_msgSend gets
computeNum=(int(*)(id,SEL,int))[targetmethodForSelector:@selector(doComputeWithNum:)];//execute the C function pointer returned by the runtime
computeNum(obj,@selector(doComputeWithNum:),aNum);
我们的代码就无法正常运行,我们自定义对象中的内容被擦出了,因为NSObject增加了两个成员变量,而MyObject类成员变量布局在编译时已经确定,有两个成员变量和基类的内存区域重叠。唯一能够阻止这个发生的就是Apple维持它之前的布局策略,但是一旦这样他们的框架就无法再往前发展了,因为它们的变量布局已经固化了。在这种情况下(也就是fragile ivars)你只能通过重新编译这些继承自Apple类的类来使得代码得以兼容。那在 non fragile ivars下会发生什么呢?
最近引入Mac OS X 10.6系统有一个特性称作“关联引用”。Objective-C不像其他语言,其原生不支持向对象动态添加变量。所以到目前为止,你都必须要费很大的劲,编译整个体系结构来假装自己向类中添加一个变量。不过在Mac OS X 10.6系统中,Objective-C 运行时原生支持(动态添加变量)。如果我们想向每一个已经存在的类中添加一个变量,例如向NSView类中添加,如下所示:
/* Associative References *//**
* Policies related to associative references.
* These are options to objc_setAssociatedObject()
*/enum{OBJC_ASSOCIATION_ASSIGN=0,/**< Specifies a weak reference to the associated object. */OBJC_ASSOCIATION_RETAIN_NONATOMIC=1,/**< Specifies a strong reference to the associated object.
* The association is not made atomically. */OBJC_ASSOCIATION_COPY_NONATOMIC=3,/**< Specifies that the associated object is copied.
* The association is not made atomically. */OBJC_ASSOCIATION_RETAIN=01401,/**< Specifies a strong reference to the associated object.
* The association is made atomically. */OBJC_ASSOCIATION_COPY=01403/**< Specifies that the associated object is copied.
* The association is made atomically. */};
/***********************************************************************
* vtable dispatch
*
* Every class gets a vtable pointer. The vtable is an array of IMPs.
* The selectors represented in the vtable are the same for all classes
* (i.e. no class has a bigger or smaller vtable).
* Each vtable index has an associated trampoline which dispatches to
* the IMP at that index for the receiver class's vtable (after
* checking for NULL). Dispatch fixup uses these trampolines instead
* of objc_msgSend.
* Fragility: The vtable size and list of selectors is chosen at launch
* time. No compiler-generated code depends on any particular vtable
* configuration, or even the use of vtable dispatch at all.
* Memory size: If a class's vtable is identical to its superclass's
* (i.e. the class overrides none of the vtable selectors), then
* the class points directly to its superclass's vtable. This means
* selectors to be included in the vtable should be chosen so they are
* (1) frequently called, but (2) not too frequently overridden. In
* particular, -dealloc is a bad choice.
* Forwarding: If a class doesn't implement some vtable selector, that
* selector's IMP is set to objc_msgSend in that class's vtable.
* +initialize: Each class keeps the default vtable (which always
* redirects to objc_msgSend) until its +initialize is completed.
* Otherwise, the first message to a class could be a vtable dispatch,
* and the vtable trampoline doesn't include +initialize checking.
* Changes: Categories, addMethod, and setImplementation all force vtable
* reconstruction for the class and all of its subclasses, if the
* vtable selectors are affected.
**********************************************************************/
题目:257. Binary Tree Paths # Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 / 2 3 5 All root-to-leaf paths are: [“1->2->5”, “1->3”]
题目: # Given a string s consists of upper/lower-case alphabets and empty space characters ’ ‘, return the length of last word in the string. If the last word does not exist, return 0. Note: A word is defined as a character sequence consists of non-space characters only. For example, Given s = “Hello World”, return 5.