不知道大家是否有Java的使用经验,Java的容器类里有一种叫Map的接口,他保存的是一个个的键值对key-value,内部的键值对是无序排列的。当我们
需要使用某一个对象时只需要通过该对象的key就可以获得该对象。那么我们现在要讲的NSDictionary、NSMutableDictionary也和这个类似。首先我
们要讲的是是NSDictionary,他是一种不可变的字典,也就是说当一个字典创建初始化完毕后,就不能再改变其内容,即使在创建时初始化为空内容,
初始化完毕后也不能再被添加内容,好首先我们首先看看他的创建与初始化:
NSDictionary的创建也分为使用动态方法创建,和使用静态方法创建:
我们一般常使用以下方法创建并初始化一个NSDictionary对象:
NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:,,,,...,nil];//动态的创建并初始化一个有多个键值对的NSDictionary对象。
NSDictionary *dic = [NSDictionary dictionaryWithObject: forkey:]; //使用静态方法创建并初始化一个有一个键值对的NSDictionary对象。
NSDictionary *dic = [NSDictionary dictionaryWithObjects: ]; //使用静态方法创建并初始化一个有一个键值对的NSDictionary对象。
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:,,,,...,nil];//动态的创建并初始化一个有多个键值对的NSDictionary对象。
NSDictionary *dic = [NSDictionary dictionaryWithObjects:(NSArray*) forkeys:(NSArray*)];//动态的创建并初始化一个有多个键值对的NSDictionary对象。
关于具体的使用方法我们看示例代码:
1、获取键值对的数目: dic.count
2、比较两个NSDictionary的内容是否相等:[dic2 isEqualToDictionary:dic]
3、根据key获取到对应的value: [dic objectForKey:@"key"]
4、获取字典所有的key: [dic3 allKeys]
5、同一个value可以被多个key引用(反之不可以),此方法获取字典中某一个value的所有key: [dic allKeysForObject:@"value"]
6、获取字典中的所有value: [dic allValues]
具体使用方法看代码:
下面我们来讲解关于字典的遍历:
我们依旧通过for循环和block进行:
1、通过for循环遍历字典
for(id key in dic){
id obj = [dic objectForKey:key]; //获取value
}
2、通过block遍历字典
[dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
.......... //已经获取到了key以及value
//当执行*stop = YES时遍历停止
}];
3、通过迭代器遍历字典
NSEnumerator* enu = [dic keyEnumerator]; //获取字典的迭代器
id nowkey = nil;
while (nowkey = [enu nextObject]) { //当迭代到空时循环结束
id obj = [dic objectForKey:key]; //获取value
}
具体使用看示例代码:
关于NSDictionary的内存的管理,我在这里多说一句,其实我们无论是将一个对象当做key还是value来使用,一旦我们将它加入到
NSDictionary是就会被retain一次,当NSDictionary被销毁时,里面的每个对象都会被release一次,如果一个对象被使用多次,那
就会被引用几次就release几次。
接下来我们就介绍一下NSMutableDictionary,可变字典:
如果你读过我的上一篇博客《OC关于NSArray、NSMutableArray的使用》就会大致了解什么是可变、什么可变,我们上面已经介绍过
NSDictionary了,他就是不可变字典,也就是说在初始化完成后就不在可以向其中添加键值对或者移除键值对。而我们下面要讲的可变
字典就是在初始化完成后依旧可以添加或移除键值对。其实除此之外,NSDictionary与NSMutableDictionary之间并没有太大的区别,因此
我们就不再讲解关于NSMutableDictionary的创建与遍历等相同的操作:
首先介绍的是向NSMutableDictionary中添加一个键值对setObject: forKey:
下面就是addEntriesFromDictionary: 他是将一个NSDictionary的所有键值对都添加到NSMutableDictionary中,当然NSMutableDictionary
作为NSDictionary的子集也是可以作为参数,将其中的所有键值对添加到对象中去。
我们看代码:
下面我们讲解将键值对移除对象的主要方法:
首先我们能想到的最直观的就是根据一个键来删除一个键值对:removeObjectForKey:
当然我们也是可以通过一个键的列表来删除一组键值对:removeObjectsForKeys:
其实当我们想清空字典也是非常方便的:removeAllObject
看代码:
首先让我们来回忆一下OC中都有哪些基本数据类型:
----------------------------------------------
//整形(int、short int、long int、unsigned int、unsigned short、unsigned long)
NSLog(@"整形:");
NSLog(@"%lu",sizeof(int));//整形4个字节
NSLog(@"%lu",sizeof(short int));//短整形2
NSLog(@"%lu",sizeof(long int));//长整形8
NSLog(@"%lu",sizeof(unsigned int));//无符号整形4
NSLog(@"%lu",sizeof(unsigned short));//无符号短整形2
NSLog(@"%lu",sizeof(unsigned long));//无符号长整形8
//实形(float 、double 、long double)
NSLog(@"实形:");
NSLog(@"%lu",sizeof(float));//浮点形4
NSLog(@"%lu",sizeof(double));//双精度形8
NSLog(@"%lu",sizeof(long double));//长精度形16
//字符型和字符串形
char a='a';
char b=100;
NSLog(@"%c,%c",a,b);
NSLog(@"%i,%i",a,b);
NSLog(@"我是字符串");//字符串形:@“我是字符串”
----------------------------------------------
根据以上学习我们发现无论是NSArray、NSMutableArray还是NSDictionary、NSMutableDictionary都只能存放OC对象而不能存放基本数据类型,
这个时候问题就来了我们如何向NSArray、NSMutableArray、NSDictionary、NSMutableDictionary中存放基本数据类型呢?
熟悉Java的读者都可你一下子想到Java中有一个东西叫做包装类,包装类是个什么东西?其实他就是可以将一个基本数据类型包装成以及Java
对象,而且在jdk5中有添加了一个新特新(自动装箱与拆箱,额外扯一点其实Java的包装类采用了一种叫做“享元模式”的设计模式,有兴趣的
读者可以深入的了解一下),既然如此那么我们OC有没有类似的机制呢?当然有,只不过他现在还不支持自动装箱与拆箱:
下面我们来看一下经常见的初始化方法:
+(NSNumber*)numberWithInt: //包装int
+(NSNumber*)numberWithChar: //包装char
+(NSNumber*)numberWithFloat: //包装float
+(NSNumber*)numberWithBool: //包装bool
......
---------------------------------
拆包方法:
+(int)intValue //拆包int
+(char)charValue //拆包char
+(float)floatValue //拆包float
+(bool)boolValue //拆包bool
..........
然后就是比较方法:
-(NSComparisonResult*)compare:
-(bool)isEqualToNumber:
还有很多基本数据类型的操作,由于很是简单我就不再一一演示,大家可以以此类推。
下面是一个很简单的代码示例:
最后我们知道c语系里还有一个特殊的类型,说他特殊主要是因为他既不属于对象,也不是基本数据类型,他就是结构体struct。
那么既然他不是对象,那就说明他也是不能当做对象使用的,那么有没有用于包装结构体的包装类呢?当然有:
下面我们来介绍NSNumber的父类NSValue类,他可以包装任意类型(包括对OC对象的再次包装),那么他当然也是可以包装结构体的了。
我们如果使用特定的方法去包装框架自带的一些类型,由于有特定的包装方法,很是简单因此我们再此不再赘述,仅展示一个示例,
其他包装框架类的包装方法(解包方法)都可由此推出:
下面我们来重点介绍自定义类型的包装方案,大家思考如果我们根本不知道自定义类型的结构那我们有如何对自定义类型进行包装?因此
我们需要知道自定义类型的结构,可以通过一个字符串来描述类型结构,然后将自定义类型声明的变量的地址传过去就可以进行包装了。
在解包是就简单了,我们只需将需要接受结果的变量的地址传入,即可通过参数传值直接将结果返回:
看代码:
OK,今天我们要介绍的内容已经将的差不多了,希望对你有所帮助,共勉!