OC 知识点回顾
/*
字符串:
NSString 不可变字符串 字符串对象的内容不能修改,字符串的指针可以改变
NSMutableString 可变字符串 可以修改字符串对象的内容,继承自NSString ,具有所有的方法
*/
1.创建对象,实例方法和类方法
NSMutableString *mStr=[[NSMutableString alloc]initWithString:@"Hello World"];
2.将不可变字符串转换为可变字符串
NSMutableString *mStr2=[NSMutableString stringWithString:@"Hello"];
3.将C字符串转换为OC字符串
char *ch;
[NSString stringWithUTF8String:ch];
4.查找子字符串的范围
NSRange range=[mStr3 rangeOfString:@"beijing"];
//从后往前搜索/
NSRange rang=[path rangeOfString:@"/" options:NSBackwardsSearch];
NSRange range=NSMakeRange(1, 2);
5.将范围内的字符串删除
[mStr3 deleteCharactersInRange:range];
6.在指定范围内,将所有的子字符串用另一个字符串替换,查找时可设置选项
[mStr3 replaceOccurrencesOfString:@"a" withString:@"b" options:NSLiteralSearch range:NSMakeRange()];
[path stringByReplacingOccurrencesOfString:@"//" withString:@"/"];
7. 以/根目录开始的BOOL
[path hasPrefix:@"/"]
判断路径是否以/结尾
[path hasSuffix:@"/"]
8.
substringFromIndex
substringToIndex
9.获取文件扩展名
NSRange range=[path rangeOfString:@"." options:NSBackwardsSearch];
if (range.location!=NSNotFound) {
return [path substringFromIndex:range.location+1];}
10.比较大小
[s1 compare:s2];//区分大小写
[s1 caseInsensitiveCompare:s2]//忽略大小写
[s1 compare:s2 options:NSNumericSearch];//只会按照字符串中不同的数字大小决定字符串的大小
isEqualToString
11.转换为大小写
[s1 uppercaseString]
[s2 lowercaseString];
12.查找判定
rang.location!=NSNotFound
13.
unichar c=[str characterAtIndex:i];//倒置时有用
/*
NSNumber 数字类 将基本数据变量封装成数字对象 打包 装箱
*/
1.比较大小 NSNumber对象中数据的大小
NSComparisonResult res=[intNumber compare:floatNumber];
2.比较两个NSNumber 对象中数据是否相等
[intNumber isEqualToNumber:floatNumber]
/*
数组分类:
NSArray不可变数组,初始化数组对象后,数组中的元素不能修改(只能查询遍历)
NSMutableArray 可变数组,继承自NSArray,数组中的元素可以修改[增加,删除,修改元素和修改数据的内容]
*/
1.
OC中的数组是一个对象,是任意类型对象地址的集合
对象和数组都在堆里面,引用和基本数据类型放在栈里面
数组中可以存放任意类型的对象,但是不能存放基本类型的数据
2.
数组中的元素是有序的,可以重复
3.
id类型的引用,点语法就无法使用啦
4.
[array containsObject:obj]
5.
[array indexOfObject:@"four”]//获取下标
6.
NSEnumerator * enumerator=[array objectEnumerator];//遍历数组创建迭代器对象
id obj;
while (obj=[enumerator nextObject]) {
XXXXXXXXXXX
}
7.
removeObjectsInArray
removeObjectsInRange:range
removeObjectsInRange:range
8. 交换
[array1 exchangeObjectAtIndex:0 withObjectAtIndex:2];//交换元素
9.将数组中的各个元素用指定的字符串连接成一个行的字符串
NSString *s=[array componentsJoinedByString:@" "];
NSArray *a=[s componentsSeparatedByString:@"*"];
NSArray *a2=[s2 componentsSeparatedByCharactersInSet:[NSCharacterSet
characterSetWithCharactersInString:@"!*"]];
NSNull:相当于NULL,代表一个空类,只有一个类方法,获取一个空实例或者空对象
/*
多态:一种事物,多种形态,使不同的类共享相同方法名称———————多态
*/
1.
调用方法时,根据的是对象,不是指针
2.
父类的引用可以指向子类对象,赋值,兼容
3.
isMemberOfClass//判断是否属于XX类
isKindOfClass//判断是否是XX或其子类类型的对象 类本身也是一个对象
isSubclassOfClass//判断一个类是否是另一个类的子类
/*
继承的使用:当多个类有很多相同的代码时,可以将相同的部分提取出来写成父类
如果类A完全拥有类B的所有成员,可以考虑类A继承类B,也可以考虑组合
注意:子类中不能出现与父类相同的成员变量
子类的对象调用方法时,优先去子类中查找,再去父类中查找,如果存在就调用执行,不存在就出错
继承体现了类之间的关系,继承关系
继承的缺点:类之间的耦合型太强
*/
1.
@protected接口中定义的变量默认
@private//实现中默认是这种
@synthesize name=_name;//将属性和变量关联起来合成方法
2.
方法重写:子类中的方法头与父类的完全一致
3.
super:当子类重写父类的方法,又需要保留父类的某些功能时,采用super 调用
4.
- (id)init{}注意初始化方法,特别是对成员变量的初始化,如数组
/*
Category 类别 分类 类别,它不是类
在不改变原来类名的基础上,扩充某个类的功能。
将一个类的实现分为多个文件,每个文件都属于类的定义部分,多用于合作开发
只能增加方法,不能增加变量
*/
1.
主类和分类(类别)
2.
主类中的方法被类别中的方法覆盖(重写),无法再调用
3.
子类也可以继承扩展功能
4.
@interface 主类(分类名)
/*
Extension 相当于未命名的Category,可以给类增加方法,也可以增加成员变量,只有.h文件,方法的实现在主类中
*/
1.
@interface Person ()
-(void)play;
@end
/*
字典:读取网络数据,一般是字符串
NSDctionary 是一个集合对象,字典中的元素以键-值对的形式存在,元素是任意类型的对象
key 不能重复,value 可以重复,一般根据key 查找value
分为(元素必须是对象地址,不能使基本数据类型)
NSDctionary 不可变字典:字典初始化后不能修改其中的元素,只能访问
NSMutableDictionary可变字典:字典初始化后可以修改其中的元素,(增加,删除,修改)
大量数据用数组存储
*/
1.
快速创建子字典对象(先写键,再写值key:value)
NSDictionary *dict=@{@"1":@"one",@"2":@"two",@"1":@"one1",@"20":@"two",@"3":@"three"};
2.
取值(为无序的)
NSArray *allkeys=[dict allKeys];
NSArray *allValues=[dict allValues];//键重复的不会出现
for (NSString *key in [dict allKeys])//遍历字典很有用
3.
根据值获取所有对应的键
NSArray *keys=[dict1 allKeysForObject:@"two"];
可变字典
4.
将另一个字典中的元素加进来
[dict addEntriesFromDictionary:dict2];
[dict setDictionary:dict2];
5.
[dict setObject:@"five" forKey:@“5”]//设值或者修改
6.
删除
[dict removeObjectForKey:@"1"];
[dict removeObjectsForKeys:array];
/*
Class
类的本质也是一个对象 是Class类型的类对象,一个类只有一个类对象,所有的类都属于Class类型
*/
1.
获取类对象,可以给实例发送class消息,也可以给类发送class消息
2.
load 当程序启动是会加载所有的类,然后调用load方法,一般先调父类的方法
initialize 当这个类第一次使用时,会调用
/*
NSSet
集合对象,与数组类似,但是NSSet是无序的,不能存放重复的元素,唯一的索引
分为:
NSSet 不可变集合
NSMutableSet可变集合
*/
1.
#define ITOBJ(n) [NSNumber numberWithInt:n]
NSSet *set=[[NSSet alloc]initWithObjects:]
2.
获取两个集合的并集
[set2 unionSet:set1];
获取两个集合的交集
[set2 intersectSet:set1];
获取两个集合的差集//减去set2中相同的
[set2 minusSet:set1];
取出集合中任意一个元素,(主要应用于只有一个元素的集合)
id obj= [set anyObject];
将集合转换为数组
NSArray *array=[set allObjects];
/*
NSIndexSet
索引集合,唯一的整数集合
分为
NSIndexSet不可变:初始化时指定索引范围NSMakeRange
’NSMutableIndexSet可变:可以向其中添加不连续的索引 addIndex
*/
/*
NSValue
将结构体,指针变量封装成对象/取值
结构体是(基本类型),不能存放到数组中,需要将其封装成对象
*/
1.
将结构体变量封装成对象
struct mystruct sm={1,2};
NSValue *value=[[NSValue alloc]initWithBytes:&sm objCType:@encode(struct mystruct) ];
2.
取出NSValue中的结构体变量
struct mystruct sm2;
将value中的结构体变量取出来赋给sm2
[value getValue:&sm2];
3.
指针
NSValue *value=[[NSValue alloc]initWithBytes:&p objCType:@encode(char *) ];
4.
常见结构体(NSRect CGPoint NSPoint NSSize NSRange)
NSPoint pt=NSMakePoint(100, 200);
通过类方法将结构体变量封装成id对象
NSValue *value=[NSValue valueWithPoint:pt];
取出NSValue对象中的NSPoint的值
NSPoint pt2=[value6 pointValue];
/*
SEL
是一个类型,将方法封装成一个SEL的数据,可以根据封装的方法获取方法的地址,调用相应的方法
类似于c中的函数指针
封装当成实参
*/
1.
执行相应的sel对象
[obj performSelector:@selector(方法)];
2.
判断对象是否可以响应相关的方法
[obj respondsToSelector:@selector(方法)]) {
3.
带参
[obj performSelector:@selector(方法) withObject:argc];
4.
将字符串形式的方法封装成SEL类型的数据
SEL sel=NSSelectorFromString(@“方法名”);
5.
对不可变数组的排序
[array sortedArrayUsingSelector:(SEL)];
[array sortUsingComparator:块]
/*
NSDate
时间日期类
*/
1.
NSDate * date=[NSDate new];
NSDate * date1=[[NSDate alloc]init];
NSDate * date2=[NSDate date];
2.
NSTimeInterval interval=[date2 timeIntervalSinceDate:date1]
3.
格式化日期类
NSDateFormatter *formatter=[[NSDateFormatter alloc]init];
设置日期和时间的显示样式
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
NSString * sDate=[formatter stringFromDate:date];
自定义格式字符串
[formatter setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
NSString * s=@"2015-11-11 10:10:10";
NSDate *date=[formatter dateFromString:s];
/*
NSFileHandle
对文件进行读写操作的类
*/
1.
NSData *da=[str dataUsingEncoding:NSUTF8StringEncoding];
2.
读取
NSFileHandle *readHandle=[NSFileHandle fileHandleForReadingAtPath:@""];
NSData *data=[readHandle readDataToEndOfFile];
写入
NSFileHandle *writeHandle=[NSFileHandle fileHandleForWritingAtPath:@""];
清空文件内容
[writeHandle truncateFileAtOffset:0]
[writeHandle writeData:data]
3.
设置读取文件开始的偏移值
[writeHandle seekToEndOfFile]
4.
[writeHandle closeFile];
/*
NSFileManager
文件管理,单例类,对文件/目录进行管理的类(创建,copy,delete,move)
*/
1.
类方法获取单例对象
NSFileManager * manager=[NSFileManager defaultManager];
2.
判断文件(夹)是否存在
BOOL res=[manager fileExistsAtPath:@"/test.txt" ];
BOOL isDir;
BOOL res=[manager fileExistsAtPath:@"/test.txt" isDirectory:&isDir];
3.
拷贝(如果目标目录中已经出现同名的文件,将会出错)
copyItemAtPath toPath
文件重命名:如果文件处于同一目录下就是重命名,如果不在同一个目录下,移动(并重命名)
移动文件,一定要指定移动的目标目录的文件名(目录路径不能只写到目录)
moveItemAtPath toPath
删除指定路径下的文件
removeItemAtPath
获取指定路径下的文件的属性,返回字典
manager attributesOfItemAtPath
属性:NSFileSize NSFileType
ej:[dict objectForKey:NSFileSize]
4.
获取当前路径,该应用生成的可执行文件的路径
NSString *path=[manager currentDirectoryPath];
5.
创建指定路径下的目录,
第二个参数是当目标目录的上级目录不存在的时候是否需要也要创建出来,
第三个参数是创建目录的初始化属性,
第四个参数是创建过程中有木有放生错误。
res=[manager createDirectoryAtPath:@"test/a/b/c" withIntermediateDirectories:YES attributes:nil error:nil];
6.
浅遍历,返回当前目录下的子目录和文件名,数组(都是相对路径,只是深度只有本目录,一层)
NSArray *array=[manager contentsOfDirectoryAtPath:@"Manager/test" error:nil];
深遍历:返回以当前目录为参照,当前目录下所有的子目录(以及子目录下的目录和文件,多层),和文件名,(以当前目录的基准的路径名)
其中都是相对路径===========如需访问,需要拼接父目录
NSArray * array=[manager subpathsOfDirectoryAtPath:@"eManager/test"error:nil];
7.
获取当前路径,该应用生成的可执行文件的路径
NSString *path=[manager currentDirectoryPath];
res=[manager fileExistsAtPath:@"oc.txt"];
8.
获取文件内容
NSData 当将数据写入文件或传输到网络,从网络获取数据,需要将其转换为纯粹的二进制字节流NSData,相当于c中的
char buf[128],作为数据的缓冲区
NSData * contents=[manager contentsAtPath:@“/Manager/2.txt"];
NSData->NSString
NSString *str=[[NSString alloc]initWithData:contents encoding:NSUTF8StringEncoding];
将内容字符串一次性的写入文件
NSString * str2=@"beijing shanghai shenzhen";
NSString->NSData
NSData *data=[str2 dataUsingEncoding:NSUTF8StringEncoding];
创建文件时指定文件内容
res=[manager createFileAtPath:@“/Manager/1.txt" contents:data attributes:nil];
readFromFile
1.initWithContentsOfFile/stringWithContentsOfFile
2.NSFileHandle->fileHandleForReadingAtPath->readHandle->[readHandle readDataToEndOfFile];
3.NSData * contents=[NSFileManager contentsAtPath:@“/Manager/2.txt"];
//NSData->NSString
NSString *str=[[NSString alloc]initWithData:contents encoding:NSUTF8StringEncoding];
writeToFile
1.NSString
2.NSFileManager createFileAtPath
3.NSFileHandle->fileHandleForWritingAtPath->writeHandle->[writeHandle writeData:data];
4.NSMutableArray writeToFile atomically是否中间使用缓存文件,及备份文件
5.字典的写必须其中的对象全部为字典对象,或者字典数组
/*
单例
是一种编程思想,与语言无关
是一种常见的设计模式,在采用单例模式的应用中,单例对象的类必须保证只有一个实例存在,自行实例化,并向整个应用程序提供使用
对一个单例类,不论实例化多少次,都只有一个对象存在,而且能被整个应用程序访问,类似于全局变量可以在整个项目中共享数据
@synchronized(self) 实现数据同步
本质是里面有一个静态的变量在里面,单例的生命周期和应用相同
手动内存管理中单例对象的内容不需要释放
1 单例类只有一个实例存在
2.类方法获取对象
3.单例对象相当于全局变量使用共享数据
*/
1.
获取单例对象的方法一般以default/shared/current/standedXX开头
/*
文件存储
通过文件实现持久化存储
*/
1.
将数据写入文件
-(void)writeToFile:(NSString *)file;
从文件获取数据
-(void)readDataFromFile:(NSString *)file;
/*
文件归档:
归档是一个过程,用某种格式保存对象,以便以后还原对象,这个过程包括将(多个)对象写入文件,以后在从文件读取
(1)将对象归档为pList文件.(数组或字典对象,元素只能是NSString NSNumeber BOOL NSDate NSData类型)
(2)自定义对象使用归档器归档,归档协议—>统一接口
*/
/*
NSKeyedArchiver:对自定义的对象编码归档
编码:就是将对象的成员变量转换为文件可以识别和存储的类型
NSKeyedArchiver创建带键的档案
归档是对每个字段设置一个key
从文档中读取数据时,在根据key取值
可以对数组,字典,自定义的对象归档
组合类的解归档都要遵守归档协议NSCoding
NSKeyedUnarchiver: 解归档
*/
1.
对数组对象归档
BOOL [NSKeyedArchiver archiveRootObject:array toFile:@“1.data"];
2.
从文档中读取对象
NSArray *array=[NSKeyedUnarchiver unarchiveObjectWithFile:@"1.data"];
3.
如果自定义的对象需要归档,必须遵守归档协议
解归档时,调用此方法给对象初始化
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];//如果父类也遵守归档协议self=[super initWithCoder:aDecoder]
if (self) {
_name=[aDecoder decodeObjectForKey:@"name"];
}
return self;
}
在归档时自动调用此方法,对对象的成员变量转化为可以识别的编码类型
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
}
/*
Protocol:协议
@protocol 关键字 协议名字<基协议> 类似实现多继承
约定方法,统一接口
协议不引用任何类,它是无类的(classless)
定义了协议的类可以看做是将协议定义的方法代理给了实现他们的类,这样,类的定义就可更加通用啦
协议中只能有方法的声明,不能定义成员变量
@optional 非正式协议(其实是一个分类,也叫抽象协议)可选的
@required 默认是必须实现的
*/
1.
方法中参数定义
id<Protocol>:限定id类型,表示obj可以指定任意类型的对象,但是这个对象必须遵守Protocol协议
可以用来当做函数形参,限制了形参传递的类型
2.
判断obj5对象是否遵守这个协议
if ([obj conformsToProtocol:@protocol(MyProtocol)]) {
判断obj5所在的类是否实现了方法
if ([obj respondsToSelector:@selector(test)]) {
[obj test];
}
}
3.
协议可以统一接口
继承和协议都可以统一接口
继承:子类继承父类的方法,子类和父类的方法名一样,(除非父类的方法不适合子类,子类会重写,重写后的方法名与父类中的方法名还
是一样),达到了同一接口的目的,子类可以继承父类的成员变量
协议:一个类遵守协议,这个类就拥有了协议中的方法,如果多个类遵守一个协议,这些类都拥有协议的方法,方法名都一样,实现了统一
接口的目的,协议中不能有成员变量(未命名类别extension)
4.
一个类可以遵守多个协议。
一个协议可以遵守另一个协议
/*
内存管理:
OC中内存管理主要是对对象管理(凡是继承于NSObject),对基本类型无效
OC中内存广利采用的是引用计数器,ARC自动引用计数
分为ARC(automatic reference counting)和MRC(manual reference counting)
实际上是一个整数,表明对象的引用次数(有多少个人在使用它),
每个对象都有一个引用计数器,会分配4字节的空间存储
当采用alloc或者new,copy[mutablecopy]新创建一个对象时,引用计数器的默认值是1
当引用计数器值为0时,该对象会被释放,所占内存会被回收,也就是说,当一个对象的引用次数 值不为0时,会一直存在,除非程序退出
给对象发送retain消息,使引用计数器值+1,方法返回对象本身
给对象发送release消息,引用计数器-1
给对象发送retainCount消息,可以获得引用计数器的值
当引用计数器值为0时,对象会被释放,会自动发送dealloc消息,一般重写dealloc方法,释放相关资源,一旦重写dealloc方法,一定要
调用[super dealloc] 一般放在最后,dealloc方法是自动调用的,不能手动调用
*/
1.
内存管理-黄金法则
如果对一个对象使用了alloc、[mutable]copy、retain,那么你必须使用相应的release或者autorelease配对操作
2.
引用计数: retainCount
3.
OC中可以给空引用发送消息,nil,(类似于C语言不能对空指针操作)
4.
已经被释放内存的对象为僵尸对象,给僵尸对象发送的消息会出现错误
message send to deallocated instance
指向一个已经释放对象的内存,(不可用)的指针叫野指针,对野指针 操作会出现问题,可以给引用赋值nil
5.
assign:
-(void)setBook:(Book *)book{
_book=book;
}
retain:
-(void)setBook:(Book *)book{
if (_book!=book) {
[_book release];
_book=[book retain];
}
}
析构函数
- (void)dealloc{
[super dealloc];调用父类的方法,一般放在最后
}
6.
创建数组用对象初始化时,会给对象的引用计数器+1
向数组中添加元素时,会给对象的引用计数器+1
从数组中删除元素时,会给对象的引用计数器-1
当数组释放时,会给其中所有的对象发送release 消息
7.
循环引用:
在ARC中
如果出现两个对象的两个指针相互引用,会出现内存泄露,内存管理的基本法则也不适用
解决方法:将一端适用retain 另一端使用assign
声明属性:对象用strong weak(很少用)
基本类型有assign
8.
ARC环境下,与内存管理相关的代码都不能调用,自动释放对象
什么时候被释放,看对象是否有强引用指向
强引用strong:默认的指针都是强引用
弱引用weak:__weak 马上会被释放
属性的声明:
strong 自动ARC下对象的引用
retain 非ARC下对象的引用
对于非ARC环境下的文件,右键build phases,compiler flags添加以下命令
-fno-objc-arc
9.
对引用计数器的改变
1.retain 2.release
一般不使用autorelease
autorelease 延迟释放,将对象加入最近的(栈顶)的自动释放池中,当池子被销毁时,会给池子中所有的对象发送release消息。
autorelease方法返回对象本身,给对象发送autorelease 消息后,对象的引用计数器不变
好处:不用担心对象的释放时间
坏处:对于大对象不能够精确控制对象的释放时间
除非万不得已,不要使用autorelease,建议使用release
自动释放池:
IOS5.0后@autoreleasepool{}
IOS5.0之前
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];
**
中间是管理的对象的代码
**
[pool release];
10.
@class
1.解决头文件互相包含
2.只知道引用了一个类,不关心内部结构,提高效率
3.如果要使用成员,就必须import
/*
代理:
真正的实现者,编程思想
个人理解:
用户是主动方(可以将协议放在制定协议的一方(主动方))
需求(协议)
开发人员就是代理,根据需求(协议)设计不同的方法
*/
1.
使用协议,类可以单独存在,降低和其他类之间的耦合性,限定符
@property(nonatomic,strong)id<protocol> delegate;
2.
在代理模式中,会出现两个对象的指针互相引用,会造成内存泄露。
一般将delegate设置为assign(weak),内存管理中没有强指针指向时就会被释放。
一般主动方会作为被动方的成员存在,主动方在,被动方就存在,采用strong标记。
代理调用的是协议方法,降低类之间的耦合性。
/*
复制对象:
mutableCopy Copy
1.字符串
无论原对象是可变不可变:
给字符串对象发送copy 消息,得到的是一个新的不可变对象
给字符串对象发送mutableCopy 消息,得到的是一个新的可变对象
2.自定义对象
3.数组
*/
1.
编译的时候就知道它的类型啦,静态编译
声明为id类型,运行时才会确定指向的对象类型,动态编译。
2.
浅拷贝:只是拷贝数组对象,数组中的元素没有拷贝.
深拷贝:不只是拷贝数组对象,数组中存储的元素也拷贝.
3.
如果需要copy ,必须遵守NSCopying协议
一般对象用retain(手动),strong(自动),字符串使用copy
4.
retain:共享对象
-(void)setName:(NSString *)name{
if(_name!=name){
[_name release];
_name=[name retain];
}
}
copy:创建新对象
-(void)setName:(NSString *)name{
if(_name!=name){
[_name release];
_name=[name copy];
}
assign:
-(void)setName:(NSString *)name{
_name=name;
}
5.
给对象发送copy消息时,会调用此协议方法
-(id)copyWithZone:(NSZone *)zone{
[self class]获取当前的类对象,如果是父类调用,得到的是父类的对象,如果是子类,获得的就是子类的对象
Car *car=[[[self class] allocWithZone:zone]init];对于继承时,很有用
}
-(id)mutableCopyWithZone:(NSZone *)zone{
Car *car=[[Car allocWithZone:zone]init];
}
/*
Json解析:
格式的数据:有两种结构组成
键-对象(字典) 键都是字符串("":..... , "":.....)
对象的集合:(数组) (, , , ,)
*/
1.
将json对象解码成对象
[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err];
2.
将对象编码成json对象(字典)
[NSJSONSerialization dataWithJSONObject:dict options:NSJSONReadingMutableLeaves error:nil];
/*
XML解析:
xml:extensible markup language :可扩展的标记语言 ,用于存储传输数据
xml数据的解析有两种:
DOM解析:直接将xml数据加载到内存,从根节点开始,取子节点,一级一级的解析,比较占内存
SAX解析:基于事件驱动的,读取xml数据就是解析的过程,速度较快,只是读取不能修改
采用GData第三方库解析,使用的是DOM解析的方式,调用底层的libxml2库文件
(1)导入GData文件
(2)设置头文件的搜索路径,选中项目->Build Setting ->Header Search Path 双击,单击+,输入/usr/include/libxml2
(3)加入底层文件libxml2 选中项目->Build Phases,Link Binary With Libraries,单击+,添加libxml2
XPath表达式:快速定位到某个标记
/表示从根标记开始
//表示任意位置的标记,满足条件
.表示当前标记
@表示属性对象
*/
路径
path=[path stringByAppendingPathComponent:subPath];
pathExtension lastPathComponent lastPathComponent isAbsolutePath