最近在读《cocoa入门-使用Objective-C》,对于该书,本人的评论是,是本非常经典好的入门教材,写的非常的到位。不过需要各位读两遍,第一遍知道讲了什么,第二遍,开始深入理解里边的个别经典描述,提升就是这样产生的。
1-4章,该部分全部略过,非常的基本,各位感兴趣的可以自行查看。
5章,图像用户界面,
关键点:
1、cocoa其实就是mac下的带有用户界面的程序开发的一套架构,该架构在MAC下,应该说是最重要的。
2、cocoa的图形用户界面元素,windows,view,nib文件(相当于MFP的rc文件,用于描述dialog的资源的),IBoutlet,IBAction。
3、NIB文件,这里要多说一些,这是一个xml格式的文件,描述了控件的信息,它是与app一起打包发行的。MFP的rc是将图像描述信息打包到exe文件当中,而在cocoa当中,是将界面对象的描述,界面对象的信息,界面对象的关联关系等都记录到nib文件当中,然后与app一起发行。app加载nib的同时,就会将nib所描述的对象加载到程序当中。举个简单的例子可能会说的比较清楚,在程序设计的过程当中,就以书中描述的计算汇率的程序为例,那里边描述了一个controller对象,在nib中,但是你可以发现,在程序的所有文件当中,对没有见到controller的对象,那么controller是如何实现的哪? 对了,就是nib实现的,通过让系统加载nib文件,那么nib文件所定义的对象就会在系统中生成,此时的界面对象响应,就会在该对象的内部发生。这也就解释了,为什么类的定义做了,类的实现做了,但是并没有对类进行对象定义,确在程序运行时,能够运行到类当中去,其道理就这与此。
4、cocoa当中到处都是MVC,其实真正重要的是C,controller控制着相关的data,以及view显示。
5、设置tab建的焦点,方法,control+拖动 window对象,然后弹出initialFirstResponder,这样就是找到第一个responder,然后ctrl+拖动,第二个对象,选择nextKeyView,顺序拖动下去,然后保存,从而实现了tab的修改。那么界面测试,通常使用的叫做cocoa simulator,这个工具是不编程也可以测试界面的工具。
6章,窗口,视图和控件
关键点:
1、窗口和窗口系统的理解,在mac当中,其实是有一个叫做,窗口服务程序的进程,负责管理了当前桌面中出现的所有窗口,他通过窗口的ID,来找到每个窗口,此外,为了使每个窗口能够与对象关联,APPLICATION.FRAMWORK起到了后台的作用。
2、核心程序框架,这个框架包括了,NSWINDOW ,NSVIEW , NSAPPLICATION,nswindow负责绘制窗口的框架接受消息,NSVIEW,负责控件管理,NSAPPLICATION,每个程序都只有一个,负责整个程序的运作管理。
继承关系
NSObject -- 》 NSResponder -- 》 NSWindows
》 NSView
》 NSApplication
消息的传递过程:UI负责接收用户出发的消息,然后发送给窗口管理程序,窗口管理程序根据这个窗口的ID,去查找对应于这个窗口ID的应用程序,然后这个应用程序,会将消息发送给NSWINDOWS对象,然后这个对象再去找对应的NSVIEW,进行处理,并将结果发送给窗口ID所对应的那个窗口。当然有的消息是不需要再反馈给UI窗口的。
NSResponder是负责事件处理的循环的
3、键窗口和主窗口,其实键窗口是指可以接受键盘消息的窗口,而主窗口是工作的主要窗口,比如photoshop,panel就是键窗口,而图像就是主窗口。
4、视图的层次结构,NSAPP NSWINDOW -- NSVIEW -- 控件(nsbutton等)
5、坐标系统,屏幕坐标,窗口坐标,视图坐标,都是第一象限
6、控件和控件单元,其实在cocoa当中,几乎所有的控件都是使用控件+控件单元的方式实现的,控件是个框架,然后向里边添加控件单元,这样做的好处,就是改善性能,提供效率。因为每次只需要对控件单元进行刷新处理,而不需要对整个控件进行刷新。另外,需要注意一点的是格式器,只会针对控件单元生效。
7、awakeFromNib,这个方法,是在nib文件被成功加载之后,会向nib当中的每一个对象发生这个消息,从而使每一个对象都有一会,进行初始化等相关的处理操作。请记住是每一个对象。
8、在插座和界面元素之间连线,通常来说都是一个比较复杂的问题,那么比较简单的原则就是:连线通常都是按照消息的流向进行的。
视图处理的理解:
其实在Cocoa当中,涉及到了IB和XCODE的联合编程,那么这个编程,其实就涉及到了UI对象和类对象的关联关系,这个关系体现了一写方面。
1、如果是自定义的控件类,那么通常是直接修改控件的类描述,为自定义的控件类。
2、对于nib文件的Fileowner所对应的类,其实是描述了这个nib文件被那个类加载,相当于对话框的主类。这个主类,可以定义任意个outlet和action进行处理。
3、当然,除了上述的开发方法,通常来说,还可以在nib当中引入controller对象,由该对象完成所有的控制操作。而并不由主类完成,这是一个设计习惯的问题。
第7,自定义视图
关键点:
1、主要是实现自定义视图的父类的两个方法,:initWithFrame和drawRect
第8,事件处理
1、事件的处理流程:窗口服务器检查到消息,发送NSEvent给APP,然后APP发给window对象,再有windows发给nsview,最后发给消息对应的控件。
2、事件类型,键盘事件,鼠标事件,周期事件,跟踪事件。
3、第一响应对象,其实任何一个控件,当他处理active状态时,他就是第一响应对象,当然可以有个方法,acceptFirstResponder来拒绝成为第一响应对象。
4、其实鼠标事件,就是NSResponder定义好的方法,在NSView对象中,重写该方法,就实现了鼠标事件响应。
5、事件委托,这个是cocoa当中最重要的一部分内容,几乎很多的反馈都是以委托的方式实现的,围绕着委托,可以有helper对象,委托协议等概念。那么对于委托对象而言,在cocoa当中,就是需要实现委托协议所定义的方法。而通常来说,不显示定义实现了协议,只要支持该方法,其实就是完成了委托的支持。这一点与显示使用协议,是完全相同的。需要注意的一点就是,委托协议,要针对不同对象,比如针对application的委托协议,和针对windows的委托协议,虽然都可以使用同一个受托人,但是需要setDelegate进行指定。
6、通告,是另一种消息传递的方式,是广播传递,编程通常的使用都是使用NSNotificationCenter对象实现。然后使用AddObserver函数添加监听者。
第9,模型和数据处理
1、protocol和键值编码,protocol就是协议,用于实现委托。键值编码,其实就是NSObject实现了NSKeyValueCoding协议。
2、这里对于任何的继承于NSObject对象的子类,都是支持键值编码处理的,此时需要特别强调,此时的键值,就是NSString格式的变量,值就是该变量的值。
如:@interface ITEM : NSObjet
{
NSString * name;
}
@end
键就是name,值是name的值。
3、编码和归档,之前提到过,只有nsstring可以保存到任意格式的文件,而集合只能保存到XML格式的类似于plist的文件当中。那么如何保存自定义对象哪?
方法其实很简单,是自定义对象支持NSCoding协议,然后使用NSARCHIVE和NSUNarchiver实现任意格式文件的读取和写入。
4,文件打开窗口和文件保存窗口,即NSOpenPanel和NSSavePanel的使用。
NSSavePanel * save = [ NSSavePanel savePanel];
SEL sel = @selector(SavePaneldidEnd:returnCode:contextInfo:];
[save beginSheetFordirectory:@"~/Documents"
file:@"item.items"
modalForWindow:[table window]
modalDelegate:self
didEndSelector:sel
contextInfo:nil]
-(void)savePanelDidEnd:(NSSavePanel *)panel
returncode:(int)returncode
contextInfo:(void*)context
{
if(returncode == NSOKButton)
{ //保存
}
}
打开的处理方法
NSOpenPanel * open = [ NSOpenPanel openPanel];
SEL sel = @selector(openPanelDidend:returncode:contextInfo:);
[open beginsheetfordirector:@"~/Documents"
file:nil
types:nil
modalForWindow:[table window]
modalDelegate:self
didEndSelector:sel
contextInfo:nil];
-(void)openPanelDidEnd:(NSOpenPanel*)panel
returncode:(int)returncode
contextInfo:(void*)contextInfo
{
if(returncode == NSOKButton)
{//打开
}
}