才看到昨天的不知道为什么没有发出去。。。
第五章 复合
复合的定义:通过包含作为实例变量的对象指针实现。例如:
@interface Unicycle : NSObject
{
Pedal*pedal;
Tire*tire;
}//Pedal和tire通过复合的方式组成了Unicycle
严格来说只有对象间的组合才叫做复合。
自定义NSLog()可以使用%@格式说明符来输出对象。
存取方法
存取方法是用来读取或改变某个对象属性的方法。如果添加一个新方法去改变car对象中的engine对象变量,那它就是一个存取方法。因为它为对象中的变量赋值,所以这类存取方法叫做setter方法。另一种存取方法叫做getter方法,getter方法为代码提供了通过对象自身访问对象属性的方式。
例如:-(Engine *) engine;
-(void) setEngine:(Engine *) newEngine;是一对存取方法。
可以简单的将存取方法理解为:存=setter 取=getter 当然不是绝对的。
两者的区别:setter方法根据它所更改的属性的名称命名,并加上前缀set。例如:setEngine:,setStringValue:等等。
getter方法则是以返回属性的名称命名。上面的setter方法所对应的getter方法应该为Engine,stringValue。
get在Cocoa的方法名称中,意味着这个方法会将你传递的参数作为指针来返回数值。
如何选择使用复合还是继承?
继承的类之间建立的关系为“is a”(是一个)。例如:三角形是一个形状,狗是一种动物。
而复合的类之间建立的关系为“has a”(有一个)。例如:形状有一个填充颜色,汽车有一个发动机和四个轮胎。根据具体的情况判断选择复合还是继承。
对于本章,给我最大的感觉存取这里比较不好理解,在这节我用了很长时间去思考OC中OOP和处理函数的机制,这对于没有C语言基础的人是一件很困难但也很有意思多事情,需要多思考,以及参考书本上的实例进行理解。
学习无捷径,come on~
7月19日
第六章和第七章的内容都是一些偏向记忆和技巧性的知识,以后学习工作中慢慢的去了解~~知识比较多的是第八章,这一章里面有非常多需要理解性记忆和多操作的知识点,不得不说OC在函数的命名上虽然很有规律,但是看起来也很繁琐。。
第六章 源文件组织
为了适应以后大型程序的编写,在编写OC的时候应该将接口和执行部分分别写在不同的文件中以便于后期的修改。后缀名为.h .m。
导入头文件有两种方法:使用引号或者尖括号。尖括号的语句用于导入系统头文件,且属性为只读。引号则是说明导入的是本地文件,属性为可编辑。
依赖关系:
是两个实体之间的一种关系。可以存在于两个类之间,也可以存在于两个或多个文件之间。
@class 类名; 引用该类。@class 创建类一个前向引用。另外@class可以解决循环依赖关系中可能产生的编译错误。
第七章 深入了解Xcode
在Xcode中编写代码时出现自动完成功能时,按tab键是接受自动完成内容,按下esc键则是关闭自动完成内容,再次按下时打开自动完成内容。
自动完成列表名称旁边的彩色方框表示这个符号的类型:E表示枚举符号,f表示函数,#表示#define指令,m表示方法,C表示类,等等。
在做不确定的操作时,应该使用快照功能保存当前工作状态,快捷键:Command+Control+S,快照文件存储在~/Library/Developer/Xcode/Snapshots/目录中。
Command +shift+f 快速打开搜索功能。
control+F 光标向前移动。control+B 光标向后移动。
control+P 光标向上一行。control+N 光标向下一行。
control+A 光标移动到行首位置。control+E 光标移动到行尾。control+D 删除光标右边的字符。control+K 删除当前光标以后的所有字符。
control+L将光标定位到窗口正中央。
暴力测试:在程序写入输出语句来输出程序控制流程和一些数据值。
command+shift+o显示open quickly 窗口。
第八章 Foundation Kit介绍
一些有用的结构体
1. NSRange
typedef struct _NSRange
{
unsigned int location;
unsigned int length;
}NSRange;
NSRange用来表示事物的范围,通常是字符串里的字符范围或者数组里的元素范围。location字段存放该范围的起始位置,而length字段则是表示该范围里所含元素的个数。
三种创建NSRange的方式:
1. 直接给字段赋值 NSRange range; range.location = 17; range.length = 4;
2. 应用C语言的聚合结构赋值机制:NSRange range = {17,4};
3.Cocoa提供的一个快捷函数NSMakeRange(): NSRange range = NSMakeRange(17,4);
第三种方法的好处是可以在任何可以使用函数的地方使用它。
2.几何数据类型
用来处理集合图形的数据类型一般它们的名称都带有CG前缀,这些类型由Core Graphics 框架提供,用来进行2D渲染。
CGPoint表示的是笛卡尔平面中的一个坐标(x,y).
struct CGPoint
{ float x; float y; };
CGSize用来存储长和宽。
struct CGRect
{ CGPoint origin; CGSize size; };
这类函数同样有快捷函数 :CGPointMake();CGSizeMake();CGRectMake()。
3.字符串
NSString的stringWithFormat(属于一种工厂方法):方法通过格式字符串和参数来创建NSString.
+ (id) stringWithFormat : (NSString *) format,…;
eg: NSString *height;
height = [NSString stringWithFormat:@“Your height is %d feet, %d inches “,5,11]; == Your height is 5 feet, 11 inches
关于上述代码中的 “+”。如果仔声明方法的时候添加了加号,就是把这个方法定义为类方法这个方法属于类对象(而不是类的示例对象),通常用于创建新的实例。这种方法叫做工厂方法。
OC运行时生成一个类的时候,会创建一个代表该类的类对象,类对象包含了指向超类,类名,类方法列表的指针,还包含一个long类型的数据,为新创建的实例对象指定大小(以字节为单位)。
如果所创建的大部分方法都是实例方法,那么要用减号(-)来声明。如果某个方法实现的很通用的功能,比如创建一个实例对象或者访问一些全局数据类型,那么最好使用(+)最为前缀将它声明为类方法。
关于实例方法和类方法的区别和使用?
// Deck.h
#import <Foundation/Foundation.h>
#import "Card.h”
@interface Deck : NSObject
@property(nonatomic) int cardNum;
// 实例方法
- (Card *)randomDrawCard;
//类方法
+ (NSString *)CardKinds;
@end
// Deck.m
#import "Card.h”
@implementation Deck
- (Card *)drawCardFromTop
{
// 实例变量
_cardNum—; //实例方法中可以使用该类所有的实例变量
//TODO.....
}
//不能使用该类的实例变量 _cardNum
+ (NSString *)CardKinds
{
NSLog("Cards are divided into four kinds: spades, diamonds, clubs and hearts");
}
@end
总结:实例方法属于类的一个或者某几个实例对象,即类对象必须实例化后才可以使用的方法,将消息发送给实例对象;实例方法中可以使用该类的所有实例变量。 OC中的类方法类似于java中的static静态方法,它属于类本身的方法,不属于类的某一个实例对象,所以不需要实例化类,用类名既可以使用,是将消息发送给类。 类方法不能使用实例变量,所以导致它只适用于一些特殊的情况。
length 方法(实例方法)用来返回字符串中的字符个数。 -(NSUInteger) length; Eg: NSUInteger length = [height length];
4.字符串比较
isEqualToString:可以用来比较接收方(receiver,接收消息的对象)和作为参数传递过来的字符串。它结果是返回一个BOOL值来表示内容是否相同。声明方法: - (BOOL) isEqualToString: (NSString *) aString; 使用方法:
NSString *thing1 = @“hello 5”;
NSString *thing2 = [NSString stringWithFormat : @“hello %d”,5];
if([thing1 isEqualToString: thing2])
{
NSLog(@“They are the same! \n");
}
比较两个字符串还可以使用compare:方法,声明方法:-(NSComparisonResult) compare: (NSString *) aString; compare:将接收对象和传递过来的字符串逐个进行比较,它返回一个NSComparisonResult(一个enum型枚举)来显示比较结果。
== 和 isEqualToString: 的区别:==运算符只判断两个者的指针数值而不是它们所指的对象,isEqualToString:则是比较内容是否相同。因此当检查两个对象(thing1和thing2)是否为同一事物,就应该用==,如果要查看是否相等(内容),那么就要用isEqualToString: 。
不区分大小写的比较
声明方法:-(NSComparisonResult) compare :(NSString *) aString options: (NSStringCompareOptions) mask;
options 参数是一个掩位码,常用选项有:1.NSCaseInsensitiveSearch: 不区分大小写字符。2.NSLiteralSearch:进行完全比较,区分大小写字符。3.NSNumericSearch: 比较字符串的字符个数,而不是字符串值。
Eg: if([thing1 compare: thing2 options: NSCaseInsensitiveSearch | NSNumericSearch ] == NSOrderedSame )
{
NSLog(@“They match !!");
}
字符串内是否包含别的字符串
检查字符串是否以另一个字符串开头 :-(BOOL) hasPrefix: (NSString *) aString;
判断字符串是否以另一个字符串结尾 :-(BOOL) hasSuffix: (NSString *) aString;
Eg: NSString *fileName = @“draft-chapter.pages”;
if([fileName hasPreifx: @“draft”])
{//This is a draft.}
if([fileName hasSuffix:@“.mov”])
{//this is a movie}
5.NSArray数组
NSArray是一个Cocoa类,用来存储对象的有序列表。该类有两个限制:1.它只能存储OC的对象,而不能存储原始的C语言基础数据类型,入int,float,enum,struct和NSArray中的随机指针。2.不能存储 nil (对象的零值或NULL值),但是有方法可以避开这些限制。
通过类方法arrayWithObject:创建一个新的NSArray,发送一个逗号分隔的对象列表,在列表结尾添加nil表示列表结束。
NSArray *array = [NSArray arrayWithObject:@“one”,@“two”,@“three”,nil ];
使用字面量结果为 NSArray *array2 = @[@“one”,@“two”,@“three”]; 使用字面量的时候不需要在最后的补充 nil。
获取数组所包含的对象个数:-(NSUInteger)count; Eg: [array count];
获取特定索引处的对象: -(id) objectAtIndex : ( NSUInteger ) index; 通过字面量访问数组语法:id *myObject = array1[1];
切分数组
声明方法:-componentsSeparatedByString:
NSString *string = @“oop:ack:bork:greeble:”;
NSArray *chunks = [ string componentsSeparatedByString : @“:”];
string = [chunks componentsJoinedByString:@“ :-) “];
上述三行代码将会创建一个内容为”oop :-) ack :-) bork :-) greeble :-) “的NSString字符串。
NSMutableArray通过类方法arrayWithCapacity来创建新的可变数组:
+(id) arrayWithCapacity :(NUSInteger) numItems;
Eg : NUMutableArray *array = [ NSMutableArray arrayWithCapacity:17];
使用addObject:在数组末尾添加对象: -(void) addObject :(id) anObject;
6.枚举
通过objectEnumerator向数组请求枚举器: -(NSEnumerator *) objectEnumerator;
Eg : NSEnumerator *enumerator = [ array objectEnumerator ];
while(id thingie = [enumerator nextObject] ) { NSLog(@“I found %@“,thingie);}
从后向前浏览某个集合:reverseObjectEnumerator方法。在获得枚举器之后,便开始一个while循环,每次循环都向枚举器请求它的nextObject(下一个对象): -(id) nextObject; nextObject返回nil时,循环结束。
需要注意的是:对可变数组进行枚举操作时,不能通过添加或删除对象这类方式来改变数组的容量。
快速枚举(只能在 Mac OS X 10.5之后的版本使用):
for (NSString *string in array){
NSLog(@“ I found %@“,string); }
该循环的功能是遍历数组中的每一个元素,并用变量string来存储每个数值,它比枚举器语法更加简洁快速。
代码块(block),苹果公司添加了一个能在NSArray中通过代码块枚举对象的方法:
-(void) enumerateObjectsUsingBlock: (void (^) (id obj, NSUInteger idx, BOOL *stop))block 通过数组重写这个枚举方式:
[array enumerateObjectsUsingBlock : ^(NSString *string, NSUInteger index, BOOL *stop) {
NSLog(@“I found %@“, string ); } ];
通过代码块可以让循环操作并发执行,而快速枚举,执行操作要一项项的线性执行。
7.NSDictionary
在编程中,字典是关键字及其定义的集合。Cocoa中有一个现实该功能的集合类NSDictionary。它能在给定的关键字(通常是一个NSString字符串)下存储一个数值(可以是任何类型的OC对象),你可以使用该关键字查找相应的数据。字典使用键查询的优化方式,它比数组要快的多。
通过NSMutableDictionary类允许你随意添加和删除字典元素,在创建新的NSDictionary时,需提供该字典所存储的全部对象和关键字。
NSDictionary和NSArray只能存储对象,而不能直接存储任何基本的数据类型,如int,float,struct。当通过将数据封装到一个对象中的时候就可以将其放入到NSDictionary或NSArray中了。
NSUInteger是无符号的整型, NSInteger是有符号的整型,在表视图应用中常见 NSUInteger row= [indexPath row];因为这是显示tableViewCell有多少个,只能是非零整数的,也就是说,NSUInteger常用于索引值;int与NSInteger没有本质区别。
8. NSNumber
Cocoa提供了NSNumber类来封装(wrap,即以对象形式来实现)基本数据类型。使用以下方法创建NSNumber对象:
+(NSNubmer *) numberWithChar :(char) value;
+(NSNubmer *) numberWithInt :(int) value;
+(NSNubmer *) numberWithFloat :(float) value;
+(NSNubmer *) numberWithBool :(BOOL) value;
也可以使用字面量语法来创建着些对象:
NSNumber *number;
number = @‘X‘; //字符型
number = @12345; //整型
number = @12345ul; //无符号长整数
number = @12345ll; //long long
number = @123.45f; //浮点型
number = @123.54; //双浮点型
number = @YES; //布尔型
也可以使用字面量语法来创建着些对象:
NSNumber *number;
number = @‘X‘; //字符型
number = @12345; //整型
number = @12345ul; //无符号长整数
number = @12345ll; //long long
number = @123.45f; //浮点型
number = @123.54; //双浮点型
number = @YES; //布尔型
9.NSValue
NSNumber实际上是NSValue的子类,可以使用NSValue将结构体放入NSArray或NSDictionary中。NSValue声明方法:
+(NSValue *) valueWithBytes : (const void *) value objCType :(const char *) type;
Eg: NSRect rect = NSMakeRect(1,2,30,40);
NSValue *value = [NSValue valueWithBytes: &rect objCType:@encode(NSRect)];
[array addObject : value];
使用getValue来提取数值 : -(void)getValue:(void *) buffer;
Eg: value = [array objectAtIndex: 0]; [value getValue: &rect];
10.NSNull
声明方法: +(NSNull *) null;
按照以下方式将它添加到集合中:
[contact setObject : [NSNull nul] forKey :@“There is nothing”];
访问方式:
id homefax = [ contact objectForKey :@“There is nothing”];
if(home fax = = [NSNull null])
{ //…确认没有打印机后的行为 }
~~~~~~~
这一章里面太多的理论知识,对于我这种不善于记忆的人来说真是一种痛苦。。。
~~~~~~~