[飘飘白云]&深入浅出 Cocoa 之消息
深入浅出 Cocoa 之消息
罗朝辉(http://blog.csdn.net/kesalin)
转载请注明出处
在入门级别的ObjC 教程中,我们常对从C++或Java 或其他面向对象语言转过来的程序员说,ObjC 中的方法调用(ObjC中的术语为消息)跟其他语言中的方法调用差不多,只是形式有些不同而已。
譬如C++ 中的:
|
Bird * aBird = new Bird(); aBird->fly(); |
在ObjC 中则如下:
|
Bird * aBird = [[Bird alloc] init]; [aBird fly]; |
初看起来,好像只是书写形式不同而已,实则差异大矣。C++中的方法调用可能是动态的,也可能是静态的;而ObjC中的消息都为动态的。下文将详细介绍为什么是动态的,以及编译器在这背后做了些什么事情。
要说清楚消息这个话题,我们必须先来了解三个概念Class, SEL, IMP,它们在objc/objc.h 中定义:
|
typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id;
typedef struct objc_selector *SEL; typedef id (*IMP)(id, SEL, ...); |
Class 的含义
Class 被定义为一个指向 objc_class的结构体指针,这个结构体表示每一个类的类结构。而 objc_class 在objc/objc_class.h中定义如下:
|
struct objc_class { struct objc_class * isa; struct objc_class * super_class; /*父类*/ const char *name; /*类名字*/ long version; /*版本信息*/ long info; /*类信息*/ long instance_size; /*实例大小*/ struct objc_ivar_list *ivars; /*实例参数链表*/ struct objc_method_list **methodLists; /*方法链表*/ struct objc_cache *cache; /*方法缓存*/ struct objc_protocol_list *protocols; /*协议链表*/ }; |
由此可见,Class 是指向类结构体的指针,该类结构体含有一个指向其父类类结构的指针,该类方法的链表,该类方法的缓存以及其他必要信息。
NSObject 的class 方法就返回这样一个指向其类结构的指针。每一个类实例对象的第一个实例变量是一个指向该对象的类结构的指针,叫做isa。通过该指针,对象可以访问它对应的类以及相应的父类。如图一所示:

如图一所示,圆形所代表的实例对象的第一个实例变量为 isa,它指向该类的类结构 The object’s class。而该类结构有一个指向其父类类结构的指针superclass, 以及自身消息名称(selector)/实现地址(address)的方法链表。
方法的含义:
注意这里所说的方法链表里面存储的是Method 类型的。图一中selector 就是指 Method的 SEL, address就是指Method的 IMP。 Method 在头文件 objc_class.h中定义如下:
|
typedef struct objc_method *Method; typedef struct objc_ method { SEL method_name; char *method_types; IMP method_imp; }; |
一个方法 Method,其包含一个方法选标 SEL – 表示该方法的名称,一个types – 表示该方法参数的类型,一个 IMP - 指向该方法的具体实现的函数指针。
SEL 的含义:
在前面我们看到方法选标 SEL 的定义为:
typedef struct objc_selector *SEL;
它是一个指向 objc_selector 指针,表示方法的名字/签名。如下所示,打印出 selector。
|
-(NSInteger)maxIn:(NSInteger)a theOther:(NSInteger)b { return (a > b) ? a : b; }
NSLog(@"SEL=%s", @selector(maxIn:theOther:));
输出:SEL=maxIn:theOther: |
不同的类可以拥有相同的 selector,这个没有问题,因为不同类的实例对象performSelector相同的 selector 时,会在各自的消息选标(selector)/实现地址(address) 方法链表中根据 selector 去查找具体的方法实现IMP, 然后用这个方法实现去执行具体的实现代码。这是一个动态绑定的过程,在编译的时候,我们不知道最终会执行哪一些代码,只有在执行的时候,通过selector去查询,我们才能确定具体的执行代码。
IMP 的含义:
在前面我们也看到 IMP 的定义为:
typedef id (*IMP)(id, SEL, ...);
根据前面id 的定义,我们知道 id是一个指向 objc_object 结构体的指针,该结构体只有一个成员isa,所以任何继承自 NSObject 的类对象都可以用id 来指代,因为 NSObject 的第一个成员实例就是isa。
至此,我们就很清楚地知道 IMP 的含义:IMP 是一个函数指针,这个被指向的函数包含一个接收消息的对象id(self 指针), 调用方法的选标 SEL (方法名),以及不定个数的方法参数,并返回一个id。也就是说 IMP 是消息最终调用的执行代码,是方法真正的实现代码 。我们可以像在C语言里面一样使用这个函数指针。
NSObject 类中的methodForSelector:方法就是这样一个获取指向方法实现IMP 的指针,methodForSelector:返回的指针和赋值的变量类型必须完全一致,包括方法的参数类型和返回值类型。
下面的例子展示了怎么使用指针来调用setFilled:的方法实现:
|
void (*setter)(id, SEL, BOOL); int i;
setter = (void(*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)];
for (i = 0; i < 1000; i++) setter(targetList[i], @selector(setFilled:), YES); |
使用methodForSelector:来避免动态绑定将减少大部分消息的开销,但是这只有在指定的消息被重复发送很多次时才有意义,例如上面的for循环。
注意,methodForSelector:是Cocoa运行时系统的提供的功能,而不是Objective-C语言本身的功能。
消息调用过程:
至此我们对ObjC 中的消息应该有个大致思路了:示例
|
Bird * aBird = [[Bird alloc] init]; [aBird fly]; |
中对 fly 的调用,编译器通过插入一些代码,将之转换为对方法具体实现IMP的调用,这个 IMP是通过在 Bird 的类结构中的方法链表中查找名称为fly 的 选标SEL 对应的具体方法实现找到的。
上面的思路还有一些没有提及的话题,比如说编译器插入了什么代码,如果在方法链表中没有找到对应的 IMP又会如何,这些话题在下面展开。
消息函数 obj_msgSend:
编译器会将消息转换为对消息函数 objc_msgSend的调用,该函数有两个主要的参数:消息接收者id 和消息对应的方法选标 SEL, 同时接收消息中的任意参数:
id objc_msgSend(id theReceiver, SELtheSelector, ...)
如上面的消息 [aBird fly]会被转换为如下形式的函数调用:
objc_msgSend(aBird, @selector(fly));
该消息函数做了动态绑定所需要的一切工作:
1,它首先找到 SEL 对应的方法实现 IMP。因为不同的类对同一方法可能会有不同的实现,所以找到的方法实现依赖于消息接收者的类型。
2, 然后将消息接收者对象(指向消息接收者对象的指针)以及方法中指定的参数传递给方法实现 IMP。
3, 最后,将方法实现的返回值作为该函数的返回值返回。
编译器会自动插入调用该消息函数objc_msgSend的代码,我们无须在代码中显示调用该消息函数。当objc_msgSend找到方法对应的实现时,它将直接调用该方法实现,并将消息中所有的参数都传递给方法实现,同时,它还将传递两个隐藏的参数:消息的接收者以及方法名称 SEL。这些参数帮助方法实现获得了消息表达式的信息。它们被认为是”隐藏“的是因为它们并没有在定义方法的源代码中声明,而是在代码编译时是插入方法的实现中的。
尽管这些参数没有被显示声明,但在源代码中仍然可以引用它们(就象可以引用消息接收者对象的实例变量一样)。在方法中可以通过self来引用消息接收者对象,通过选标_cmd来引用方法本身。在下面的例子中,_cmd 指的是strange方法,self指的收到strange消息的对象。
|
- strange { id target = getTheReceiver(); SEL method = getTheMethod();
if (target == self || mothod == _cmd) return nil;
return [target performSelector:method]; } |
在这两个参数中,self更有用一些。实际上,它是在方法实现中访问消息接收者对象的实例变量的途径。
查找 IMP 的过程:
前面说了,objc_msgSend 会根据方法选标 SEL 在类结构的方法列表中查找方法实现IMP。这里头有一些文章,我们在前面的类结构中也看到有一个叫objc_cache *cache 的成员,这个缓存为提高效率而存在的。每个类都有一个独立的缓存,同时包括继承的方法和在该类中定义的方法。。
下面来剖析一段苹果官方运行时源码:
-
static Method look_up_method(Class cls, SEL sel,
-
BOOL withCache, BOOL withResolver)
-
{
-
Method meth = NULL;
-
-
if (withCache) {
-
meth = _cache_getMethod(cls, sel, &_objc_msgForward_internal);
-
if (meth == (Method)1) {
-
// Cache contains forward:: . Stop searching.
-
return NULL;
-
}
-
}
-
-
if (!meth) meth = _class_getMethod(cls, sel);
-
-
if (!meth && withResolver) meth = _class_resolveMethod(cls, sel);
-
-
return meth;
-
}
通过分析上面的代码,可以看到,查找时:
1,首先去该类的方法 cache中查找,如果找到了就返回它;
2,如果没有找到,就去该类的方法列表中查找。如果在该类的方法列表中找到了,则将 IMP返回,并将它加入cache中缓存起来。根据最近使用原则,这个方法再次调用的可能性很大,缓存起来可以节省下次调用再次查找的开销。3,3,如果在该类的方法列表中没找到对应的 IMP,在通过该类结构中的 super_class指针在其父类结构的方法列表中去查找,直到在某个父类的方法列表中找到对应的IMP,返回它,并加入cache中;
4,如果在自身以及所有父类的方法列表中都没有找到对应的 IMP,则看是不是可以进行动态方法决议(后面有专文讲述这个话题);
5,如果动态方法决议没能解决问题,进入下面要讲的消息转发流程。
便利函数:
我们可以通过NSObject的一些方法获取运行时信息或动态执行一些消息:
class 返回对象的类;
isKindOfClass 和 isMemberOfClass检查对象是否在指定的类继承体系中;
respondsToSelector 检查对象能否相应指定的消息;
conformsToProtocol 检查对象是否实现了指定协议类的方法;
methodForSelector 返回指定方法实现的地址。
performSelector:withObject 执行SEL 所指代的方法。
消息转发:
通常,给一个对象发送它不能处理的消息会得到出错提示,然而,Objective-C运行时系统在抛出错误之前,会给消息接收对象发送一条特别的消息forwardInvocation 来通知该对象,该消息的唯一参数是个NSInvocation类型的对象——该对象封装了原始的消息和消息的参数。
我们可以实现forwardInvocation:方法来对不能处理的消息做一些默认的处理,也可以将消息转发给其他对象来处理,而不抛出错误。
关于消息转发的作用,可以考虑如下情景:假设,我们需要设计一个能够响应negotiate消息的对象,并且能够包括其它类型的对象对消息的响应。 通过在negotiate方法的实现中将negotiate消息转发给其它的对象来很容易的达到这一目的。
更进一步,假设我们希望我们的对象和另外一个类的对象对negotiate的消息的响应完全一致。一种可能的方式就是让我们的类继承其它类的方法实现。 然后,有时候这种方式不可行,因为我们的类和其它类可能需要在不同的继承体系中响应negotiate消息。
虽然我们的类无法继承其它类的negotiate方法,但我们仍然可以提供一个方法实现,这个方法实现只是简单的将negotiate消息转发给其他类的对象,就好像从其它类那儿“借”来的现一样。如下所示:
|
- negotiate { if ([someOtherObject respondsToSelector:@selector(negotiate)]) return [someOtherObject negotiate];
return self; } |
这种方式显得有欠灵活,特别是有很多消息都希望传递给其它对象时,我们就必须为每一种消息提供方法实现。此外,这种方式不能处理未知的消息。当我们写下代码时,所有我们需要转发的消息的集合都必须确定。然而,实际上,这个集合会随着运行时事件的发生,新方法或者新类的定义而变化。
forwardInvocation:消息给这个问题提供了一个更特别的,动态的解决方案:当一个对象由于没有相应的方法实现而无法响应某消息时,运行时系统将通过forwardInvocation:消息通知该对象。每个对象都从NSObject类中继承了forwardInvocation:方法。然而,NSObject中的方法实现只是简单地调用了doesNotRecognizeSelector:。通过实现我们自己的forwardInvocation:方法,我们可以在该方法实现中将消息转发给其它对象。
要转发消息给其它对象,forwardInvocation:方法所必须做的有:
1,决定将消息转发给谁,并且
2,将消息和原来的参数一块转发出去。
消息可以通过invokeWithTarget:方法来转发:
|
- (void) forwardInvocation:(NSInvocation *)anInvocation { if ([someOtherObject respondsToSelector:[anInvocation selector]]) [anInvocation invokeWithTarget:someOtherObject];
else [super forwardInvocation:anInvocation]; } |
转发消息后的返回值将返回给原来的消息发送者。您可以将返回任何类型的返回值,包括: id,结构体,浮点数等。
forwardInvocation:方法就像一个不能识别的消息的分发中心,将这些消息转发给不同接收对象。或者它也可以象一个运输站将所有的消息都发送给同一个接收对象。它可以将一个消息翻译成另外一个消息,或者简单的"吃掉“某些消息,因此没有响应也没有错误。forwardInvocation:方法也可以对不同的消息提供同样的响应,这一切都取决于方法的具体实现。该方法所提供是将不同的对象链接到消息链的能力。
注意: forwardInvocation:方法只有在消息接收对象中无法正常响应消息时才会被调用。 所以,如果我们希望一个对象将 negotiate 消息转发给其它对象,则这个对象不能有negotiate 方法,也不能在动态方法决议过程中为之提供实现。否则,forwardInvocation:将不可能会被调用。
参考资料:
Objective-CRuntime Reference:
Objective-C Runtime Programming Guide:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html
pcliuguangtao: 对于 forwardInvocation 的提出想来是OC 的Creaters对以前遇到调用方法错误直接出现异常的改善方式。让programmer可以handle更多的异常。(5年前#4楼)0
才才小包: 你好,今天复习cocoa相关知识的时候,突然想到一个问题,object-c中,@interface这个定义在哪里可以找到?平常只知道@interface是用来声明一个类的,但想深入了解下。谢谢。(5年前#3楼)0
才才小包: struct objc_class { Class isa; // 少了一个isa? Class super_class;(5年前#2楼)收起回复0-
才才小包回复 飘飘白云: 不客气。^-^,还是应该坚持看官方文档。受教了。(5年前)0
飘飘白云回复 才才小包: 谢谢指出。该结构定义在:http://www.opensource.apple.com/source/objc4/objc4-208/runtime/objc-class.h(5年前)0
sbsbsbbsbsbsbsbsb: 很不错,objective c底层的一些东西,我也想学习下这方面底层的东西,请lz推荐点资料啊。(7年前#1楼)查看回复(1)0
RxSwift Runtime分析(利用OC消息转发实现IOS消息拦截)<原理同ReactiveCocoa>
阅读数 890
简要介绍:这是一篇介绍IOS消息拦截的文章,来源于对RxSwift源码的分析,其原理是利用Object-c的消息转发(forwardInvocation:)来实现(ReactiveCocoa中也是这个... 博文 来自: cleven
[Cocoa]_[初级]_[文件拖放操作]
阅读数 1703
场景:支持所有类别的文件拖放(从外部直接拖文件到程序中)实例:DragDropView.h#import@protocolDragDropViewDelegate;@interfaceDragDrop... 博文 来自: moqj_123的专栏
为什么我们要用cocoapods?
阅读数 524
cocoapods:专门用来管理第三方库的在没有cocoapods之前导入AFN框架有时候需要导入一些依赖库,所以很头疼,用cocoapods导一个框架会自动导所有依赖框架.导入CocoaPods的步... 博文 来自: 梁森的博客
ReactiveCocoa入门教程一
阅读数 759
ReactiveCocoa框架是Github开源的一个应用于iOS和MacOS开发的新框架,使用它能大幅度改变在“苹果体系”里面的编程习惯。所以如果是有一些iOS编程经验的人来看这个框架的使用方法可能... 博文 来自: Ek的博客
Cocoa 框架 For iOS(一) 框架的介绍,Objectivie-C运行时能力的解析等
阅读数 6万+
Cocoa框架是iOS应用程序的基础,了解Cocoa框架,对开发iOS应用有很大的帮助。1、Cocoa是什么?Cocoa是OSX和iOS操作系统的程序的运行环境。是什么因素使一个程序成为Cocoa程序... 博文 来自: 知行合一
初学cocoa开发:带你走入不一样的世界
阅读数 5627
最近由于项目需求,特意研究了一下mac端app的相关开发,一开始就想着在网上搜搜资料,后来才发现网上资料的太少了!也曾在cocoaChina那个osx开发那个论坛上混了好久,但是效果一直不怎么好,里面... 博文 来自: u012890071的专栏
[Cocoa]深入浅出 Cocoa 之 Plugin - 罗朝辉(飘飘白云) - CSDN博客
11-9
[Cocoa]深入浅出Cocoa之消息(一) - liping_csdn的专栏 10-30 208 深入浅...[Cocoa]深入浅出 Cocoa 之Bonjour 网络编程 - 罗朝辉(飘飘白云)(关注程序语言、...
[Cocoa]深入浅出 Cocoa 之 Framework - 罗朝辉(飘飘白..._CSDN博客
3-8
iOS 开发 深入浅出Rumtime运行时之消息发送机制详解
阅读数 2398
在Objective-C中,使用对象进行方法调用是一个消息发送的过程(Objective-C采用“动态绑定机制”,所以所要调用的方法直到运行期才能确定)。方法在调用时,系统会查看这个对象能否接收这个消... 博文 来自: IOS开发工程师--周玉的博客
深入浅出Cocoa之类与对象 - 罗朝辉(飘飘白云) - CSDN博客
11-28
来自: 罗朝辉(飘飘白云) Cocoa是什么??? - 王中...[Cocoa]深入浅出Cocoa之消息(一) - liping_csdn的...
...Method Resolution) - 罗朝辉(飘飘白云) - CSDN博客
11-21
[深入浅出Cocoa]之消息(二)-详解动态方法决议(Dynamic Method Resolution)罗朝辉 (http://blog.csdn.net/kesalin/)本文遵循“署名-非商业用途-保持一致”创作...
深入浅出Cocoa教程
04-17[Cocoa]深入浅出Cocoa之 Method Swizzling - 罗朝辉(飘..._CSDN博客
10-6
[Cocoa]深入浅出Cocoa之 Method Swizzling 罗朝辉(http://blog.csdn.net/kesalin) CC许可,转载请注明出处 在前文深入浅出Cocoa之消息中,我简要介绍了ObjC 中消...
...Cocoa]iOS网络编程之Socket - 罗朝辉(飘飘白云) - CSDN博客...
10-30
罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 更多Cocoa 开发文章,敬请访问《深入浅出Cocoa》 CSDN专栏:http://blog.csdn.net/column/detail...
[Cocoa]深入浅出Cocoa之消息
阅读数 397
[Cocoa]深入浅出Cocoa之消息深入浅出Cocoa之消息 罗朝辉(http://www.cnblogs.com/kesalin/)本文遵循“署名-非商业用途-保持一致”创作公用协议 在入门级别... 博文 来自: nb_tpl的专栏
Cocoa处理消息的方法- Delegate
阅读数 515
在Mac,Windows或者Linux平台上,所有的GUI程序都可以称作消息驱动的,就是说整个应用程序就是在处理消息的循环中进行的,用户的操作或者系统发送的一些通知都会被送到应用程序的消息处理循环中,... 博文 来自: yohohohoho的专栏
...iOS网络编程之CFNetwork - 罗朝辉(飘飘白云) - CSDN博客...
11-28
来自: 罗朝辉(飘飘白云) [Cocoa]深入浅出Cocoa之Bonjour网络编程 - yiyunhzy的专栏 08-26 708 [Cocoa]深入浅出Cocoa之Bonjour网络编程 深入浅出Cocoa之Bonjour...
...出Cocoa]详解键值观察(KVO)及其实现机理 - 罗朝辉(飘飘白云) -...
11-19
[深入浅出Cocoa]详解键值观察(KVO)及其实现机理 罗朝辉 (http://blog.csdn...飘飘白云 博客专家 关注 原创 195 粉丝 2742 喜欢 482 评论 642 ...
[Cocoa]深入浅出Cocoa之消息(一)
阅读数 221
深入浅出Cocoa之消息 罗朝辉(http://www.cnblogs.com/kesalin/)本文遵循“署名-非商业用途-保持一致”创作公用协议 在入门级别的ObjC教程中,我们常对从C++或J... 博文 来自: liping_csdn的专栏
[Cocoa]XCode的一些调试技巧 - 罗朝辉(飘飘白云) - CSDN博客
11-22
[Cocoa]XCode的一些调试技巧2012年01月31日 16:02:21 飘飘白云 阅读数:30235 所属专栏: 深入浅出Cocoa 版权声明:本文为博主原创文章,未经博主允许不得转载...
Apple Mac cocoa入门级教程- HelloWorld!
阅读数 1万+
cocoa教程1-HelloWorld!来源:www.CocoaDev.cn首先,使用Xcode来创建一个新的project.这里假设你已经安装了开发工具.如果还没有,可以用开发光盘或者系统光盘安装,... 博文 来自: 发芽的石头
【Cocoa(mac) Application 开发系列之一】创建第一个application—计算器
阅读数 1万+
本站文章均为 李华明Himi 原创,转载务必在明显处注明:转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/mac-cocoa-application/89... 博文 来自: 李华明Himi
Cocoapods系列教程(一)——入门
阅读数 813
原文地址:[Cocoapods系列教程(一)](http://www.pluto-y.com/cocoapods-getting-stared/)[Cocoapods](https://cocoapo... 博文 来自: Pluto Y的博客
深入浅出 Cocoa 之 Core Data(1)框架讲解
阅读数 867
罗朝辉(http://www.cppblog.com/kesalin)CC许可,转载请注明出处 1、@importurl(http://www.cppblog.com/cutesoft_client... 博文 来自: 在路上
【iOS】深入浅出 Cocoa 之消息
阅读数 736
深入浅出 Cocoa 之消息 罗朝辉(http://blog.csdn.net/kesalin)在入门级别的ObjC教程中,我们常对从C++或Java或其他面向对象语言转过来的程序员说,ObjC中的... 博文 来自: 省
[Cocoa]深入浅出Cocoa系列
阅读数 453
转自:深入浅出Cocoa系列罗朝辉(http://www.cnblogs.com/kesalin/)本文遵循“署名-非商业用途-保持一致”创作公用协议 这是本人在研究 Cocoa 开发过程中写过的一些... 博文 来自: martin_liang的专栏
[Cocoa]深入浅出Cocoa之类与对象
阅读数 753
最近打算写一些ObjC中比较底层的东西,尤其是runtime相关的。苹果已经将ObjCruntime代码开源了,我们可以从:http://opensource.apple.com/source/obj... 博文 来自: chaoyuan899的专栏
Android OpenGLES2.0(十二)——FBO离屏渲染
阅读数 1万+
之前的博客我们所做的示例都是直接渲染到屏幕上的,如果我们并不需要渲染到屏幕上,也就是离屏渲染,该怎么做呢?FBO离屏渲染是一个很好的选择。在这篇博客中,我们将以渲染摄像头数据为例,使用FBO进行离屏渲... 博文 来自: 湖广午王
[Cocoa]处理消息的方法-Delegate
阅读数 1478
原文链接:http://www.cocoachina.com/b/?p=124我们上次演示的程序在关掉了应用程序的窗口之后,应用程序并没有真正的退出,现在我们就来完成这个任务。在Mac,Windows... 博文 来自: u011513212
ReactiveCocoa入门教程二
阅读数 446
上一篇文章我们使用ReactiveCocoa搭建了一个简单的登录页面,这一次我们来搭建注册页面。本篇代码在https://github.com/Ekulelu/ReactiveCocoaRegiste... 博文 来自: Ek的博客
ios Cocoa error 4097
阅读数 1800
[UIKeyboardInputManagerClienthandleError:forRequest:]willretrysendinghandleKeyboardInput:keyboardSta... 博文 来自: poijm
[Cocoa]深入浅出Cocoa 之动态创建类
阅读数 4135
在前文《深入浅出Cocoa之类与对象》一文中,我已经详细介绍了ObjC中的Class与Object的概念,今天我们来如何在运行 时 动态创建类。下面这个函数就是应用前面讲到的Class,MetaCla... 博文 来自: huifeidexin_1的专栏
[Cocoa]深入浅出Cocoa之Bonjour网络编程
阅读数 728
[Cocoa]深入浅出Cocoa之Bonjour网络编程深入浅出Cocoa之Bonjour网络编程罗朝辉(http://www.cnblogs.com/kesalin/)本文遵循“署名-非商业用途-保... 博文 来自: yiyunhzy的专栏
[Cocoa]深入浅出 Cocoa 之 Bonjour 网络编程
阅读数 1万+
深入浅出Cocoa之Bonjour网络编程罗朝辉(http://blog.csdn.net/kesalin/)CC许可,转载请注明出处本文高度参考自 Tutorial:NetworkingandBon... 博文 来自: 罗朝辉(飘飘白云)
Cocoa programming for mac os x 3rd 翻译版高清晰版(仅17章).pdf
04-17关于cocoa框架,你所要知道的一切(苹果官方文档,cocoa框架核心竞争力,必须收藏!)
阅读数 1707
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Accessib... 博文 来自: 移动应用开发技术专栏—by 阿尘
ios runtime之深入浅出 Cocoa 消息
阅读数 478
在入门级别的ObjC教程中,我们常对从C++或Java或其他面向对象语言转过来的程序员说,ObjC中的方法调用(ObjC中的术语为消息)跟其他语言中的方法调用差不多,只是形式有些不同而已。 譬如C++... 博文 来自: hanmingsa的专栏
[Cocoa]_[初级]_[Cocoa入门级界面开发之界面初级程序编辑的步骤和实现方法]
阅读数 1689
1.打开Xcode,创建一个项目,选择CocoaApplication,点击next,Class:命名TestCocoaApplication.默认选择,直到完成为止。2.左边的下拉框中选择MainM... 博文 来自: moqj_123的专栏
[Cocoa]_[画直线、矩形、文字]
阅读数 2632
总结Cocoa下画直线、矩形、文字的方法,在界面开发种经常会遇到。1.画直线,有两种方法。(1)把直线看成是一个高度较小的的矩形//(1)直线的本质是一个高度较小的矩形NSRectrect5=NSMa... 博文 来自: yepeng2014的专栏
[Cocoa]_[初级]_[几种在Cocoa应用程序经常用到的几种信息提示框]
阅读数 753
1.Yes和No类型的提示框intchoice=NSRunAlertPanel(@"Confirm",@"Areyousureyouwanttodeleteallform?",@"No",@"Yes"... 博文 来自: moqj_123的专栏
COCOA设计模式 完整版 中文版
04-13cocoa、mac打开文件和文件夹的代码
阅读数 2529
【原文地址:cocoa、mac打开文件和文件夹的代码】【作者:chenghxc】Mac项目开发中经常会进行文件操作,比较常用的是打开文件和文件夹,虽然很简单的一段代码,对于刚学Mac开发还是要多做些记... 博文 来自: chenghxc
在Cocoa App中展示自定义的对话框
阅读数 4716
继上一篇Toolbar的使用,我想在点击工具栏item的时候,下拉一个对话框。官方文档见此:点击打开链接通过创建alert:NSAlert*alert=[[[NSAlertalloc]init]aut... 博文 来自: JasonLee的专栏
Cocoa Programming for OS X 5th.epub MAC OSX桌面开发指南第五版
03-12Cocoa夜未央第四期-老jar
11-25iOS系统框架介绍--CocoaTouch层
阅读数 2252
iOS操作系统是iPhone、iPodtouch以及iPad设备的核心。作为一名iOS开发工程师,很有必要去对iOS平台进行一定的了解,构建iOS平台的知识与MacOSX系统同出一辙,iOS平台的许多... 博文 来自: keyZhang的专栏
Java设计模式学习06——静态代理与动态代理
阅读数 1万+
一、代理模式为某个对象提供一个代理,从而控制这个代理的访问。代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代。代理类负责请求的预处理、过滤、将请求分配给委托... 博文 来自: 小小本科生成长之路
强连通分量及缩点tarjan算法解析
阅读数 55万+
强连通分量: 简言之 就是找环(每条边只走一次,两两可达) 孤立的一个点也是一个连通分量 使用tarjan算法 在嵌套的多个环中优先得到最大环( 最小环就是每个孤立点) 定义: int Ti... 博文 来自: 九野的博客
VirtualBox COM获取对象失败
阅读数 3万+
错误详情 1. 先来看看错误详情 获取 VirtualBox COM 对象失败.应用程序将被中断.Failed to instantiate CLSID_VirtualBox ... 博文 来自: 多点折腾少点抱怨
jquery/js实现一个网页同时调用多个倒计时(最新的)
阅读数 41万+
jquery/js实现一个网页同时调用多个倒计时(最新的) 最近需要网页添加多个倒计时. 查阅网络,基本上都是千遍一律的不好用. 自己按需写了个.希望对大家有用. 有用请赞一个哦! //js ... 博文 来自: Websites
Java设计模式14——中介者(Mediator)模式
阅读数 3767
一、定义用一个中介对象封装一系列对象的交互,中介者是多个对象不需要显示的相互作用,而且可以独立的改变他们的交互。二、举例通过上述定义可能不好理解,下面举一个例子,假如在一个没有总经理的公司中,有三个部... 博文 来自: 小小本科生成长之路
R语言逻辑回归、ROC曲线和十折交叉验证
阅读数 4万+
自己整理编写的逻辑回归模板,作为学习笔记记录分享。数据集用的是14个自变量Xi,一个因变量Y的australian数据集。 1. 测试集和训练集3、7分组 australian ... 博文 来自: Tiaaaaa的博客
Particle Filter Tutorial 粒子滤波:从推导到应用(一)
阅读数 5万+
前言: 博主在自主学习粒子滤波的过程中,看了很多文献或博客,不知道是看文献时粗心大意还是悟性太低,看着那么多公式,总是无法把握住粒子滤波的思路,也无法将理论和实践对应起来。比如:理论推导过... 博文 来自: 知行合一
关于SpringBoot bean无法注入的问题(与文件包位置有关)
阅读数 14万+
问题场景描述整个项目通过Maven构建,大致结构如下: 核心Spring框架一个module spring-boot-base service和dao一个module server-core 提供系统... 博文 来自: 开发随笔
博主专栏
-
文章数:26 篇 访问量:61万+
-
文章数:9 篇 访问量:21万+
个人分类
最新评论
- 使用System.arraycop...
bigyuu:挺清晰的
- [OpenGL ES 07-1]光...
litterbug23:还是没有讲清,物体的贴图与光照是怎么混合的呢? 物体本身的颜色,物体贴图颜色,最终应该怎么与光照颜色混合? 看了怎么多篇文章,没有一篇是把这个问题讲清楚的。每个人都在把一些书本上的东西重复了一遍又一遍。
- 【转】阴影锥(shadow vol...
qq1337715208:可惜了,图全没了,原链接也挂了
- 我的iOS作品
lihaoze522:同意[reply]myfei2[/reply]
- [OpenGL ES 01]Ope...
lihaoze522:写的真的好细致 十分感谢
归档
- 2019年1月 1篇
- 2018年12月 1篇
- 2018年11月 2篇
- 2018年7月 1篇
- 2018年5月 1篇
- 2018年3月 1篇
- 2018年1月 1篇
- 2017年9月 1篇
- 2017年8月 1篇
- 2017年5月 1篇
- 2017年4月 1篇
- 2017年3月 1篇
- 2016年12月 1篇
- 2016年3月 1篇
- 2016年2月 1篇
- 2015年12月 1篇
- 2014年10月 2篇
- 2014年7月 5篇
- 2014年6月 2篇
- 2014年4月 4篇
- 2014年3月 1篇
- 2013年8月 1篇
- 2013年7月 1篇
- 2013年6月 1篇
- 2013年4月 6篇
- 2013年3月 4篇
- 2013年1月 2篇
- 2012年12月 5篇
- 2012年11月 9篇
- 2012年10月 2篇
- 2012年1月 6篇
- 2011年12月 7篇
- 2011年11月 5篇
- 2011年10月 6篇
- 2011年9月 9篇
- 2011年8月 8篇
- 2011年7月 4篇
- 2011年5月 1篇
- 2011年4月 2篇
- 2011年3月 9篇
- 2010年9月 2篇
- 2010年3月 2篇
- 2009年9月 4篇
- 2009年8月 1篇
- 2009年7月 1篇
- 2009年6月 4篇
- 2009年5月 2篇
- 2009年4月 2篇
- 2009年3月 1篇
- 2009年2月 1篇
- 2009年1月 1篇
- 2008年12月 2篇
- 2008年11月 7篇
- 2008年8月 2篇
- 2008年7月 8篇
- 2008年6月 9篇
- 2008年5月 1篇
- 2008年4月 3篇
- 2008年3月 7篇
- 2008年2月 4篇
- 2008年1月 2篇
- 2007年11月 2篇
- 2007年10月 2篇
- 2007年9月 1篇
- 2007年7月 1篇
- 2007年6月 3篇
- 2007年5月 3篇
- 2007年3月 2篇
- 2006年10月 3篇
- 2006年9月 5篇
- 2006年8月 1篇
- 2006年7月 4篇
- 2006年6月 1篇
- 2006年4月 1篇
- 2006年3月 5篇
- 2006年2月 2篇
- 2006年1月 6篇
- 2005年12月 24篇
400-660-0108
工作时间 8:30-22:00
-
8
T


浙公网安备 33010602011771号