------Java培训、Android培训、iOS培训、.Net培训 期待与您交流! -------
本篇讲述的是Foundation框架的一些常用的结构体和常用类。
1.Foundation框架的结构体
NSRange
#import <Foundation/Foundation.h>
int main()
{
NSString *s = @"This is Foundation test,welcome to OC program!";
NSRange r = [s rangeOfString:@"Foundation"];
NSLog(@"\n位置是:%ld,长度是:%ld",r.location,r.length);
return 0;
}
结果:
位置是:8,长度是:10
使用rangeOfString查找某个小字符串在某个字符串中的范围,并将结果用NSRange来保存
位置是:9223372036854775807,长度是:0
位置上是什么值呢?换成%d再输出一下
位置是:-1,长度是:0
因为原来是unsigned long,无符号,所以输出的是上面那一堆。由此我们可以知道,NSRange的返回值,查找到的时候,返回查找子串首字母的下标和子串长度;找不到的时候,location返回-1,length返回0
NSPoint/CGPoint
CGPoint point1 = NSMakePoint(10, 5);
NSPoint point2 = CGPointMake(12, 13);
上面两种都可以,point2的使用会更多一点
注意的点:
NSLog(@"%f,%f",CGPointZero.x,CGPointZero.y);
结果:
CGPoint point1 = NSMakePoint(10, 5);
NSPoint point2 = CGPointMake(12, 13);
NSLog(@"%d",CGPointEqualToPoint(point1, point2));
这两个点不同,所以结果是0
NSSize/CGSize
用法和上面讲的CGPoint类似,有两个属性:width和height NSSize size = CGSizeMake(20, 20);
NSSize size2 = NSMakeSize(20,20);
NSLog(@"%d",CGSizeEqualToSize(size, size2));
结果是:1
NSRect/CGRect
包含CGPoint 和 CGSize,用法也类似
NSRect r1 = NSMakeRect(1, 1, 2, 3);
NSRect r2 = CGRectMake(1, 1, 2, 3);
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height);
x和y表示一个CGPoint,w和h表示CGSize
这里有一个特别需要注意的点:
CGRectContainsPoint(一个矩形中是否包含某个点(边界值不包含))
NSRect r1 = NSMakeRect(1, 1, 2, 3);
CGPoint p1 = CGPointMake(2, 2);
NSLog(@"%d",CGRectContainsPoint(r1, p1));
结果:1
返回的时bool型数据,如果包含这个点返回1,不包含返回0,注意边界上的点是不包含的。
打印结构体的值
刚才在打印结构体值的时候,感觉很麻烦,下面将介绍直接打印的方式。思路是将结构体转成字符串,再打印整个结构体
NSString *str = NSStringFromRange(r2);//将范围转成字符串
NSString *str = NSStringFromPoint(r2);//将点转成字符串
NSString *str = NSStringFromSize(r2);//将size转成字符串
NSString *str = NSStringFromRect(r2);//将Rect转成字符串
NSLog(@"%@",str);
示例:
NSRect r1 = NSMakeRect(1, 1, 2, 3);
CGPoint p1 = CGPointMake(3,4);
NSString *str1 = NSStringFromRect(r1);
NSString *str2 = NSStringFromPoint(p1);
NSLog(@"\n%@\n%@",str1,str2);
结果:
2015-04-16 10:34:38.961 Foundation的结构体[1005:303]
{{1, 1}, {2, 3}}
{3, 4}
2.常用类
NSString(不可变字符串)和NSMutableString(可变字符串)
int age = 25;
//创建带格式的不可变字符串
NSString *str = [NSString stringWithFormat:@"my age is %d",age];
//创建带格式的可变字符串
NSMutableString *mstr = [NSMutableString stringWithFormat:@"my age is %d",age];
//为已经创建的可变字符串添加字符
[mstr appendString:@"\tthis is Foundation study"];
//不可变字符串中是没有这个方法的,它想要添加字符,只能用下面的方式
NSString *str2 = [str stringByAppendingString:@"\t我是不可变字符串"];
NSLog(@"\n%@\n%@\n%@",str,mstr,str2);
使用NSMutableString可以直接在后面添加字符串,但是NSString就不行,它只能调用stringByAppendingString方法后赋值给一个新的字符串,它本身的值并没有改变。
还有一些用法:
int age = 25;
//创建带格式的不可变字符串
NSMutableString *str = [NSMutableString stringWithFormat:@"my age is %d",age];
NSRange range = [str rangeOfString:@"is"];
[str deleteCharactersInRange:range];
NSLog(@"%@",str);
注意,deleteCharactersInRange:这个方法只能是NSMutableString的。
NSString *s = [NSString stringWithUTF8String:"hello"];
NSLog(@"%@",s);
“hello”是一个C语言字符串,这样转完之后变成OC字符串。
const char *s1 = [s UTF8String];
printf("%s\n",s1);
(3)从文件中读取字符串
NSString *file = [NSString stringWithContentsOfFile:@"/Users/liweixi/Desktop/ios-study/日志的代码/OC/常用类/常用类/main.m" encoding:NSUTF8StringEncoding error:nil];
NSLog(@"\n%@",file);
还可以用URL
NSURL *url = [NSURL URLWithString:@"file:///Users/liweixi/Desktop/10.c"];
NSString *file = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
但是注意了,url中是不能有中文的,会报错的的
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSString *file = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
还可以把OC中的东西写入文件
NSString *s = @"hello foundation\n";
[s writeToFile:@"/Users/liweixi/Desktop/test.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
集合类
NSArray(不可变数组)
它有一个子类NSMutableArray(可变数组)
Person *p = [[Person alloc] init];
NSArray *a = [NSArray arrayWithObjects:p,@"hello",@"ios",@"foundation", nil];
NSLog(@"%@",a[2]);
NSLog(@"%@",[a objectAtIndex:2]);
上面代码可以看出,NSArray可以存放不同类型的对象,但是它不能存放基本数据类型、结构体、枚举等这些类型的数据(要存放它们在后面NSNumber的时候会讲),它只能存放OC对象,还有一点,nil不可省略,是oc数组结束的标志,因此,OC数组还不能存空值
for (id obj in a)
{
NSLog(@"%@",obj);
}
但是这种方法有个小问题,需要自定义一个变量来存取下标
[a enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%ld-%@",idx,obj);
}];
每遍历一次数组元素,就会调用这个block,并且把当前元素和索引传给这个block。个人觉得这种方法很好用,stop指针相当于break
NSLog(@"%ld",a.count);
a.count是用来求数组元素个数的。
NSArray *a = @[p,@"hello",@"ios",@"foundation"];
怎么省事怎么来啊,但是注意,不能使用这种方式来创建NSMutableArray,因为利用这种方式创建出来的数组仍然是NSArray,如果不慎使用,可能会在运行的时候报那个,不能识别的消息传给对象的经典错误的
NSSet
都是集合,能存放多个OC对象
只能存放OC对象,不能存放非OC对象(基本数据类型,结构体,枚举等)
本身不可变,都有一个可变的子类
不同点
NSArray本身有顺序,但是NSSet是无序的
NSSet *s = [NSSet setWithObjects:@"ferferf",@"fergg",@"grtgr",@"fgrtgth", nil];
//随机取出对象
NSString *str = [s anyObject];
NSLog(@"%@",str);
它也有个子类:NSMutableSet(可变的)。
NSDictionary
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:
@"jack",@"name",
@"25",@"age", nil];
NSLog(@"%@",[d objectForKey:@"name"]);
NSArray *objs = @[@"jack",@"25"];
NSArray *keys = @[@"name",@"age"];
NSDictionary *d1 = [NSDictionary dictionaryWithObjects:objs forKeys:keys];
NSLog(@"%@",[d1 objectForKey:@"name"]);
(3)利用编译器特性快速创建
NSDictionary *d2 = @{
@"name":@"jack",
@"age":@"25"};
NSLog(@"%@",[d2 objectForKey:@"name"]);
objectForKey表示按照key值取出object内容,还有一种简便写法
id obj = d2[@"name"];
NSLog(@"%@",obj);
同样利用
和数组一样,字典也可以遍历
//字典的遍历
//方法一
for (id obj in d2)
{
NSLog(@"%@",obj);
}
//方法二
[d2 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"%@-%@",key,obj);
}];
方法一并不好,还是使用方法二更好。
NSLog(@"%@",d2);
结果:
age = 25;
name = jack;
}
NSNumber和NSValue
可以将基本数据类型、结果体等包装成对象。 NSNumber *n = [NSNumber numberWithInt:25];
NSDictionary *d = @{
@"age":n
};
NSLog(@"%@",d);
快速包装基本数据类型:
NSDictionary *d = @{
@"age":@(25)
};
NSLog(@"%@",d);
NSNumber能够包装基本数据类型,原因是因为继承了NSValue类
NSInteger a = [d[@"age"] integerValue];
NSLog(@"%d",a);
上述代码的意思是,从字典中取出key为 age 的object ,并将它转为 int型
NSValue *v = [NSValue valueWithPoint:NSMakePoint(2,23)];
NSArray *a = @[v,@"hello"];
NSLog(@"%@",a);
结果
"NSPoint: {2, 23}",
hello
)
NSValue也可以转为结构体
NSString *p = NSStringFromPoint([v pointValue]);
NSLog(@"%@",p);
上述代码是将NSValue类型的v转成NSPoint类型后再转为NSString输出
NSDate
日期和时间类 NSDate *date = [NSDate date];
NSLog(@"%@",date);
注意,这样输出的是0时区的时间
//格式化输出日期
NSDate *date = [NSDate date];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSString *today = [df stringFromDate:date];
NSLog(@"%@",today);
结果:
还可以自定义一个日期来输出
NSString *str = @"2015-04-01 11:35:20";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *date = [df dateFromString:str];
NSLog(@"%@",date);
NSString *today = [df stringFromDate:date];
NSLog(@"%@",today);
结果:
2015-04-16 13:20:40.830 NSDate[2552:303] 2015-04-01 03:35:20 +0000
2015-04-16 13:20:40.831 NSDate[2552:303] 2015-04-01 11:35:20
使用字符串定义一个日期,将它转为一个格式化的日期,如果直接用这个日期输出,那么结果是当天0时区的时间,如果是再转成字符串,就可以得到你定义的时间了
3.应用实例
学到这里我才发现,OC其实就是使用各种方法,只要知道用什么方法,程序很快就能写出来,这就是面向对象编程的优势所在了吧
最后放一个个人认为有点不好做的小练习代码
#import <Foundation/Foundation.h>
NSUInteger countFileCore(NSString *path)
{
NSFileManager *manager = [NSFileManager defaultManager];
BOOL dir = NO;
BOOL exist = [manager fileExistsAtPath:path isDirectory:&dir];
if (!exist) {
NSLog(@"路径不存在");
return 0;
}
if (dir)
{
NSArray *fileListArray = [manager contentsOfDirectoryAtPath:path error:nil];
NSUInteger count = 0;
for (NSString *filename in fileListArray)
{
NSString *fileFullPath = [NSString stringWithFormat:@"%@/%@",path,filename];
count += countFileCore(fileFullPath);
}
return count;
}
else
{
NSString *extention = [[path pathExtension] lowercaseString];
if ( !([extention isEqualToString:@"h"]
|| [extention isEqualToString:@"m"]
|| [extention isEqualToString:@"c"]))
{
return 0;
}
//单个文件代码量统计,加载文件内容
NSString *file = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSArray *lineArray = [file componentsSeparatedByString:@"\n"];
//替换路径
NSRange range = [path rangeOfString:@"/Users/liweixi/Desktop/ios-study"];
NSString *s = [path stringByReplacingCharactersInRange:range withString:@""];
NSLog(@"\n路径:%@\n文件代码数:%ld",s,lineArray.count);
return lineArray.count;
}
}
int main() {
@autoreleasepool
{
NSString *filepath = @"/Users/liweixi/Desktop/ios-study";
NSUInteger count = countFileCore(filepath);
NSLog(@"代码量是%ld",count);
}
return 0;
}
基础篇的学习就到这里了,所有知识点你都get了吗?