美文网首页
iOS 相关集合函数的使用

iOS 相关集合函数的使用

作者: _凉风_ | 来源:发表于2016-06-23 17:05 被阅读347次

一、结构体

1. NSRange 范围

  • 定义
typedef struct _NSRange{ 
    NSUInteger location;// NSUInteger结构体是 unsign long int 类型
    NSUInteger length;
} NSRange;
  • 创造结构体
NSRange r1 = {2, 4}; // 方法1:不常用
NSRange r2 = {.location = 2, .length = 4}; // 方法2:不常用
NSRange r3 = NSMakeRange(2, 4); // 方法3:Foundation框架自带函数
  • NSString 中的 rangeOfString(查找字符串) 方法
    作用:查找字符串在本字符串中的范围,返回 NSRange 结构体
    注意:如果 查找字符串未找到,返回的 NSRange 结构体 length = 0, location = NSNotFound 「NSNotFound 为枚举类型 为常量整数 -1」

2. NSPoint UI元素的位置

  • 定义
typedef struct CGPoint{ 
    // CGFloat结构体 是double类型
    CGFloat x; // 在UI界面中 x 向右递增
    CGFloat y; // 在UI界面中 y 向下递增
} CGPoint;
typedef CGPoint NSPoint; // 开发用 CGPoint,因为它跨平台
  • 创造结构体
CGPoint p1 = NSMakePoint(2, 4); // 方法1:Foundation框架自带函数
NSPoint p2 = CGPointMake(2, 4); // 方法2:开发中常用,CGPoint 和 NSPoint等价
  • CGPointZero「常量」等价于 CGPointMake(0, 0);
  • <code>bool CGPointEqualToPoint(CGPoint , CGPoint)</code> 比较两个点位置是否相同

3. NSSize UI元素的尺寸

  • 定义
typedef struct CGSize{ 
    CGFloat width;// CGFloat结构体 是double类型
    CGFloat height;
} CGSize;
typedef CGSize NSSize; // 开发用 CGSize,因为它跨平台
  • 创造结构体
CGSize s1 = NSMakeSize(2, 4); // 方法1:Foundation框架自带函数
NSSize s2 = CGSizeMake(2, 4); // 方法2:开发中常用,CGSize 和 NSSize等价
  • CGSizeZero「常量」等价于 CGSizeMake(0, 0);
  • <code>bool CGSizeEqualToSize(CGSize , CGSize)</code> 比较

4. NSRect 矩形UI元素的 左上角的位置 和 尺寸

  • 定义
typedef struct CGRect{ 
    CGPoint origin;
    CGSize size;
} CGRect;
  • 创造结构体
CGRect rect = { CGPointMake(2, 4), NSMakeSize(2, 4) };
  • CGRectZero「常量」等价于 CGRectMake(0, 0, 0, 0);

  • <code>bool CGRectEqualToRect(CGRect , CGRect)</code> 比较「Foundation框架」

  • <code>bool CGRectCotainsPoint(CGRect, CGPoint)</code>判断 点是否在矩形范围内「CoreGraphics框架」

  • <code>bool CGRectCotainsRect(CGRect, CGRect)</code>判断 矩形是否在矩形范围内「CoreGraphics框架」

  • 将结构体 转成字符串

NSString *str = NSStringFromCGRect(CGRect rect);
NSLog("%@", str);

打印效果:
<code>{ {0, 0}, {0, 0} }</code>

二、类

1. NSString「不可变字符串」

  • 字符串的创建方式
NSString *s1 = @"方法  1";
NSString *s2 = [[NSString alloc] initWithString:@"方法 2"];
NSString *s3 = [[NSString alloc] initWithFormat:@"方法 %d", 3];
NSString *s4 = [[NSString alloc] initWithUTF8String:"方法 4:C字符串 转 OC字符串"];
const char *s = [s4 UTF8String]; // OC字符串 转 C字符串
// 一般都有一个类方法和对象方法配对,方法名为 类名With...
NSString *s5 = [NSString stringWithFormat:@"方法 5"];

NSString *s6=[NSString stringWithContentsOfFile:@"/绝对路径 方法 6" encoding:NSUTF8StringEncoding error:nil];
  • 读取文件
// 方法 1:从本地读取
NSString *s1=[[NSString alloc] initWithContentsOfFile:@"/绝对路径" encoding:NSUTF8StringEncoding error:nil];
// 方法 2:从 URL 读取
// URL 格式:协议头://路径「[file://](http://file//) 本地,[ftp://](http://ftp//) , [http://](http:/) 」
NSURL *url = [[NSString alloc] initWithString:@"[file://](http://file//)/绝对路径"]; // 前面"//"是URL格式,后面"/"代表根路径
NSURL *url1 = [NSURL fileURLWithPath:@"/绝对路径"]; // 已经调用的 file方法,无序传入URL的协议头来声明文件类型
NSString *s2 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
  • 写入文件「字符串导出」
// atomically: YES 只有写入完成后才创建文件
// atomically: NO 只要写入就创建文件,不管其是否完整,都创建文件
[@"写入内容对象" writeToFile:@"/路径、创建写入文件名称" atomically:YES encoding:NSUTF8StringEncoding error:nil];

NSURL *url = [[NSString alloc] initWithString:@"[file://](http://file//)/绝对路径"];
[@"写入内容对象" writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil];
  • NSMutableString「继承自NSString,可变字符串」
// 添加到原来字符串后面,返回添加后的新对象「原来字符串不变」
NSString *s = [NSString stringWithFormat:@"可变字符串"];
NSString *s0 = [s appendString:@"添加的字符串"];

// 添加到原来字符串后面「原来字符串变」
NSMutableString *s1 = [NSMutableString stringWithFormat:@"可变字符串"];
[s1 appendString:@"添加的字符串"];

// 删除字符串的一些字符
NSRange range = [s1 rangeOfString:@"加"];
[s1 deleteCharacterInRange: range];
  • 字符串比较
NSString *s1 = @"abd";
NSString *s2 = @"abc";

// 比较「内容」是否相同
BOOL result = [s1 isEqualToString: s2];
// 比较「地址」是否相同
result = (s1 == s2);

// 比较「大小」是否相同
// 返回值:
//    NSOrderedAscending     前 < 后
//    NSOrderedSame            相同
//    NSOrderedDescending    前 > 后
result = [s1 compare: s2];
// 比较「大小」是否相同,忽略大小写
result = [s1 caseInsensitiveCompare: s2];
  • 字符串搜索
NSString *s = @"[http://www.baidu.com";](http://www.baidu.com";)
// 判断以什么开头
BOOL result = [s hasPrefix: @"[http://](http://"];)"];

// 判断以什么结尾
BOOL result = [s hasSuffix: @".com"]; 

// 判断是否包涵给定的字符串
//     若包涵,返回给定字符串的 1.起始位置 2.该字符串的长度
NSRange rr = [s rangeOfString: @"bai"]; // 默认:从前往后查找
NSRange rr = [s rangeOfString: @"bai" options:NSBackWardsSearch];
  • 字符串截取
NSString *s = @"<head>要截取的字符串</head>";
NSRange range = {6, 7}; // 设置获取字符串范围
NSString *get = [s substringWithRange: range];

// 从 什么地方 开始截取,一直截取到 最后
get = [s subStringFromIndex: 6];
// 从 开头 开始截取,一直截取到 哪个位置
get = [s subStringToIndex: 7];
  • 字符串替换
NSString *s = @"ni hao hehe";
// stringByReplacingOccurrencesOfString: 被替换的字符串
// withStirng: 用什么替换
NSString *newStr = [s stringByReplacingOccurrencesOfString: @"hehe" withString: @"haha"];

// 首末位 去除
NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet];
newStr = [s stringByTrimmingCharactersInSet: Set]; // 将首末位 去除set对象类型的字符串
  • 字符串路径相关方法
NSString *str = @"/h/a/c.c";
// 1.判断是否是绝对路径「判断字符串是否以'/'开头」
BOOL *op = [s isAbsolutePath];

// 2.获取文件路径中的最后一个目录「删除最后一个'/'以及其后面的内容」
NSString *newStr2 = [str lastPathComponent];

// 3.删除文件路径的最后一个目录「获取最后一个'/'的内容」
NSString *newStr3 = [str stringByDeletingLastPathComponent];

// 4.给文件添加一个目录「返回 字符串末尾 + / + 指定内容,若给定内容含有 / 则不会重复添加,若给定内容有重复的 / 则只保留一个」
NSString *newStr4 = [str stringByAppendingPathComponent:@"添加的文件名"];

// 5.获取路径中文件的扩展名「从字符串末尾开始 截取第一个 . 后面的内容」
NSString *newStr5 = [str pathExternsion];

// 6.删除路径中文件的扩展名「从字符串末尾开始 删除第一个 . 后面的内容」
NSString *newStr6 = [str stringByDeletingPathExternsion];

// 7.给文件路径添加一个扩展名
NSString *newStr7 = [str stringByAppendingPathExternsion: @"mm"];

2. NSArray「集合类」

  • 存储对象 有序
  • 是 OC数组,只能存放OC对象「对象类型不必一致」
  • 数组里可以装入 字典类
  • 不能存放 nil 值、非OC对象类型「比如:int、struct、enum等」
  • NSArray:不可变有序数组
// NSArray 对象创建
NSArray *array0 = [NSArray arrayWithObject:@"创建含有一个对象的字符串数组"];
NSArray *array1 = @["对象1", @"对象2"]; // 编译器会把本句转换为以下一句「编译器特性」,只返回不可变数组 NSArray
NSArray *array2 = [NSArray arrayWithObjects:@"对象1", @"对象2", nil]; // nil是元素结束的标记,必不可少

// NSArray 元素个数
NSLog(@"%ld", array2.count); // 打印array2的数组元素个数,这里 = 2

// NSArray 元素访问
array2[0]; // 编译器自动转为 以下这句
[array2 objectAtIndex:0];

// NSArray 快速遍历 1
//  id obj代表数组中的每一个元素
for(id obj in array2){ 
    NSUInteger i = [array2 indexOfObject: obj]; // 找出obj元素在数组中的位置
    NSLog(@"%ld - %@", i, obj);
}

// NSArray 快速遍历 2
//  每遍历一个元素就会调用 block,并把 当前元素和索引位置 传给block
//  每次遍历会检测 *stop的值,若为 YES可提前跳出循环
[arrary2 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){

    NSLog(@"%ld - %@", idx, obj);
    if(idx==1) *stop = YES;
}];
  • NSMutableArray:可变有序数组「继承自 NSArray」
// 数组创建
NSMutableArray *array = [NSMutableArray array];

// 元素添加
[array addObject:@"可添加任何对象,但不能添加 基本数据类型"];

// 删除元素
[array removeAllObjects]; // 删除所有元素
[array removeObject:@"删除指定对象"];
[array removeObjectAtIndex:0]; // 删除下标为0的元素,后面元素自动往前移动

3. NSSet「集合类」

  • 存储对象 无序
  • 不能存放 nil 值、非OC对象类型「比如:int、struct、enum等」
  • NSSet: 不可变无序数组
// 无序数组创建
NSSet *set0 = [NSSet setWithObject:@"创建含有一个对象的字符串数组"];
NSSet *set1 = @["对象1", @"对象2"]; // 编译器会把本句转换为以下一句「编译器特性」
NSSet *set2 = [NSSet setWithObjects:@"对象1", @"对象2", nil]; // nil是元素结束的标记,必不可少
// 随机返回一个对象
NSString *str = [set0 anyObject];
// 删除对象
[set0 removeAllObjects]; // 删除所有元素
[set0 removeObject:@"删除指定对象"]; 
  • NSMutableSet: 可变无序数组「继承自 NSSet」

4. NSDictionary「集合类」

  • 不可变、无序集合类
  • 集合类型不必一致
  • 存储 键值对:key —> value「key值唯一,value值不唯一」
  • 如果给出的键 无对应的值,则返回 nil「空」
// 根据键值,创建单元素字典集合对象
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"value" forKey:@"keyName"];
// 创建多元素集合对象 1
NSArray *keys = @[@"keyName",@"address"];
NSArray *objects = @[@"nameValue",@"addressValue"];

NSDictionary *dict = [NSDictionary dictionaryWithObjects:objects forKey:keys];
// 创建多元素集合对象 2
NSDictionary *dict1 = @{@"key1":@"value1", @"key2":@"value2"}; //「编译器特性」只有不可变字典类才会用此方法,自动生成以下代码
NSDictionary *dict1 = [NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1", @"value2",@"key2", nil];

// 根据键,获取值
id objValue1 = dict[@"keyName"]; //「编译器特性」自动生成以下代码
id objValue1 = [dict objectForKey:@"keyName"];

// 获取 键值对的 对数
NSLog(@"%ld", dict1.count); // 这里 打印的值是 2
  • NSMutableDictionary「可变集合类,继承自NSDictionary」
// 创建 空 可变集合类
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// 添加键值对
[dict setObject:"value1" forKey:@"keyName1"];

[dict setObject:"value2" forKey:@"keyName1"]; // 当再次给key赋值时,旧值会被新值覆盖

// 移除键值对
[dict removeObjectForKey:@"keyName1"];

// 打印字典类
NSLog(@"%@", dict);
// 打印效果
NSDictionary{
    keyName1 = value2;
    keyName2 = value2;
}

// 字典遍历 1
NSArray *keys = [dict allKeys]; // 取出字典类所有的 key值作为一个有序的数组
for(int i=0; i<dict.count; i++){
    NSArray *key = keys[i];
    NSArray *obj = dict[key];
    NSLog(@"%@ = %@", key, obj);
}
// 字典遍历 2
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
    NSLog(@"%@ = %@", key, obj); // *stop = YES; 时提前停止
}];

// 数组类嵌套字典类
NSArray *persons = @[
    @{@"key1":@"value1", @"key2":@"value2"}, //字典类 0
    @{@"key3":@"value3", @"key4":@"value4"}  //字典类 1
];
NSLog(@"%@", persons[0]); // 输出 字典类 0
NSLog(@"%@", persons[0][@"key1"]); // 输出 value1

5. 基本数据类型 转换为 OC类

  • 将 基本数据类型 转换为 NSNumber对象「in、char、float、double、short、long、long long」
NSNumber *n = @10; //「编译器特性」自动生成以下代码
NSNumber *n = [NSNumber numberWithInt:10]; // 此外还有:@YES、@'A'、@5.21

// 将 变量 包装成 NSNumber对象
int age = 20;
NSNumber *n1 = @(age); //「编译器特性」自动生成以下代码
NSNumber *n1 = [NSNumber numberWithInt:age]; 

// C语言字符串转换为 OC字符串
char *c = "init_a_C_string";
NSString *oc = @(c);
  • 将 NSNumber对象 转换为 基本数据类型
    <code>int i = [n intValue];</code>
  • NSNumber因为继承了 NSValue 所以能包装基本数据类型为对象
    NSValue 可以将 结构体 转换 为对象
CGPoint *p = CGPointMake(10, 10);
NSValue *v = [NSValue valueWithPoint: p]; // 将结构体 包装成 NSValue对象
NSArray *a = @[v]; // 将包装后的对象放入数组集合中使用

6. NSDate

// 创建时间对象
NSDate *date  = [NSDate date];
// 打印时间「打印的为0时区的时间,不是本时区的时间」
NSLog(@"%@", date);
  • NSDateFormatter 日期格式化类
// 日期 -> 字符串
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// y=年、M=月、d=日、m=分、s=秒、H=时「24小时制」、h=时「12小时制」
formatter.datFormat = @"yyyy-MM-dd HH:mm:ss";  // 设定日期格式
NSString *str = [formatter stringFromDate: date]; // 将 日期 转为 字符串

// 字符串 -> 日期
NSString *time = @"2016-02-13 23:49";

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

formatter.datFormat = @"yyyy-MM-dd HH:mm";  // 设定日期格式
NSDate *date = [formatter dateFromString: time]; // 将 字符串 转为 日期

7. NSCalendar

NSDate *now = [NSDate date];
// 创建日历对象「非单例对象」
NSCanlendar *calendar1 = [NSCanlendar currentCanlendar];
// 利用日历类,从当前 Date对象中 单独获取 年月日时分秒
// components:获取多个枚举类型参数
NSCanlendatUnit type = NSCanlendatUnitYear | NSCanlendatUnitMonth; // 通过 | 链接多个枚举值
NSDateComponents *cmps = [calendar1 components:type fromDate now];
NSLog(@"Year = %ld", cmps.year);

// 比较两个时间的差值
// 设置过去的时间
NSString *ss =@"2016-2-17 4:27:26 +0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormatter = @"yyyy-MM-dd hh:mm:ss Z";
NSDate *date = [formatter dateFromString: ss];
NSDateComponents *cmp1 = [calendar components:type fromDate:date toDate:now options:0];

8. 集合对象的内存管理

  • 若将对象添加到数组中,则数组会对对象进行 一次 retain
  • 数组对象释放,会给数组所有对象发送一条 release 消息
  • 数组移除对象,会给移除的对象发送一条 release 消息

9. copy

定义:利用一个源 文件/对象,产生一个副本 文件/对象
特点:修改副本对象不会引起原对象的改变
方法:

  • copy:创建不可变副本(NSString、NSArray、NSDictionary)
    不会生成新对象,copy的对象是原来的那一个对象「浅拷贝:指针拷贝」
    因为都不可变,所以为了优化内存,不会生成新对象
    使用copy功能的前提:遵守NSCopying协议,实现 copyWithZone:方法
  • MAC平台下,不可变副本使用copy方法,不会 对原来对象进行 一次retain
  • IOS平台下,不可变副本使用copy方法, 对原来对象进行 一次retain
// s 为 不可变字符串
NSString *s = @"Hello";
NSString *s1 = [s copy]; //不会产生新对象「都是不可变,不用另外开辟空间复制,浅复制」
NSLog(@"s的地址:%p s1的地址:%p", s, s1);
  • mutableCopy:创建可变副本(NSMutableString、NSMutableArray、NSMutableDictionary)
    使用 mutableCopy 功能前提:遵守NSMutableCopying协议,实现 mutableCopyWithZone: 方法
    会生成新对象,mutableCopy 的对象是一个新对象「深拷贝:内容拷贝」
  • 由于生成新对象,在任何平台下都 不会 对原来对象进行 一次 retain
    只会对新对象进行 一次 retain
NSMutableString *s2 = @"Hey";
NSMutableString *s3 = [s2 copy]; // 不会产生新对象「浅复制」
NSMutableString *s4 = [s2 mutableCopy]; // 会产生新对象「深复制」
NSLog(@"s2的地址:%p s3的地址:%p s4的地址:%p",s2, s3, s4);
  • copy block 之后引发循环引用
    如果对象中 block 又用到了对象本身,那么为了避免内存泄露,应该将对象修饰为 __block
typedef myBlock 
@interface Person:Object
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) 
@end
int main(){
    __block Person *p = [[Person alloc] init]; // [p retainCount] == 1
    p.name = @"原来对象";
    p.pBlock = ^(){
        NSLog(@"name = %@", p.name); // [p retainCount] == 2
    }
    p.pBlock;
    [p release]; // [p retainCount] == 1
    return 0;
}

自定义类实现 copy 操作

  • 遵守 NSCopying 协议
  • 实现 copyWithZone:该方法返回对象的副本
    创建一个新对象,并设置该对象数据与现有对象一致,返回该对象
  • zone:表示 分配对象需要的内存空间,避免出现堆内存碎片而使用「古老的技术,系统指定,几乎可以忽略」
// Student 父类
@implememt Person
- (id) copyWithZone:(NSZone *)zone{
    // 1.创建一个新对象
    Person *p = [[[self class] allocWithZone:zone] init];
    // 2. 设置当前对象值为新的对象
    p.age =_age;
    p.name = _name;
    // 3. 返回新对象
    return p;
}
@end

// Person 子类
@implememt Student
// 想要子类copy保留子类的属性,必须重写copyWithZone:方法
- (id) copyWithZone:(NSZone *)zone{
    // 1. 使用父类函数,创建副本,设置值
   id obj = [super copyWithZone: zone];
    // 2. 设置子类特有的值
   [obj setHeight:_height];
    // 3. 返回新对象
    return p;
}
@end

相关文章

网友评论

      本文标题:iOS 相关集合函数的使用

      本文链接:https://www.haomeiwen.com/subject/noxodttx.html