------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
集合(有序数组NSArray,无序数组NSSet,无序字典NSDictionary )
NSMUtableArray 是 NSArray 的子类;
NSArray
NSArray是OC的数组,以面向对象的形式操作数组.
NSArray是OC的有序数组,可以存储任何类型的OC对象,但是不能储存nil、int、float、enum、struct等类型的数据
NSArray是不可变数组.数组元素在创建数组时就被确定.数组创建后不可添加/修改/删除元素.除非把指针指向一个新数组
创建
创建一个空数组
NSArray *array = [NSArray array];
创建一个有一个元素的数组
array = [NSArrayarrayWithObject:@"123"];
创建一个有多个元素的数组
array = [NSArrayarrayWithObjects:@"A", @"B", nil];
使用nil来标记数组的结束.这个数组有两个元素.注意不要写两个nil.
任何OC对象都可以放到NSArray中,不需要是同一类型的对象
array = [NSArray arrayWithObjects:person, dog, book, nil];
使用编译器特性来方便快速的创建数组
NSArray *array =@[@"Jack", @"Rose", @"123"];
NSArray *array =@[person, dog, book];
注意
1 使用@开头
2 末尾不加nil
3上面的数组创建好之后就不可以再修改内容了,比如第一个创建的array只能是空数组,不能够往里面存放内容。
遍历数组
1 for循环
count = array.count;
for (int i = 0; i < count; i++)
{
id obj = [array objectAtIndex:i];
NSLog(@"%d: %@", i, obj);
}
2快速遍历
for (id obj in array)
{
unsigned long i = [array indexOfObject:obj];
NSLog(@"%lu: %@", i, obj);
}
3 使用block:
[array enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) { ... }];
这个方法对每一个元素都调用一次block,可以在block内写代码对元素进行运算。
非常方便,既有obj,又有index,而且还可以设置stop随时终止遍历.
如何在for循环中终止遍历?使用break;
如何在block遍历中终止遍历?修改stop的值.
为什么stop要使用星号,是 BOOL指针类型呢?
因为在函数内部需要修改这个*stop的值.也就是说,本来*stop的值是NO,如果需要停止,就需要修改*stop的值为YES.既然要修改外部参数的值,就需要使用指针才能修改.
使用举例:
使用block输出数组中前两个元素的值
[array enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) { //遍历数组
NSLog(@"%lu: %@", idx, obj);
if (idx == 1) {
*stop = YES; //修改*stop的值退出遍历
}
}];
// 数组的建立,数元素,打印某个元素,某个数组,数组遍历
int main()
{
Person *p = [Person new];
NSArray *array = [NSArray arrayWithObjects:@"jack",@"rose",p,nil]; // 多元素必须以nil结束
NSArray *array1 = @[@"m1",@"m2",@"m3"]; // 另外一种快速建立数组的方式
NSLog(@"%ld",array.count); //数数数组有多少元素
NSLog(@"%@",array[1]); // 取出某个元素
// 遍历数组,对象打印出来是类名+对象地址
for (int i = 0;i<array.count;i++)
{
NSLog(@"%@",array[i]);
}
// 快速遍历1
for (id obj in array)
{
int i = (int)[array indexOfObject:obj];
NSLog(@"%d-%@",i,obj);
}
// 快速遍历2
// 遍历一个元素就调用一次block,然后把元素和索引当作参数传给block
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%ld,,,%@",idx,obj);
// 停止遍历
if (idx == 1)
{
*stop = YES;
}
}];
return 0;
}
NSMutableArray
NSMutableArray是NSArray的子类,是可变数组,可以修改存放的内容。
创建
NSMutableArray *mArray = [NSMutableArray arrayWithObject:@"1"];
修改元素
添加:
[mArray addObject:@"2"];
[mArray insertObject:@"3" atIndex:0];
删除:
[mArray removeObject:@"2"];
[mArray removeObject:@"2" inRange:range];
[mArray removeObjectAtIndex:1];
[mArray removeLastObject]
[mArray removeAllObjects];
[mArray removeObjectsInRange:range];
[mArray removeObjectsInArray:array]; //删除和array共有的元素
替换:
[mArray replaceObjectAtIndex:0 withObject:@"100"];
[mArray replaceObjectsInRange:range withObjectesFromArray:array];
[mArray exchangeObjectAtIndex:1 withObjectAtIndex:3];
int main()
{
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"jack",@"milk",@"like",nil];
// NSMutableArray *array1 = @[@"apple",@"juice"]; // 这样写不对,因为,只有不可变数组有这种方法,可变的只能用上边这种发方法
[array addObject:@"love"];
[array removeObject:@"milk"];
NSLog(@"%ld",array.count);
NSLog(@"%@",array);
return 0;
}
NSSet
NSSet和NSArray的最大区别是,NSArray的数据是有序存放的,NSSet的数据是无序存放的。
NSSet中也只能存放OC对象类型,不能存放基本类型的数据,不能存放nil,仅仅使用nil作为元素结束的标记。
创建
NSSet *set = [NSSet set]; //空的set
set = [NSSet setWithObject:@"Jack"]; //有一个元素的set
set = [NSSet setWithObjects:@"Jack", @"Rose", nil]; //有多个元素的set
set = [NSSet setWithSet:set2]; //一个和另一个set一样的set
set = [NSSet setWithArray:myArray]; //使用一个数组中的元素来创建set
常用方法
unsigned long n = set.count; //获得元素的个数
id anyObj = [set anyObject]; // 随机获取某个元素
NSMutableSet
添加数据
[set addObject:@"Jim"];
移除数据
[set removeObject:@"Jim"];
[set removeAllObjects]
NSDictionary
创建
1空字典 NSDictionary *dict = [NSDictionary dictionary];
2有一组数据的字典 dict = [NSDictionary dictionaryWithObject:@"apple(obj)"forKey:@"red(key)"];
3有多组数据的字典:
方法一:
NSArray *objectArray = @[@"apple", @"banana", @"orange"];
NSArray *keyArray = @[@"red", @"yellow", @"orange"];
dict = [NSDictionary dictionaryWithObjects: objectArray forKeys:keyArray];
第一个参数是objects数组,第二个是keys数组,二者的内容一一对应。
方法二:
dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"obj1apple", @"k1red",
@"obj2banana", @"k2yellow",
@"obj3orange", @"k3orange", nil];
对每一组数据,先写value再写key,要以nil结束。
使用编译器特性快速创建:
dict = @{@"name":@"jack", @"address":@"beijing"};
格式: @{ key1 : obj1, key2 : obj2, ...};末尾不用添加nil
注意:这样创建的字典是不可变字典
字典的遍历
1经典遍历
因为字典不能通过index取出key或者value,可以提前把allKeys取出来放在一个数组中,再进行遍历:
NSArray *keys = [dict allKeys];
for (int i = 0; i < dict.count; i++)
{
NSLog(@"%@ = %@", keys[i], dict[key[i]]);
}
2快速遍历
for (id key in dict)
{
id obj = [dict objectForKey:key];
NSLog(@"%@ = %@", key, obj);
}
遍历的是字典的所有keys,因为每个key都是不同的,根据key可以找到对应的object。但是object可能是相同的,不能根据object找到唯一对应的key。
3 Block遍历
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
NSLog(@"%@ = %@", key obj);
}
];
对每组键值对调用一次block
NSMutableDictionary
NSMutableDictionary是NSDictionary的子类,它创建的字典可以添加/修改数据。
添加元素
[dict setObject:stu forKey:@"stu"];
如果字典中已经有这个key了,就会把它的值修改为stu。如果字典中没有这个key,就会添加这组数据。
[dict addEntriesFromDictionary:dict2];
把另一个字典中的所有内容添加到这个字典中。
删除元素
[dict removeAllObjects]; //删除所有数据
[dict removeObjectForKey:@"red"]; //删除这个key对应的这组数据。如果字典中没有这个key,不会报错
[dict removeObjectsForKeys:keysArray]; //删除数组中所有keys对应的数据
/*
集合
1.NSArray\NSMutableArray
* 有序
* 快速创建(不可变):@[obj1, obj2, obj3]
* 快速访问元素:数组名[i]
2.NSSet\NSMutableSet
* 无序
3.NSDictionary\NSMutableDictionary
* 无序
* 快速创建(不可变):@{key1 : value1, key2 : value2}
* 快速访问元素:字典名[key]
*/
#import <Foundation/Foundation.h>
int main()
{
NSArray *persons = @[
@{@"name" : @"jack", @"qq" : @"432423423", @"books": @[@"5分钟突破iOS编程", @"5分钟突破android编程"]},
@{@"name" : @"rose", @"qq" : @"767567"},
@{@"name" : @"jim", @"qq" : @"423423"},
@{@"name" : @"jake", @"qq" : @"123123213"}
];
//
// NSDictionary *jim = persons[2];
//
NSString *bookName = persons[0][@"books"][1];
NSLog(@"%@", bookName);
//NSArray *array = persons[0][@"books"];
//NSLog(@"%@", array);
// 先取出1位置对应的字典
// 再取出字典中qq这个key对应的数据
//NSLog(@"%@", persons[1][@"qq"]);
// NSLog(@"%@", jim);
return 0;
}
void use4()
{
// 字典不允许有相同的key,但允许有相同的value(Object)
// 字典的无序的
NSDictionary *dict = @{
@"address" : @"北京",
@"name" : @"jack",
@"name2" : @"jack",
@"name3" : @"jack",
@"qq" : @"7657567765"};
// NSArray *keys = [dict allKeys];
//
// for (int i = 0; i<dict.count; i++)
// {
// NSString *key = keys[i];
// NSString *object = dict[key];
//
//
// NSLog(@"%@ = %@", key, object);
// }
[dict enumerateKeysAndObjectsUsingBlock:
^(id key, id obj, BOOL *stop) {
NSLog(@"%@ - %@", key, obj);
// *stop = YES;
}];
}
void use3()
{
NSMutableDictionary *dict = @{@"name" : @"jack"};
[dict setObject:@"rose" forKey:@"name"];
}
void use2()
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// 添加键值对
[dict setObject:@"jack" forKey:@"name"];
[dict setObject:@"北京" forKey:@"address"];
[dict setObject:@"rose" forKey:@"name"];
// 移除键值对
// [dict removeObjectForKey:<#(id)#>];
NSString *str = dict[@"name"];
//NSLog(@"%@", str);
NSLog(@"%@", dict);
//NSLog(@"%@", @[@"jack", @"rose"]);
}
void use()
{
/*
字典:
key ----> value
索引 ----> 文字内容
里面存储的东西都是键值对
*/
// NSDictionary *dict = [NSDictionary dictionaryWithObject:@"jack" forKey:@"name"];
// NSArray *keys = @[@"name", @"address"];
// NSArray *objects = @[@"jack", @"北京"];
// NSDictionary *dict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
/*
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"jack", @"name",
@"北京", @"address",
@"32423434", @"qq", nil];*/
NSDictionary *dict = @{@"name" : @"jack", @"address" : @"北京"};
// id obj = [dict objectForKey:@"name"];
id obj = dict[@"name"];
NSLog(@"%@", obj);
// 返回的是键值对的个数
NSLog(@"%ld", dict.count);
}
int main()
{
NSArray *array = @[
@{@"name":@"jack",@"book":@[@"5fenzhong",@"6fenzhong"]}, // 数组里边包含字典,字典里再来个数组
@{@"name":@"milk"},
@{@"name":@"sike"}
];
NSLog(@"%@",array[0][@"book"][1]);
}
类(NSNumber NSValue NSDate)
NSNumber
把基本数据类型包装成NSNumber对象
各种基本数据类型的数据都可以包装成NSNumber对象
[NSNumber numberWithBool];
[NSNumber numberWithChar];
[NSNumber numberWithInt];
[NSNumber numberWithLong];
[NSNumber numberWithFloat];
[NSNumber numberWithDouble];
使用编译器特性快速包装基本数据类型
编译器特性:可以使用 @快速把基本数据类型转换成NSNumber类型
比如:
@20 - 把int类型转换成NSNumber类型的对象
@10.5 - 把double类型转换成NSNumber类型的对象
@YES - 把BOOL类型转换成NSNumber类型的对象
@'A' - 把char类型转换成NSNumber类型的对象
@"A" - 注意区分,这个是NSString类型的对象
如果使用变量,要使用小括号把变量名括起来(否则会被误当成关键字)
比如:
int age = 20;
NSNumber *n = @(age);
把NSNumber对象还原成基本数据类型
可以把NSNumber对象转换成各种的基本数据类型
[num boolValue];
[num charValue];
[num intValue];
[num shortValue];
[num longValue];
[num unsignedIntValue];
[num unsignedLongValue];
[num floatValue];
[num doubleValue];
字符串转换成基本数据类型
字符串其实也有类似的方法:
NSString *str = [NSString stringWithFormat:@"%d", 10];
int a = [str intValue];
NSString *str2 = @"3.5";
double d = [str2 doubleValue];
NSValue
NSValue能够把各种类型的数据包装为对象,NSNumber其实是它的子类。
系统自带结构体包装成NSValue类型的对象
如果我们想把结构体放到集合中,就需要把结构体包装成OC对象:
[NSValue valueWithPoint: ];
[NSValue valueWithRect: ];
[NSValue valueWithSize: ];
[NSValue valueWithRange: ];
NSValue对象还原成结构体
[value pointValue];
[value rectValue];
[value sizeValue];
[value rangeValue];
任何类型包装成NSValue类型的对象
举例:
typedef struct {int year, month, day;} Date;
Date date = {2014, 3, 5}; //要包装的数据
char *type = @encode(Date); //把数据的类型转换为字符串
NSValue *myDate = [NSValue value:&date withObjCType:type]; //包装成NSValue对象
它的第一个参数的类型是void *,表示可以接受任何指针类型,id == void *
如何解包
Date date1; // 存储数据的变量
[myDate getValue:&date1]; //取出包装的结构体,并赋值给date1
NSDate
NSDate是用来表示日期和时间的类。
创建
当前时间:
NSDate *date = [NSDate date]; // date是执行这行代码时的时间
NSLog(@"%@", date); //打印date时默认打印格林尼治时区的时间
以当前时间为基准,n秒后的时间:
date = [NSDate dateWithTimeIntervalSinceNow:10];
比现在的时间快10秒的时间(未来的时间)
以1970年初零点为基准,n秒后的时间:
date = [NSDate dateWithTimeIntervalSince1970:1000];
以最近年初零点为基准,n秒后的时间:
date = [NSDate dateWithTimeIntervalSinceReferenceDate:1000];
以某个时间为基准,n秒后的时间:
NSDate *date2 = [NSDate dateWithTimeInterval:10 sinceDate:date]
表示比date这个时间晚10秒钟的那个时间(未来的时间)
遥远未来的某一天:
date= [NSDate distantFuture];
调试时貌似总是固定的一天,但是运行时也有可能是随机的一天。
遥远过去的某一天:
date2= [NSDate distantPast];
日期格式的字符串
在手机上显示日期需要转换成字符串,可以按照指定的格式转换
需要一个日期格式类:
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
设置格式:
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
大写M代表月,小写m代表分钟
大写H代表24小时制时间,小写h代表12小时制时间
根据格式把日期转换成字符串:
NSString *str = [formatter stringFromDate:date]; //把date转换成字符串
根据格式把字符串转换成日期:
NSDate *date = [formatter dateFromString:str]; //把符合格式的字符串转换成日期
如果字符串的日期格式不同,就设置一个相应的dateFormat
NSString *s = @"2011/09/10 18:56"; //某种格式的日期和时间
formatter.dateFormat = @"yyyy/MM/dd HH:mm"; //设置对应的格式
NSDate *date = [formatter dateFromString:s]; //就可以转换成NSDate对象了
NSLog(@"%@", date); //查看返回的日期
结构体
NSRange
1.概况
NSRange用来表示A在B中所占的范围。
它有两个成员, location和 length,它们的类型都是NSUInteger (unsigned long)。
比如:字符串@"Hello world!"中, "world"这几个字符的范围: location = 6, range = 5。
2.创建NSRange类型的变量
NSRange r; r.location = 2; r.length = 3; //定义变量后分别给成员赋值
NSRange r1 = {2, 3}; //初始化,前面是location,后面是length
NSRange r2 = {.location = 2, .length = 3}; //初始化,顺序无所谓
NSRange range = NSMakeRange(2, 3); //(使用函数创建)最常用的方式,前面是location,后面是length
注意:NSRange是使用了typedef的结构体类型,不是类,所以定义变量时不用加星号。
3.查看子字符串在主字符串中的位置
举例:
NSString *str = @"hello world!";
NSRange range = [str rangeOfString:@"world"];
NSLog(@"Range: %@", NSStringFromRange(range));
4.快速方便的打印属性值
使用点属性打印属性值很不方便,尤其是当属性很多时
NSLog(@"location: %zi", range.location);
NSLog(@"length: %zi", range.length);
可以转为字符串再打印,可以方便的查看所有属性的值:
NSString *str_range = NSStringFromRange(range);
NSLog(@"%@", str_range); //打印结果为 {8, 10}
CGPoint、CGSize、CGRect
前述
CGPoint, CGSize, CGRect和 NSPoint, NSSize, NSRect是完全等价的.
CG代表CoreGraphics. NS代表NextStep.
通常使用CGXxxx,因为它跨平台 (iOS和Mac平台).使用它的类和方法时需要链接CoreGraphics框架. Foundation里有它们的声明,但是函数的实现是在CoreGraphics框架里.
1简介
CGPoint代表图像中一个元素的位置,它有两个成员 x和 y,类型都是 CGFloat (double)。
CGSize代表一个元素的尺寸,它有两个成员 width和 height,类型都是 CGFloat。
CGRect代表一个矩形,它有两个成员 CGPoint origin 和 CGSize size,前者代表矩形左上角的坐标位置,后者表示矩形的宽和高。
2创建变量
1>使用创建一般结构体的方式创建:
CGPoint p = {10, 20}; CGPoint p2; p2.x = 10; p2.y = 20;
CGSize s = {30, 50}; CGSize s2; s2.width = 30; s2.height = 50;
CGRect r = {{10, 20}, {30, 50}};
CGRect r2; r2.origin.x = 10; r2.origin.y = 20; r2.size.width = 30; r2.size.height = 50;
CGRect r3 = {p, s};
2>使用函数快速创建:
CGPoint p1 = CGPointMake(10, 20); CGPoint p2 = NSMakePoint(10, 20);
CGSize s1 = CGSizeMake (30, 50); CGSize s2 = NSMakeSize (30, 50);
CGRect r1 = CGRectMake (10, 20, 30, 50); CGRect r2 = NSMakeRect (10, 20, 30, 50);
CGPointZero 等价于 CGPointMake(0, 0)
CGSizeZero 等价于 CGSizeMake(0, 0)
CGRectZero 等价于 CGRectMake(0, 0, 0, 0)
3 常用函数
CGPointEqualToPoint(p1, p2); //比较两个点的位置是否相同.
CGSizeEqualToSize(s1, s2); //比较两个尺寸是否相同
CGRectEqualToRect(r1, r2); //比较两个矩形是否占据同样的位置
CGRectContainsPoint(r, p); //判断r这个矩形范围内是否包含p这个点.
4快速查看所有属性
查看结构体内部的成员值,如果使用点成员名非常麻烦.比如,
NSLog(@"Origin (%d, %d). Size (%d, %d).", rect,origin,x, rect,origin,y, rectysize.x, rect.size.y);
注意
rect.origin.x里的点不是点语法,因为rect不是对象而是结构体,这里的点是访问结构体的成员.
最常使用的方式是,把结构体转成字符串,可以快速打印所有属性的值
NSString *str_p = NSStringFromPoint(p); //字符串 {10, 20}
NSString *str_s = NSStringFromSize(s); //字符串 {30, 50}
NSString *str_r = NSStringFromRect(r); //字符串 {{10, 20}, {30, 50}}
NSLog(@"%@", str_r);
NSString
字符串的创建
直接创建字符串
NSString *s = @"hello";
NSString *s = [[NSString alloc] initWithString:@"hello"];
NSString *s = [[NSString alloc] initWithFormat:@"hello, %@!", @"jack"];
C语言字符串和OC字符串的相互转换
NSString *s = [[NSString alloc] initWithUTF8String:"hello"]; //用于把C语言字符串转为OC字符串
const char *c = [s UTF8String]; //把OC字符串转为C语言字符串
把文件内容读取为字符串
NSString *s = [[NSString alloc] initWithContentsOfFile:@"/Users/apple/Desktop/test.txt"encoding:NSUTF8StringEncoding error:nil];
把链接内容读取为字符串
URL就是资源路径,格式:协议头://路径,
网络资源的协议头通常是http,
本地资源通常是file, ftp资源是ftp。URL字符串必须有协议头。
NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop/test.txt"];
注意前面有三个斜杠,前两个是固定写法,第三个是表示绝对路径 /Users。另外, [NSURLfileURLWithPath:@"/Users/..."]; 这种已经说了是 fileURL了就可以不加 file:// 了。
NSString *s = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:nil];
使用URL也可以读取远程文件,比如网页文件:
NSURL *baiduURL = [NSURL urlWithString:@"http://www.baidu.com"]; //可以查看源代码,发现编码是UTF8
NSString *s = [NSString stringWithContentsOfURL:baiduURL encoding:NSUTF8StringEncoding error:nil]; //读取的是网页的代码
使用类方法
NSString *s = [NSString stringWithFormat:@"%d", 5];
NSString *s = [NSString stringWithContentsOfURL: ...];
注意:NSString的类方法通常都以string开头。
NSMutableString
创建
NSMutableString继承NSString,创建可变字符串。
NSMutableString *ms = [NSMutableString stringWithFormat:@"age is 10"];
NSString *us = [NSString stringWithFormat:@"age is 10"];
注意:决定这个字符串是可变的还是不可变的,取决于右边调用方法的类,而不是左边对象指针的类型。
内容修改
1添加内容:
[ms appendString:@"ABC"]; //拼接内容到字符串后面
[ms appendFormat:@"%d", 5];
2替换内容:
range = [ms rangeOfString:@"no"]
[ms replaceCharactersInange:range withString:@"yes"];
3插入内容:
[ms insertString:@"hello" atIndex:3]; //在这个index前面插入
4删掉内容:
NSRange range = [ms rangeOFString:@"10"];
[ms deleteCharactersInRange:range]; //删掉部分内容