《Objective-C基础教程》读书笔记(1)

来源:互联网 发布:php收银系统 编辑:程序博客网 时间:2024/06/06 08:32

新浪微博:东门兜

提供一下这本书的下载地址:Objective-C基础教程 下载

第二章 对C的拓展
Objective-C刚诞生的时候,拓展名.m代表message,指的是Objective-C的一个主要特性。

在C语言中,程序员通常使用基于#ifdef命令的方案来避免一个文件包含另一个文件,而后者又包含第一个文件的情况。而在Objective-C中,程序员使用#import实现这个功能,可保证头文件只被包含一次,而不论此命令实际上在那个文件中出现了多少次。

(#)import Foundation/Foundation.h语句告诉编译器查看Foundation框架中的Foundation.h头文件。什么是框架?框架是一种聚集在一个单元的部件集合,包含头文件、图像、声音文件等。Foundation框架处理的是用户界面之下的层中的特性,例如数据结构的通信机制。

“NS”是什么意思呢?Cocoa对其所有函数、常量和类型名称都添加了“NS”前缀,这个前缀告诉你函数来自Cocoa而不是其他工具包。两个不同事物使用相同标识符时会导致名称冲突,而前缀可以预防这个大问题。“NS”开头是因为NeXTSTEP。

把Xcode中的警告设置成错误来处理。那个这个玩意儿,在6.2的Xcode当中又是在哪里呢?看看下面的图,按照1,2,3,4就可以找到了(暂且先不谈开起来好不好):

Treat Warning as Errors

C语言有bool类型,具有true值和false值。Objective提供了相似的BOOL类型,具有YES和NO值,YES定义为1,NO定义为0。绝不要直接将BOOL值和YES比较,直接和NO比较则一定安全,因为C语言中假值就是0。

本章小结:
1、编写了两个简单的Objective-C的小程序。
2、用import让编译器引入一次头文件。
3、学习了NSString,以@符号开头的字符串。
4、使用了重要且通用的NSLog(),支持将NSString插入到NSLog()输出中。
5、学习了BOOL类型。


第三章 面向对象编程基础知识
间接:不在代码中直接使用某个值,而是使用指向该值的指针。包括通过号码簿找号码,委托别人帮你做事等都是间接。

基本变量就是间接的一种实际应用。如果需要修改的代码相同,且修改多次,则要考虑是否能将代码用变量替代或归为一个方法。

使用文件名的间接,我们可以将字符串数组或者一串内容完全移到代码之外,将其全部置于文本文件中。

输入控制台参数:

控制台参数1

控制台参数2

控制台参数3

argc保存argv数组的长度。
argv[0]保存程序名,
如:/Users/yangyh/Library/Developer/Xcode/DerivedData/Hello_Objective-C-dajidenzbrkictgqwjiotrnbxkav/Build/Products/Debug/Hello
argv[1]为你信添加的参数。

函数是过程式编程的中心:你决定使用什么函数,然后调用那些函数,传递其需要的数据。
过程式编程的缺点:
1、使用过程式编程时,你得时间花在了连续数据与处理该类数据函数上。必须注意,要为各种数据类型使用正确的函数。但是令人失望的是,有时候一不留神就会将矩形传递给准备处理圆形的函数。(即编写大量函数耗费的时间与函数使用错误)
2、编写这种代码的另一个问题是程序的拓展和维护变得很困难。如果我们想增加某个同型号的东西,我们就不得不修改大量的代码。(即不易于拓展和维护)
3、此外还可能造成空间的浪费,比如A型号有它独有的特点,其他都没有,但我们不得不将所有型号都改成和A型号一样,这样就很浪费空间了。(即浪费大量空间)

过程式编程,“函数第一,数据第二”。对象式编程,“数据第一,函数第二”。过程式程序建立在函数之上,数据为函数服务。而面向对象编程则以程序的数据为中心,函数为数据服务。对象其实是一种神奇的C struct。

id代表identifier(标识符)。id是一种泛型,用于表示任何种类的对象。对象是带有代码的C struct。因此,id实际上是一个指针,指向其中的某个结构。

面向对象OOP的几个术语:
类:一种struct结构,一个程序可能包含几十个类。
对象/实例:包含值和指向类的隐藏指针。运行中的程序通常包含成千上万个对象。
消息/方法:通知对象去做什么。
方法调度程序:用于推测执行什么方法以响应某个特定的消息。
接口:类拥有的武器,接口不提供实现的细节,通常不必了解。
实现:使接口正常工作的代码。

方法的结尾写上 //方法名
接口通常被称为API,“Application programming interface”中3个首字母的缩写。

在@interface和@implementation间的参数名不同是正确的。如果我们继续使用相同的参数名,就会隐藏实例变量,并且编译器会生成警告信息。

剪切和粘贴编程方式的一个缺点是容易出现大量重复的代码。而继承可以有效避免冗余代码。

面向对象编程大师的开放/关闭原则,即软件实体应该对拓展开放,而对修改关闭。应对变化时,遵循开放/关闭原则的软件会表现出更强的健壮性,因为你不必修改那些可正常运行的代码。

本章小结:
1、间接:变量、文件名、传递隐藏的参数。
2、过程式编程的缺点与局限。
3、面向对象的编程。实例向类发送消息,类收到消息后,执行方法。
4、OOP的相关术语。
5、@interface和@implementation。
6、实例化对象。


第四章 继承
什么时候该用继承?
1、程序中含有大量的重复内容,这会影响程序的执行效率。进行编程时,出现这样的重复内容就表明它是一个不好的架构。你需要维护两倍甚至更多的代码,这样经常会发生错误。
2、多个类的变量、方法、接口、实现都很相似,或者说都相同,它们属于同一大类。

为什么要使用继承呢?
使代码更简约、可读性更强,同时程序的执行效率更高。

UML统一建模语言

UML统一建模语言,UML是一种用图表表示类、类的内容以及它们之间关系的常见方式。

不要直接更改由继承得到的实例变量的值。一定要使用方法来更改它们。

重新修改后的代码,像这种移动和简化代码的方式称为重构。这在OOP社区中是一个非常时尚的话题。进行重构时,你通过移动某些代码来改进程序的架构,正如我们在这里删除重复的代码,而不改变代码的行为或运行结构一样。通常的开发周期包括向代码中添加某些特性,然后通过重构删除所有重复的代码。

关于继承的相关术语:
超类/父类:是你所继承的类。
子类/孩子类:是实施继承的类。
重写:改变方法的实现时,需要重写继承方法。

继承功能的方法调度过程:当代码发送消息时,Objective-C的方法调度程序将在当前类中搜索相应的方法。如果调度程序无法在接收消息的对象类中找到相应的方法,它就在该对象的超类中进行查找。必要时,这种操作将会在继承链的每一个类中重复执行。如果在子类和父类中都没有找到某种方法,调度程序将会检查NSObject类,因为它是继承链中的下一个超类。如果NSObject类(最高级别的超类)中也没有该方法,则会出现运行时错误(同时还会出现编译时警告信息)。

使用更具体种类的对象(Rectangle或Circle)代替一般类型(Shape),这种能力称为多态性。

制作自己全新的子类时,通常需要添加自己的方法。有时,为了在类中引入某个独特的特性,需要添加新方法。还有些时候,可能需要替换或增强由这个新类的某个超类所定义的现有方法。

[super setFillColor:c]:向super发送消息时,实际上是在请求Objective-C向该类的超类发送消息。

重写方法时,调用超类方法总是个不错的选择,这样可以实现更多的功能。通过调用继承的方法,可以确保能够获得方法实现的所有特性。

本章小结:
1、学习了什么时候使用继承和继承的语法。
2、学习了如何使用继承来简化代码和完善架构。
3、学习了继承的方法调度、实例变量继承。
4、方法的重写。
5、super关键字如何通过在重写的方法中充分利用超类代码。


第五章 复合
在之前的Shapes-Object程序中,我们已经看到了一种形式的复合:Shape类使用了矩形(一个struct)和颜色(一个enum)。严格地讲,只有对象间的组合才能叫做复合。诸如int、float、enum和struct等基本类型都被认为是对象的一部分。

NSLog()给一个对象发送描述消息,然后对象的description方法生成一个NSString并返回。之后NSLog()在其输出中包含这个字符串。在类中添加description方法就可以自定义NSLog()如何输出对象。

对象初始化:

- (id)init {    if (self = [super init]) {    }    return (self);}

使用new创建新对象时,实际上系统要完成两个步骤。第一步,为对象分配内存,即对象获得一个用来存放其实例变量的内存块;第二步,自动调用init方法,让该对象处于可用状态。

将[super init]的结果赋给self是Objective-C的标准惯例,这么做是为了防止超类在初始化过程中返回的对象不同于原先创建的对象。

在对其他对象的属性进行操作时,应该始终使用对象所提供的存取方法,永远不要直接改变其他对象属性的数值,应该使用setter方法进行更改。存取方法是程序间接工作的另一个例子。

setter方法根据它所更改的属性的名称来命名,并加上前缀“set”;getter则仅仅根据其返回的属性的名称来命名,不要将get用作getter方法的前缀。get这个词在Cocoa中有着特殊的含义。如果get出现在Cocoa的方法名称中,就意味着这个方法会通过你当作参数传入的指针返回数值。

如果数组索引超出了0到3的范围,那么程序就会输出错误信息并退出。该代码就是所谓的防御式编程,这是一种很好的思想。防御式编程能够在开发周期的早期发现错误,例如索引错误。

复合还是继承?继承在对象间建立了“is a”(是一个)的关系。复合建立的则是“has a”(有一个)的关系。创建新对象时,先花时间想清楚什么时候应该用继承,什么时候应该用复合。创建新对象时,先花时间想清楚什么时候应该用继承,什么时候应该用复合。

本章小结
1、学习了复合的定义。
2、自定义NSLog的description方法。
3、用init创建对象。
4、存取方法和命名规范。(在6.2的Xcode中已经发生变化了)
5、什么时候用继承?什么时候用复合?


第六章 源文件组织
接口包含了所有使用该类所需的信息;实现告诉编译器如何让该类工作。一个文件存放接口部分的代码:类的@interface指令、公共struct定义、enum常量、#defines和extern全局变量等。所有实现细节(如类的@implementation指令、全局变量的定义、私有struct等)都被放在.m文件中。如果使用.mm做文件拓展名,编译器就会认为你是用Objective-C++编写代码,这样你就可以同时使用C++语言和Objecitve-C来编程了。

Xcode将加入项目的新文件放在Groups & Files窗格中选定的文件夹里。这些文件夹(在Xcode中被称作组)能够帮助你组织项目中的源文件。在设置组时,Xcode并不会真的在硬盘上移动文件或者创建目录。组关系只是一个由Xcode管理的虚拟工具。如果你愿意,可以创建一个指向文件系统中某个特定目录的组,Xcode会帮助你将新创建文件放在该目录里。

导入头文件有两种不同的方法:使用引号或者使用尖括号。例如,#import Cocoa/Cocoa.h和#import”Tire.h”。带尖括号的语句是用来导入系统头文件的,而带引号的语句则说明导入的是项目本地的头文件。尖括号的头文件为只读(它属于系统),引号的头文件为编辑。

@class用于复合变量,在@interface文件中,如果你发现它只是通过指针引用对象,那么你可以使用@class,然后在@implementation文件中,加入#import。它在告诉编译器:“相信我,以后你会知道这个类到底是什么。但是现在,你只需要知道这些。”

如果有循环依赖关系,@class也很有用。即A类使用了B类,B类也使用A类。如果试图通过#import语句让这两个类互相引用,那么最后就会出现编译错误。但是如果在A.h中使用@class B,在B.h中使用@class A,那么这两个类就可以相互引用了。

如果是通过继承而不是通过指针指向其他类,就不能在头文件中使用@class语句。因为在子类中添加实例变量时,它们会被附加在超类实例变量的后面。然后编译器用这条信息来判断在内存的什么位置能找到这些实例变量,从每个方法调用自身的self隐藏指针开始寻找。为了能够准确地计算出实例变量的位置,编译器必须了解该类的所有内容。

本章小结
1、学习了如何将代码分配到多个文件中,和组文件夹。
2、学习了用#import导入头文件,获取该类的功能。
3、学习了跨文件依赖,循环依赖。
4、@class的使用


第七章 深入了解Xcode
面对像Xcode这样的大型工具,最好的学习方法就是先粗略浏览一遍文档,然后使用它一段时间,接着再浏览一遍文档。每次浏览文档时,就会理解并掌握更多的内容。

更改公司名称的例子就不需要了。

双击源文件可以在新窗口中打开源文件。

首行缩进:选择需要调整的代码,同时按下command+[ (左移动代码)或 command+](右移动代码)。
代码自动生成:在任何时候你都可以按ESC键,让Xcode打开这个包含所有可能代码的自动完成列表。(使用ESC出现的联想列表中左边的字母表示什么含义?)
占位符:出现多个占位符时,可以使用control+/将光标移到下一个占位符。
快照:在某个时刻保存一个项目副本,当你要恢复的时候,可以从这里恢复。很像我们以前在windows机子上的还原精灵。control+command快捷键可以开启快照。
(思考:有没有想过在编写代码时,全部都使用快捷键,而不要借助鼠标?amazing!)

Find->Find in project:在项目中所有文件里进行查找和替换。
Editor->Edit All in Scope:重命名一个类。但不改源文件。(需要先选中一个类名,比如Car。)
Edit->Refactor->Rename:它不仅能够重命名类,还能做一些诸如重命名相应源文件之类的妙事。(需要先选中一个类名,比如Car。)或者,右击代码框,点击Refactor,点击里面的Rename,可以替换一切相关文件。

Xcode中打开文件内容,右击有菜单Structure,里面有实用的小功能。

记得我的经理说过一句话:快捷键可以提高效率。下面是小范围文本编辑时采用的快捷键。

Xcode快捷键

书签功能貌似没了。
代码的折叠与展开。
使用#pragma mark -在方法导航中插入分割线。
锁文件貌似没了。

访问苹果公司的官方API文档,最快的方法是按住Option键并双击某个符号。此外,如果只是要查看某个类或方法的简要说明,只需要按住Option键并左键单击某个类或方法就可以了。如果要查看某个类的.h头文件,只需要按住Command键并左键单击某个类就可以了。

调试:查找程序错误地过程。
暴力调试:在程序中放入输入语句(如NSLog)来输出程序的控制流程和一些数据集。(我记得以前调试javascript代码时就经常采用这样的方式,用alert弹出提示框 = =!)
断点:断点就是调试器应该停止程序的运行并让你查看运行情况的地方。
书上说的调试方法已经是比较古老的了,现在只要在想调试的行打上断点,然后直接run就可以了,非常方便。
调试中可以查看变量此时的详细情况。

本章小结
1、首行缩进、代码自动生成、括号匹配。
2、快照、三种批量编辑。
3、小范围文本编辑快捷键。
4、搜索文件。
5、代码编辑器顶部的代码导航条、#pragma、拆分窗口。
6、API文档查看。
7、调试、查看变量的当前状态。

如果错误请指出,我将听取意见,好好修改,谢谢各位。:)

0 0
原创粉丝点击