Objective-C中一些 值得程序员注意的地方 学习笔记


Objective-C中一些 值得程序员注意的地方:


1.有关于BOOL陷井方面有如下方面:

关于BOOL条件语句中的比较最好是与NO的值来进行比较,因为BOOL的YES与NO值只是约定,并且编译器将BOOL认作8位二进制数据。若是不小心将一个长于1字节的整型值赋值给BOOL变量,那么只有底位字节将会用做BOOL的值,假设底位字节刚好为0的话,那么BOOL的值将会是0,即NO值,所以关于比较方面推荐用变量值与NO值进行比较。
2.Objective-C中一些基础的语法问题:(重要声明:Objective-C就是C,不是什么其他的语言)

NS****命名规则:简单来说就是以NS为前缀加上匈牙利命名法。

#import在 Objective-C中的使用情况:#import在 Objective-C程序中相当于#include在C/C++中的用法,但是前者在功能上面与后者是有一定的区别,简单说一点:前者可保证头文件只被包含一次,而不管此命令在那个文件中实际出现(使用)了多少次。在c语言中,程序员通常使用机遇#ifdef命令的方案来避免一个文件包含另一个文件,而后者又包含第一个文件的情况,在objective-c中,程序员使用#import实现这个功能。

NSLog()和@"字符串"在objective-c中的使用情况:

NSLog()函数在Objective-C中的作用相当于Console、printf()在c/c++语言中的作用。NSLog()还有时间戳、日期戳和自动添加换行符('\n')等一些Console与printf()不具备的功能。在Objective-C中@符号是其在标准c语言基础上添加的特性之一,""双引号中的字符串前有一个@符号,这表示引用的字符串应该作为Cocoa的NSString元素来处理。

NSString的部分功能有:

a.告知其长度;b.将自身与其他字符串进行比较;c.将自身转换为整型值或者浮点值。
在Objective-C中多参数方法的简要介绍:
多参数方法需要抓住的一点是后面的参数都需要写上名字。

在 Objective-C中加号、减号、中括号他们的意义与用法:

首先需要了解的一点是在 Objective-C中是没有public与private的概念的,即可以认为全部都是public。减号表示的是一个函数、方法、消息的开始。加号则表示不需要创建一个类的实例,其他类就可以直接调用这个类中的函数(也可以说加号表示静态的成员函数)。中括号在 Objective-C中表示方法的调用(通常在 Objective-C中都是说"消息")。下面一段转换关系就可以清楚的搞懂中括号的使用了:[[[MyCalss alloc] init:[foo bar]] autorelease]; 其转换为C#或者Java的语法如:MyCalss.alloc().init(foo.bar()).autorelease(); 这段转换关系非常的重要。

最后关于部分重要东西及个别问题的介绍:

1.id:

Objective-C有一种比较特殊的数据类型是id,可以理解为"随便"。等价于c语言中的void *;在Objective-C里一切数据都是以指针的形式保存,你获取到的就是这个对象在内存的位置,而id就是你知道的这个位置。

2.同一个数组可以保存不同的对象:

在Objective-C中数组(NSArray)里面可以保存各种不同的对象,通过以下例子来表示:{myArray<—|0:(float)234.33f 1:@"要玩娱乐" 2:(NSImage *) (图片资源) 3:@"世纪大光棍"}以上这个数组包含了4个元素,分别是浮点数、字符串以及图片。

3.BOOL、YES、NO:

在Objective-C中通常把YES等价于C#、Java、C、C++中的true,把NO等价于false,而实际上YES为1,NO为0,BOOL本身是一个char型数据(编译器认作为8位二进制数据)。

4.IBOutlet、IBAction是什么东西,为什么总能看见:
在语法中IBOutlet、IBAction没有太大作用,若是希望在Interface Builder中能看到这个控件对象,那么在定义的时候前面加上(IBOutlet),在IB里面就能看到这个对象outlet,如果希望在Interface Builder里控制某个对象执行某些动作,就在方法前面加上(IBAction).实际上IBOutlet、IBAction就跟void是一样的。
5.nil的意义是什么:

在Objective-C里NULL(空)就是用nil来表示,nil表示空指针。

6.@"字符串"与"字符串"有什么不同或者区别:

"字符串"是C的字符串,@"字符串"是把C的字符串转换成NSString的一个简写.在需要NSString的地方才需要这个转化,例如:NSLog里面.在需要C string的地方,还是用"字符串"的形式.另外,@""这个转换是不支持中文的,例如NSLog(@"字符串");是一定输出不了中文的.
3.函数原型和声明方式:
首先:先行下短线—即是“减号”,每种方法的名称、方法的返回值的类型和某些参数。先行短线后面接着就是返回值.

中缀符:Objective-C中有一种名为中缀符(infix natation)的语法技术,方法的名称及其参数都是合在一起的.如:可以这样调用带一个参数的方法:[circle setFillColor:kRedColor];带两个参数的方法调用如下:[textThing setStringValue:@"hello there"color: kBlueColor];setStringValue:和color:实际上是参数的名称(实际上是方法名称的一部分,后面在详细介绍),@"hello there"和BlueColor是被传递的参数.

冒号:有参数的方法时通常是方法的名称结尾处是冒号,冒号之后紧接着就是这个参数类型及其参数名.冒号之后的圆括弧中是参数的类型.在无参数的方法中在方法的名称结尾处通常是不需要添加冒号的而是分号.这里是非常需要注意的,有时候就是因为在没参数的方法后面加上了冒号而导致程序出现了错误信息是没有意义的初级错误.

总结出以下情况为函数原型及声明的一般形式: - (方法的类型) 方法的名称: (参数的类型) 参数的名称; 或者是: - (方法的类型) 方法的名称;

最后:声明完成后必须在最后一句加上@end来告诉编译器类的声明已经完成.这也是很重要的一处基础.

4.实现代码的指令及需要注意的地方:
编译器同过@implementation这个指令来为某个类提供代码,类名出现在@implementation之后,该行的结尾处没有分号,因为在Objective-C编译器指令后不必使用分号.在@implementation指令中各个方法的定义,不必按照在@interface指令中的顺序出现,甚至可以在@implementation中定义那些在@interface中没有相应声明的方法。可以把他们(这里的他们是指的是:在@interface中没有相应声明的方法)看成私有的方法,仅在类的实现中使用。在这里有一点需要注意:在Objective-C中是不存在真正的私有方法.也就是说单独在@implementation指令中定义的方法是能从外部进行访问的,这算是Objective-C动态本质的副作用.传递隐藏的参数是另一种间接操作的事例.Objective-C运行时(runtime)可以将不同的对象当成隐藏的self参数传递,所以哪些对象的实例变量发生更改时,运行时也可以进行相应的更改.


说明:用户运行应用程序时,Objective-C运行时是支持这下应用程序(包括我们自己的应用程序)的代码块,运行时执行非常重要的任务,如向对象发送消息和传递参数.
5.实例化对象:
Shapes-Object中最后的、非常关键过程,在该过程中,我们创建形状对象,例如红色的圆形和绿色的矩形,这个过程的专业术语就叫做实例化(instantiation).实例化对象时,需要分配内存,然后这些内存被初始化并保存一些有用的默认值,这些值不同于你在 获得新分配的内存时得到的随机值,内存分配和初始化完成后,就闯将了一个新的对象实例.这里有一点需要注意:由于对象的局部变量特定于该对象的实例,因此我们称它们为实例变量,通常简写为ivars.

为了创建新对象,我们需要向相应的类发送new消息,因此接收并处理完new消息后,我们就会得到一个可以使用的新对象实例.

Objective-C有一个极好的特性,你可以把类当成对象来向类发送消息,这种便捷的行为不局限于某个特定的对象,而是对全体类都通用,这种消息通常用在创建新对象时,如果需要创建新的circle对象,请求Circle类创建新对象比请求某个现有的circle对象更合适一些.


第4章节:

1.继承:~~@interface Circle: NSObject~~冒号后的标识是需要继承的类,因为可以从非类中继承对象.Cocoa,NSObject继承对象,因为NSObject提供了大量有用的特性(当继承一个已继承自NSOvhect的类时,你也能获取这些特性).Objective-C中继承不支持多继承,想在Objective-C中获得多继承的优点,那么就要使用Objective-C的其他特性,如:分类和协议,在本书12、13章有介绍.

2.重构:移动和简化代码的方式称为重构,这在OOP社区中是一个非常时尚的话题.进行重构时,你通过移动某些代码来改进程序的架构,正如我们在这里把程序中重复代码删除,而不改变代码的行为或运行结果一样,通常的开发周期包括想代码中添加某些特性,然后通过重构删除所有的重复的代码.通常,在面向对象的程序中添加某些新特性后,程序反而变得更简单,你可能对此觉得很奇怪,这就想我们添加了Shapes类后所出现的情况.

说明:因为继承在子类和超类只见建立了一种"is a"(是一个)关系,所以NSObjec的实例变量称为isa.即Rectangle是一种Shape,Circle是一种Shape,使用Shape的代码也可以使用Rectangle或Circle来代替.使用更具体种类的对象(Rectangle或Circle)代替一般类型(Shape),这种能力称为多态性(polymorphism),它在希腊语中形象地表示"很多形状".

小心易碎:编译器使用"基地址加偏移"机制实现奇妙的功能.给定的对象基地址,是指第一个实例变量的首个字节在内存中的位置.通过在该地址加上偏移地址,编译器就可以查找其他实例变量的位置.如:如果圆角矩形对象的基地址是0x1000,则isa实例变量的地址是0x1000+0,即位于0x1000位置,isa的值占4个字节,因此,下一个实例变量fillColor的起始地址位于4个偏移地址之后,即位于0x1000+4位置,或写作0x1004,,每个实例变量与对象的基地址都有一个偏移位置.如果访问方法中的fillColor实例变量,编译器生成代码并得到存储self的位置值,然后加上偏移值(在本例中为4),得到指向存储变量值的位置.随着时间的推移,这也回产生一些问题,现在,在编译器生成的程序中,这些偏移位置是通过硬编码实现的.尽管苹果公司的工程师希望向NSObject中添加其他的实例变量,但他们无法做到,因为这样做会改变所有实例变量的偏移位置.这被称为脆弱的基类问题(fragile base class problem).通过在Leopard中引入新的64位Objective-C运行(它使用间接寻址方式确定变量的位置),苹果公司解决了这个问题.

3.重写方法:有时候为了在类中引入某个独特的特性,需要添加新方法.还有时候可能需要替换或增强由这个新类的某个超类所定义的现有方法.(使某方法为空,当方法中的子类都各自实现了自己的功能方法时,就说方法实现了重写).涉及关键字有:super(超类)。

说明一点:重写方法时,调用超类方法总是一个不错的选择,这样可以实现更多的功能.通过用调用super来实现机会,这样可以 保证能够获得方法的所有特性。

第5章节:

1.什么是复合:将多个组建组合在一起配合使用,从而得到完整的作品.这里需要注意的一点是:从严格上来讲,只有对象间的组合才能叫做复合,诸如int,float,enum和struct等基本类型都被认为是对象的一部分.

提醒:如果类中没有包含人和实例变量,就可以省去代码中的花括号。

需要记住的有:通过NSLog()可以使用%@格式说明符来输出对象.NSLog()处理%@说明符时,它会询问参数列表中相应的对象以得到这个对象的描述.从技术上说,就是NSLog()给这个对象发送描述消息,然后对象的description方法生成一个NSString并返回.之后NSLog()在其输出中包含这个字符串.在类中添加description方法就可以自定义NSLog()如何输出对象.
2.存取方法:存取方法(accessor method)是用来读取或改变对象特定属性的方法。类存取方法称为setter方法。另外一种存取方法就getter方法。getter方法为使用对象的代码提供了读取对象属性的途径。

3.修改方法(mutator)是用来改变对象状态的方法。需要说明的一点:在其对象的属性进行操作时,应该始终使用对象所提供的存取方法,永远不要直接改变其对象属性的数值。存取方法是程序间接工作的另一个例子。

4.防御式编程:在存取方法中使用通用代码来检查实例变量的数组索引,以保证它是有效数值,若是超出了有效范围,那么程序就会输出错误信息并且退出,那么该段代码就是所谓的防御式编程.(编程者需要考虑种种可能出现的问题,并且设置异常抛出机制,引申到编程者换位思考的问题上,就可发现出程序所欠缺的部分待优化的功能)。
注意:继承的适用范围,切记不要用复杂的系统来继承包含在本系统中的模块,如:简单来说父与子的血脉继承关系是单向的,所以继承也需要考虑适用范围问题。


第7章节-深入了解Xcode:
1.使用编辑器的技巧与诀窍:

Xcode会在开发者键入代码法过程中给出建议,这是Xcode的代码提示功能,通常叫做代码自动完成功能.

Xcode中的快捷键:command键加上“[”、“]”两个键的功能是把当前光标位置的一行代码进行整体左移跟整体右移。command键加上“/”则为把当前光标位置的一行代码进行行注释。

2.括号匹配:输入程序代码时,也许在输入了某些字符(如")"、"]"或"}")后屏幕会有些闪烁,这就是Xcode在告诉在这里与之对应的开括号在哪里.这就是Xcode的"括号匹配",也可以双击某个分隔符,Xcode会选定它以及与它匹配的括号之间的全部代码.

3.批量编辑:选择File->Make Snapshot(快捷键command-control-S),Xcode会记住项目的当前的状态.先在你就可以随心所欲的"破坏"你的项目.如果意识到犯了一个很严重的错误,那么可以通过File->Snapshots来恢复你的快照.在这里若是要做什么项目上的重大的修改的时候都推荐备份一份代码跟保留一份修改当前一个完整版本的代码快照.(说明:备份代码的重要性,因为在实际上快照被存储在一个磁盘镜像中,它存放于~/Library/Application Support/Developer/Shared/SnapshotRepository.sparseimage.有时候这个磁盘镜像可能会被损坏(也许因为生活压力太大了),这时Xcode会向你报告一个“神秘”的错误:Snapshot Failed:A project snapshot cannot be created.如果开发者看到了这样的错误,请尝试删除这个景象并重新启动).
4.Xcode中的查找与替换功能:此功能在子菜单Edit->Find中.里面有几个非常方便的选项.Find in Project可以在项目的所有文件里进行查找和替换.其实这种查找与替换工作并不是很好使用,如:若是开发者只是想重命名函数中的变量,那么它做了过多的操作(因为它可能会改变整个文件中的变量名称),而开发者想重命名一个类时,它又无法办到,另外重要的一点,它不能重命名源文件.<在这里又有两个功能可以弥补这些不足:1.可以简称为Edit all in scope,开发者可以选定一个符号,如局部变量或参数,然后选择Edit->Edit all in Scope,然后在开发者输入时,所有该符号出现的地方都会立即更新,这不但是进行大量改动的快捷方式,而且操作是看起来很"酷",输入完毕之后,只要在源文件编辑窗口单击其他地方,就会离开Edit all in Scope模式。2.“内置重构工具”,若开发者有一个GUI程序,它甚至能够深入到nib文件的层次进行修改操作,在需要修改的文件中设置插入点,然后选择Refactor,为了保险需要确保Snapshot复选框被选中,单击Preview之后,Xcode会分析出要做什么,并将结果展示出来.可惜的是,重构并不能重命名注释中的文字,所以类末注释、Xcode生成的头文件注释或者任何开发者编写的文档注释都需要手工编辑,开发者可以使用查找和替换功能来简化这一过程.

5.代码导航:这里参考博客园中的emacs快捷键。http://blog.sina.com.cn/s/blog_6aafe9c90100u4mj.html这篇文章很重要.

7.任意搜索:Xcode项目窗口的右上角右一个搜索框,Xcode通过开发者输入的字符来过滤浏览器中显示的内容.要使用这个索搜框,首先要在Groups&Files列表中选定任意项,如Source文件夹,然后浏览器会显示该文件夹里的所有源文件。在搜索框中输入文本可以对这些文件进行筛选。

8.芝麻开门:假如开发者正在看某个源文件,看到了文件上方的#import,如果能够徐素打开这个头文件而不用鼠标点来点去,是不是会很方便呢?这个非常容易:只需要使用command+shift+o键就可以弹出一个对话框,然后在这个对话框中搜索栏中输入开发者看到的头文件名,然后在下面弹出来的信息中选取适合的文件即可查看此文件内容.

9.书签:在Xcode中与许开发者在代码中插入书签,在代码中可能又一些需要引起人们注意的地方,如:在代码某一个区域以后需要修改优化等操作的话,那么开发者在这里做一个标记的话,到动手操作的时候就可以快速定位此处了。做法为:首先在源文件中放入插入点或者选定一个文本区域,然后选中Edit->Add to Bookmarks,或者使用默认的快捷键command+D(与Safari中的一样),最后当出现提示的时候,输入书签名称即可.

10.集中注意力:紧挨着源代码的左边又两个空列,它们当中左边较宽的一列叫做边列(gutter),靠右较窄的一列叫做焦点列(focus ribbon):焦点列的作用能够让开发者在浏览代码段时集中注意力.焦点列的灰度:代码嵌套得越深,在它旁边的焦点列中,灰色也会越深.这种颜色编码能够使代码的复杂程度一目了然.用鼠标悬停在焦点列上时会突出显示相应的代码段,也可以点击焦点列来折叠相应的代码段。

11.开启导航条:在代码编辑器的顶部右一个小控件条,也就是导航条.这里面的很多控件可以让开发者快速地在项目中的源文件之间进行切换.关于#pragma的说明:“Pragma”源自希腊单词,意思是“行动”.#pragma指令将Objective-C常规代码之外的信息或说明传递给编辑器和代码编辑器.通常,Pragma是被忽略的,但它在一些软件开发工具中可能有其他含义,如果某个工具并不知道pragma是什么,则应该“点头微笑”并且忽略它,而不是生成警告或错误信息.

12.研究助手(Research Assistant)的浮动小窗口会根据逆在Xcode力的交互操作来更新所显示它的内容,要打开研究助手,选择菜单Help->Show Show Research Assistant。

13.文档管理程序:开发者想直接访问苹果公司官方API文档,最快的方法是按住Option键并双击某个符号,这是查找该符号相关文档的快捷方式.需要在Xcode其他窗口甚至是网页浏览器中打开文档也很容易,只需要按住control键并单击(或右键单击)文档区域来打开菜单即可.

14.调试:系统的在代码中查找程序哪里出错的过程叫做调试(debugging)。

15.暴力调试:最简单的调试方式就是暴力调试,暴力调试是指在程序中放入输出语句(如NSLog)来输出程序的控制流程和一些数据值.

16.Xcode调试器:Xcode还有一个调试器,调试器是位于开发者编写的程序和操作之间的程序,它能够中断开发者的程序,使之在运行中停止.这样就可移检查程序的数据及其修改程序.开发者也可以单不执行逐行进行检查程序.说明:Xcode使用的调试器就是GDB,GDB是GNU项目的一部分,它可以在很多不同平台上使用.若开发者愿意,也可以通过命令行来运行它,GDB有者完善的文档系统,尽管它的文档有些难于理解并且网络上流传者好几个版本的GDB教程.

17.精巧的调试符号:打算调试程序时,需要确保开发者正在使用Debug生成配置.可以通过Xcode工具栏中的弹出菜单Active Build Configuration来检验.Debug配置告诉编辑器发出额外的调试器符号,而调试器通过这些符号可以知道程序在什么地方都有写什么.同时,还要确认程序是用调试器来运行的,在Xcode里有两种运行程序的方法,选择菜单Run->Run或者按快捷键command+R,将会不使用调试器运行程序,若要使用调试器,选择菜单Run->Go(Debug)、Run->Debug,或者按快捷键command+Y.说明:多线程编程是一种同时处理多个执行流的编程方式,正确应用它是很困难的,通常,多线程编程所产生的错误非常难于找到,如果有人告诉你多线程很容易,那么他们不是被骗了或者试图向你推销什么东西。下面介绍是4个控件:第一个控件看起来cd机的开始按钮.,安继续键可以使用command+option+p。单击它之后,程序会接着运行到遇见下一个断点,然后结束或者崩溃.第二个控件看起像跳过按钮使用的快捷键是command+option+O.单击这个控件之后它就会执行下一行,然后又会吧程序控制权交还给开发者,第三个按钮,向下指向一个点的箭头,它是跳入按钮(也可以使用快捷键:键盘右上角的键+command+I),这个按键的功能就是跳入方法内部,显示其代码,最后箭头设置在代码的起始位置.第四个按钮是跳出按钮,快捷键是command+右上角的键+T,单击它会终止当前运行的函数并且程序会停在调用程序的下一行代码.若是在试验当中,那么就没有必要在试验当中按这个键了。再下一个按钮(又一个喷雾罐的方框)是用来打开Xcode调试窗口的,再下一个按钮用来打开GDB控制台,开发者可以再这个调试器种直接输入调试命令.最后一个控件是显示调用栈的弹出菜单,调用栈是当前处于活动状态的函数的集合,如果A调用B,B调用C,那么C就位于栈的顶部.再更为复杂的程序中,这种调用栈也称为栈跟踪。

18.检查程序:当开发者在程序的某个部分设置断点或者分步执行时,说明开发者向了解程序状态--变量的值.在Xcode种又数据提示功能.


第八章节-Foundation Kit快速教程:

Cocoa的框架由两个不同的框架组成的:Foundation Kit和Application Kit组成,后者包含了所有的用户接口对象和高级类.main()函数的创建通过alloc、初始化通过init
1.有用的数据类型:a.范围的作用、b.几何数据类型。a.第一个结构体是NSRange,第一种是直接给自段赋值;第二种是应用c语言的聚合结构赋值机制;第三种是Cocoa提供的快捷函数NSMakeRange();如:x.NSRange range;range = 17;range = 4;y.NSRange range = {17,4};z.NSRange range = NSMakeRange(13,15);b.NSPoint来表示一个点,NSSize来储存长度和宽度.Cocoa提供一个由点和大小复合而成的矩形函数数据类型:其快捷函数为:NSMakePoint();NSMakeSize();和NSMakeRect();这里需要说明:Cocoa的这些数据类型是C的struct类型而不是对象呢?原因归结起来就是因为性能。程序(尤其是GUI程序)会用到许多临时的点、大小和矩形来完成他们的工作,还记得吧,所有的Objective-C对象都是动态分配的,而动态分配是一个代价较高的操作,它会消耗大量的时间,所以将这些结构创建成第一等级的对象都会在使用过程种增加大量的系统开销.
2.字符串:Cocoa种的NSString有很多内置方法,让字符串个的处理边的简单很多.a.创建字符串,通过接受格式字符串和一些参数来输出格式话的结果NSString和stringWithFormat:方法就是通过格式字符串和参数来创建NSString的;b.类方法,;c.关于大小、d.比较策略、e.不区分大小写的比较、f.字符串内是否还包含别的字符串.
4.字典NSDictionary:字典就是关键字及其定义的集合。Cocoa种有一个实现这种功能的集合类NSDictionary.NSDictionary在给定的关键字(通常是一个NSString字符串)下存储一个数值(可以是任何类型的对象)。然后开发者就可以用这个关键字来查找相应的数值,所以开发者有一个存储了某人所有联系信息的NSDictionary.那么开发者就可以对这个字典说,“给出关键字home-address下的值”,说明:字典(也被称为散列表或者关联数组)使用的是键查询的优化存储方式,它可以立即找出要查询的数据,而不需要便利整个数组进行查找,对于频繁的查询和大型的数据集来说,使用字典比数组要快得多,实际上字典非常快。

posted on 2012-03-06 19:45  呓语若梦半浮生  阅读(7490)  评论(0编辑  收藏  举报

导航