Foundation
框架是其他所有iOS框架的基础
- 包含了很多开发中常用的数据类型
- 结构体
- 枚举
- 类
- 要想使用
Foundation
中的数据类型,包含它的主文件
即可#import <Foundation/Foundation.h>
1. 结构体 常用 NSRange
CGPoint
CGSize
CGRect
NSRange
typedef struct _NSRange{
NSUInteger location;
NSUInteger length;
} NSRange;
NSRange r = {2, 3}; // 不用
NSRange r2 = {.location = 2, .length = 3}; // 不用
NSRange r3 = NSMakeRange{2, 3}; // 掌握 !!!
NSString *str = @"VampireJune";
// 查找某个字符串在 str 中的范围
// 如果找不到,length = 0,location = NSNotFound == -1
NSRange r4 = [str rangeOfString:@"June"];
NSLog(@"loc = %ld, len = %ld", r4.location, r4.length);
-
NSPoint
==CGPoint
(跨平台的(Mac 和 iOS),只用这个) 表示一个点的位置
struct CGPoint{
CGFloat x;
CGFloat y;
};
typedef struct CGPoint CGPoint;
CGPoint p = NSMakePoint(10, 10);
// 最常用的方法 CGPointMake
NSPoint p1 = CGPointMake(20, 20);
// 表示原点
CGPointZero == CGPointMake(0, 0);
// 还有 CGSizeZero, CGRectZero
// 使用这些函数的前提是添加 CoreGraphics 框架
// 比较两个点是否相同 (x, y)
BOOL B = CGPointEqualToPoint(CGPointMake(20, 20),CGPointMake(20, 20))
// 还有 CGSizeEqualToSize,CGRectEqualToRect
-
NSSize
==CGSize
表示UI元素尺寸
NSSize s = CGSizeMake(20, 20);
NSSize s1 = NSMakeSize(20, 20);
CGSize s2 = NSMakeSize(20, 20);
struct CGSize{
CGFloat width;
CGFloat height;
}
typedef struct CGSize CGSize;
-
NSRect
==CGRect
代表二维平面中的某个物体的位置和尺寸
struct CGRect{
CGPoint origin;
CGSize size;
};
CGRect r1 = CGRectMake(0, 0, 100, 20);
// 超麻烦
NSLog(@"x = %f, y = %f, width = %f, height = %f",
r1.origin.x, r1.origin.y, r1.size.width, r1.size.height);
// 将结构体转为字符串
// NSString *st = NSStringFromRect(r1);
NSLog(@"%@",st);
// 还有NSStringFromPoint, NSStringFromSize
CGRect myRect (CGFloat x, CGFloat y, CGFloat width, CGFloat height)
{
CGRect rect;
rect.origin.x = x;
rect.origin.y = y;
rect.size.width = width;
rect.size.height = height;
return rect;
}
// 多种写法
CGRect r2 = {{0, 0}, {100, 20});
CGRect r3 = {p, s);
CGRect r3 = {CGPointZero, CGPointMake(20, 20)};
// 使用这个函数的前提是添加 CoreGraphics 框架
// 判断一个矩形范围是否包含坐标20 ,20的点
CGRectContainsPoint(CGRectMake(0, 0, 100, 20),CGPointMake(20, 20));
2. 常用类 NSString
NSArray
NSSet
NSDictionary
NSDate
NSObject
NSString
NSString : 不可变字符串
NSMutableString : 可变字符串
NSString *s1 = @"VampireJune";
NSString *2 = [[NSString alloc] initWithFormat:@"is %d",10];
// 类方法创建 字符串
[NSString stringWithFormat:@"is %d",10];
// C字符串 --> OC字符串
NSString *s3 = [[NSString alloc] initWithUTF8String:"VampireJune"];
// OC字符串 --> C字符串
const char *cs = [s3 UTF8String];
// 从文件中读取字符串
// NSUTF8StringEncoding 用到中文就可以用这种编码
NSString *s4 = [[NSString alloc] initWithContentsOfFile:"/绝对路径" encoding:NSUTF8StringEncoding error:nil];
// URL : 资源路径
// 协议头 : //路径(file://、ftp://)
NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop....."];
// 类方法
[NSURL urlWithString:@"file:///Users/apple/Desktop....."];
// 省去了协议头
[NSURL fileURLWithPath:@"/Users/apple/Desktop....."];
NSString *s5 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
// 一般都会有一个类方法跟对象方法配对
// 字符串导出到文件
// atomically : 原子性操作,
* YES,当文件写了部分失败了,这个文件不会创建
* NO ,当文件写了部分失败了,这个文件还会创建
[@"Vampire\nJune" writeToFile:@"文件路径" atomically:YES encoding:NSUTF8StringEncoding error:nil];
// 不可变字符串后拼接一个字符串,返回一个新字符串对象
NSString *s6 = [NSString stringByAppendingString:@"..."];
-
NSMutableString
可变
字符串 继承自NSString
// 拼接内容到 s1 的后面
[s1 appendString:@"..."];
// 删除 Range 的内容 VampireJune
NSRange ra = [s1 rangeOfString:@"VampireJune"];
[s1 deleteCharactersInRange: ra];
3. 集合类 NSArray
NSSet
NSDictionary
NSArray
// OC数组只能存放 OC 对象,不能存放 非OC对象类型,如,int、struct、enum等,不能存放 nil 值
// 创建不可变数组
// nil 是数组元素结束的标记
NSArray *array = [NSArray arrayWithObjects:@"Vampire",@"June",nil];
// 编译器特性,快速创建OC数组
NSArray *array1 = @[@"Vampire",@"June"];
// 获取数组的个数
[array count]; == array.count
// 拿取位置 1 的元素
[array objectAtIndex:1]; == array[1];(编译器特性,转成前面代码)
遍历 1
Person *p = [[Person alloc] init];
NSArray *array = @[p,@"June"];
for (int i = 0; i < array.count; i++)
{
NSLog(@"%@", array[i]);
}
遍历 2 快速遍历
for (id obj in array)
{
// 找出 obj 元素在数组中的位置
NSUInteger i = [array indexOfObject:obj];
NSLog(@"%@ -- %ld", obj, i);
if(i == 1)
{
// 停止遍历,退出循环
break;
///** 注 break 只用在 switch语句 和 for循环
}
}
遍历 3 block遍历
[array enumerateObjectsUsingBlock:
// 每遍历到一个元素,就会调用一次 block
// 并且把当前元素和索引位置当做参数传给 block
^(id obj, NSUInteger idx, BOOL *stop)
{
if(idx == 1)
{
// 停止遍历
*stop = YES;
}
}];
遍历 3 block遍历 的本质 解释
void ^(myBlock)(id, NSUInteger, BOOL *) = ^(id obj, NSUInteger idx, BOOL *stop)
{
}
for (int i = 0; i < array.count; i++)
{
// 用来标记是否需要停止遍历
BOOL isStop = NO;
// 取出元素
id obj = array[i];
myBlock(obj, i, &isStop);
if(isStop)
{
break;
}
}
-
NSMutableArray
可变
数组 继承自NSArray
NSMutableArray *array = [NSMutableArray array];
[array addObject:]; // 添加元素
// 错误 [array addObject:nil];
[array removeObject:]; // 删除元素
- 集合的内存管理 (MRC里)
NSMutableArray *array = [NSMutableArray array];
Person *p = [[Person alloc] init];
// 当把一个对象添加到集合中时,这个对象会做一次 retain 操作,计数器会 +1
// 当把一个对象从集合中移除时,这个对象会做一次 release 操作,计数器会 -1
[array addObject:p];
[p release];
// 当一个集合被销毁时,会对集合里面的所有对象做一次 release,里面的所有对象的计数器会 -1
[array release];
// 泛型 指定数组类型
@property (nonatomic, strong) NSMutableArray <NSString *> *names;
-
NSSet
NSMutableSet
无顺序的集合
NSSet *s = [NSSet setWithObjects:@"Vampire",@"June",nil];
[s anyObject]; // 随机取出一个元素
NSMutableSet *s2 = [NSMutableSet set];
-
NSSet
和NSArray
的对比- 共同点
- 都是集合,都能存放多个
OC对象
-
只能
存放OC对象
,不能
存放非OC对象
类型(基本数据类型:int
、char
、float
等,结构体
,枚举
)
- 都是集合,都能存放多个
-不同点
-
NSArray
有顺序 -
NSSet
无顺序
- 共同点
-
NSDictionary
NSMutableDictionary
字典key
--->value
索引 ---> 文字内容
-
里面存储的东西都是
键值对
-
不允许
有相同
的key
,但允许有相同的value
- 无顺序
-
NSDictionary *dic = [NSDictionary dictionaryWithObject:@"June" forKey:@"name"];
id obj = [dic objectForKey:@"name"];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"June", @"name", @"地址", @"address",nil ];
NSDictionary *dic = @{@"June": @"name", @"地址": @"address"};
id obj = dic[@"name"];
dic.count // 返回的是 键值对 的个数
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:@"jack" forKey:@"name"]; // 添加键值对
// 字典中只允许有一个 key,设置已经有的key,value,原来的会被覆盖
[dic setObject:@"Vampire" forKey:@"name"];
[dic removeObjectForKey"@"name"]; // 移除键值对
// 遍历字典 1
NSArray *keys = [dic allKeys];
for (int i = 0; i < dic.count; i++)
{
NSString *key = keys[i];
id obj *value = dic[key];
NSLog(@"%@ -- %@",key ,value);
}
// 遍历字典 2
[dic enumerateKeysAndObjectsUsingBlock:
^(id key, id obj, BOOL *stop)
{
// 停止遍历
*stop = YES;
}];
- 集合对比
OC | JAVA |
---|---|
NSArray | List |
NSSet | Set |
NSDictionary | Map |
1. NSArray\ NSMutableArray
* 有序
* 快速创建(不可变):@[obj, obj1, obj2];
* 快速访问元素:数组名[i]
2. NSSet\ NSMutableSet
* 无序
3. NSDictionary\ NSMutableDictionary
* 无序
* 快速创建(不可变):@{key1 : value1, key2 : value2};
* 快速访问元素:字典名[key]
4. 泛型 指定 key value 类型
@property (nonatomic, strong) NSMutableDictionary <NSString *, NSNumber *> *names;
NSNumber
// @10 是将 10 包装成一个 NSNumber 对象
NSNumber *num = [NSNumber numberWithInt:10]; == @10
int a = [num intValue];
// 将 age 包装成一个 NSNumber 对象
int age = 100;
[NSNumber numberWithInt:age] == @(age)
// NSNumber 之所以能包装基本数据类型为对象,是因为继承了 NSValue
NSValue 可以包装任意值
// 结构体 ---> OC对象
CGPoint p = CGPointMake(10, 10);
// 将结构体转为 Value 对象
NSValue *vv = [NSValue valueWithPoint:p];
// 将 value 转为对应的结构体
[vv pointValue];
NSDate
// 创建一个时间对象 当前时间 0时区时间(北京-东8区)
NSDate *date = [NSDate date];
// 比 date 时间 晚 5 秒
NSDate *date2 = [NSDate dateWithTimeInterval:5 sinceDate:date];
// 从 1970 开始到 date2 走过多少秒
NSTimeInterval seconds = [date2 timeIntervalSince1970];
[date2 timeIntervalSinceNow];
// 日期格式化类 NSDateFormatter
NSDateFormatter *f = [[NSDateFormatter alloc] init];
// 设置格式
// y年 M月 d日 Z时区
// m分 s秒 H(24)时 h(12)时
f.dateFormat = @"yyyy-MM-dd HH:mm:ss"
[f stringFormDate:date];
// 创建一个日历对象
NSCalendar *calendar = [NSCalendar currentCalendar];
// 利用日历对象 或者 时间对象 对应的 年、月、日、时分秒
int unit = NSCalendarUnitYear | NSCalendarUnitMonth;
NSDateComponents *c = [calendar components:unit formDate:now];
// 打印时间的要素
NSLog(@"%ld", c.year);
// 利用日历,比较 时间 差距
NSString *time1 = @"2014-04-08 20:50:40";
NSString *time2 = @"2014-04-04 18:45:30";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
f.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *date1 = [f dateFormString;time1];
NSDate *date2 = [f dateFormString;time2];
// 创建一个日历对象
NSCalendar *calendar = [NSCalendar currentCalendar];
int unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *c = [calendar components:unit formDate:date1 toDate:date2 options0];
NSLog(@"相差%ld年%ld月%ld日%ld时%ld分%ld秒",c.year, c.month, c.day, c.hour, c.minute, c.second);
5. NSFileManager
用来进行常见的文件\文件夹操作
-
NSFileManager
使用了单例
模式 - 使用
defaultManager
方法可以获得单例对象
NSFileManager *mgr = [NSFileManager defaultManager];
// 默认不是文件夹,即默认是文件
BOOL dir = NO;
// isDirectory 判断是否是个文件夹 需要传 dir 的地址,可以改变 dir 的值,返回值代表 是文件还是文件夹
// 返回值 exist 代表这个路径的文件\文件夹是否存在
BOOL exist = [mgr fileExistsAtPath:@"路径" isDirectory:&dir];
// 获得文件、文件夹的属性
NSDictionary *attr = [mgr attributesOfItemAtPath:@"路径" error:nil];
// 获得当前文件夹下面有哪些内容
NSArray *contents = [mgr contentsOfDirectoryAtPath:@"路径" error:nil];
// 获得当前文件夹下面 所有子路径
NSArray *contents = [mgr subpathsOfDirectoryAtPath:@"路径" error:nil];
6. Copy
MutableCopy
- 作用:利用一个源对象产生一个副本对象
- 特点:修改源对象的属性和行为,不会影响副本对象
- 使用:一个对象可用调用 copy\mutableCopy 方法类创建一个副本对象
copy:创建的是不可变副本(如NSString、NSArray、NSDictionary)
> copy : 需要遵守 NSCopying 协议,实现 copyWithZone: 方法
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
mutableCopy:创建的是可变副本(如可变字符串、可变数组、可变字典)
> mutableCopy : 需要遵守 NSMutableCopying 协议
实现 mutableCopyWithZone: 方法
@protocol NSCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end
-
浅复制
(浅拷贝,指针拷贝,shallow copy)-
本质
是:没有
产生新
的对象
- 源对象和副本对象是同一个对象
- 源对象(副本对象)引用计数器 +1,相当于做一次 retain 操作
-
-
深复制
(深拷贝,内容拷贝,deep copy)-
本质
是:产生
了新
的对象
- 源对象和副本对象是不同的两个对象
- 源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
-
只有
源对象
和副本对象
都不可变
时,才是浅复制
其他都是
深复制
7. @property
内存管理策略的选择
-
1.非ARC
-
copy
:只
用于NSString\block
(坚决不能用可变字符串) -
retain
: 除NSString\block
以外的OC对象 -
assign
: 基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain
,一端用assign
-
-
2.ARC
-
copy
:只
用于NSString\block
(坚决不能用可变字符串) -
strong
: 除NSString\block
以外的OC对象 -
weak
: 当2个对象相互引用,一端用strong
,一端用weak
-
assgin
: 基本数据类型、枚举、结构体(非OC对象)
-
8. 递归
- 1.函数自己调自己
- 2.必须有个明确的返回值
9. static
在 OC 中的使用
static
-
1.修饰局部变量
- 让局部变量只初始化一次
- 局部变量在程序中只有一份内存
- 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,才会销毁)
-
2.修饰全部变量
- 全部变量的作用域仅限于当前文件
例:#define a 0.5 VS const CGFloat a = 0.5;
像宏一样,不能改值
有多少使用宏的地方,就会开辟多少临时存储空间
使用
const
,就只会开辟一个存储空间还可以使用 extern 全局引用
如果引用的是个常量,最好加一个,
const
例:
extern const CGFloat a
(编译阶段就能很快发现,避免修改被const
修饰的常量,运行是崩溃)